commit 6bef87be901a62ffff4a5e52932fdab9c0d8cb27 from: Stefan Sperling date: Tue Sep 11 09:23:44 2018 UTC move object cache out of repository.c to its own file commit - 55da3778cb79bda6ee8eda5f117a838b4fd50a83 commit + 6bef87be901a62ffff4a5e52932fdab9c0d8cb27 blob - e8932c8f9df52141dff8b8cfe9d03e125064fb93 blob + 8ebd171f529c9d6c08c782f240742acb82235dab --- got/Makefile +++ got/Makefile @@ -2,9 +2,10 @@ PROG= got SRCS= got.c blame.c commit_graph.c delta.c diff.c diffoffset.c \ - diffreg.c error.c fileindex.c object.c object_idcache.c \ - object_idset.c object_parse.c opentemp.c path.c pack.c \ - privsep.c reference.c repository.c sha1.c worktree.c inflate.c + diffreg.c error.c fileindex.c object.c object_cache.c \ + object_idcache.c object_idset.c object_parse.c opentemp.c \ + path.c pack.c privsep.c reference.c repository.c sha1.c \ + worktree.c inflate.c CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib \ -DGOT_LIBEXECDIR=${GOT_LIBEXECDIR} blob - /dev/null blob + 871bc3ca8a4a7207189fb3c8f90b89a094fc37ce (mode 644) --- /dev/null +++ lib/got_lib_object_cache.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Stefan Sperling + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +enum got_object_cache_type { + GOT_OBJECT_CACHE_TYPE_OBJ, + GOT_OBJECT_CACHE_TYPE_TREE, + GOT_OBJECT_CACHE_TYPE_COMMIT, +}; + +struct got_object_cache_entry { + struct got_object_id id; + union { + struct got_object *obj; + struct got_tree_object *tree; + struct got_commit_object *commit; + } data; +}; + +struct got_object_cache { + enum got_object_cache_type type; + struct got_object_idcache *idcache; + size_t size; + int cache_hit; + int cache_miss; +}; + +const struct got_error *got_object_cache_init(struct got_object_cache *, + enum got_object_cache_type); +const struct got_error *got_object_cache_add(struct got_object_cache *, + struct got_object_id *, void *); +void *got_object_cache_get(struct got_object_cache *, struct got_object_id *); +void got_object_cache_close(struct got_object_cache *); blob - d663456eb11bc81aa37a87e77507c574b311dcc7 blob + 4d2e819add6d372bea4d03615acfc92b64acad3c --- lib/got_lib_repository.h +++ lib/got_lib_repository.h @@ -17,33 +17,6 @@ #define GOT_PACKIDX_CACHE_SIZE 64 #define GOT_PACK_CACHE_SIZE GOT_PACKIDX_CACHE_SIZE -#define GOT_OBJECT_CACHE_SIZE_OBJ 1024 -#define GOT_OBJECT_CACHE_SIZE_TREE 128 -#define GOT_OBJECT_CACHE_SIZE_COMMIT 512 - -enum got_object_chache_type { - GOT_OBJECT_CACHE_TYPE_OBJ, - GOT_OBJECT_CACHE_TYPE_TREE, - GOT_OBJECT_CACHE_TYPE_COMMIT, -}; - -struct got_object_cache_entry { - struct got_object_id id; - union { - struct got_object *obj; - struct got_tree_object *tree; - struct got_commit_object *commit; - } data; -}; - -struct got_object_cache { - enum got_object_chache_type type; - struct got_object_idcache *idcache; - size_t size; - int cache_hit; - int cache_miss; -}; - struct got_repository { char *path; char *path_git_dir; blob - da1f8b58653dd67775c857702048d3d2aab690f8 blob + 70d904c862876bbd6a22fd646cf6c0fa9be94d6a --- lib/object.c +++ lib/object.c @@ -47,6 +47,8 @@ #include "got_lib_inflate.h" #include "got_lib_object.h" #include "got_lib_privsep.h" +#include "got_lib_object_idcache.h" +#include "got_lib_object_cache.h" #include "got_lib_object_parse.h" #include "got_lib_repository.h" blob - /dev/null blob + 086dcccdf5ebe1fe5035579014d7b1d6bd7c4ab1 (mode 644) --- /dev/null +++ lib/object_cache.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018 Stefan Sperling + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "got_error.h" +#include "got_object.h" + +#include "got_lib_delta.h" +#include "got_lib_inflate.h" +#include "got_lib_object.h" +#include "got_lib_object_idcache.h" +#include "got_lib_object_cache.h" + +#define GOT_OBJECT_CACHE_SIZE_OBJ 1024 +#define GOT_OBJECT_CACHE_SIZE_TREE 128 +#define GOT_OBJECT_CACHE_SIZE_COMMIT 512 + +const struct got_error * +got_object_cache_init(struct got_object_cache *cache, + enum got_object_cache_type type) +{ + size_t size; + + switch (type) { + case GOT_OBJECT_CACHE_TYPE_OBJ: + size = GOT_OBJECT_CACHE_SIZE_OBJ; + break; + case GOT_OBJECT_CACHE_TYPE_TREE: + size = GOT_OBJECT_CACHE_SIZE_TREE; + break; + case GOT_OBJECT_CACHE_TYPE_COMMIT: + size = GOT_OBJECT_CACHE_SIZE_COMMIT; + break; + } + + cache->idcache = got_object_idcache_alloc(size); + if (cache->idcache == NULL) + return got_error_from_errno(); + cache->type = type; + cache->size = size; + return NULL; +} + +const struct got_error * +got_object_cache_add(struct got_object_cache *cache, struct got_object_id *id, void *item) +{ + const struct got_error *err = NULL; + struct got_object_cache_entry *ce; + int nelem; + + nelem = got_object_idcache_num_elements(cache->idcache); + if (nelem >= cache->size) { + err = got_object_idcache_remove_least_used((void **)&ce, + cache->idcache); + if (err) + return err; + switch (cache->type) { + case GOT_OBJECT_CACHE_TYPE_OBJ: + got_object_close(ce->data.obj); + break; + case GOT_OBJECT_CACHE_TYPE_TREE: + got_object_tree_close(ce->data.tree); + break; + case GOT_OBJECT_CACHE_TYPE_COMMIT: + got_object_commit_close(ce->data.commit); + break; + } + free(ce); + } + + ce = calloc(1, sizeof(*ce)); + if (ce == NULL) + return got_error_from_errno(); + memcpy(&ce->id, id, sizeof(ce->id)); + switch (cache->type) { + case GOT_OBJECT_CACHE_TYPE_OBJ: + ce->data.obj = (struct got_object *)item; + break; + case GOT_OBJECT_CACHE_TYPE_TREE: + ce->data.tree = (struct got_tree_object *)item; + break; + case GOT_OBJECT_CACHE_TYPE_COMMIT: + ce->data.commit = (struct got_commit_object *)item; + break; + } + + err = got_object_idcache_add(cache->idcache, id, ce); + if (err) { + if (err->code == GOT_ERR_OBJ_EXISTS) { + free(ce); + err = NULL; + } + } + return err; +} + +void * +got_object_cache_get(struct got_object_cache *cache, struct got_object_id *id) +{ + struct got_object_cache_entry *ce; + + ce = got_object_idcache_get(cache->idcache, id); + if (ce) { + cache->cache_hit++; + switch (cache->type) { + case GOT_OBJECT_CACHE_TYPE_OBJ: + return ce->data.obj; + case GOT_OBJECT_CACHE_TYPE_TREE: + return ce->data.tree; + case GOT_OBJECT_CACHE_TYPE_COMMIT: + return ce->data.commit; + } + } + + cache->cache_miss++; + return NULL; +} + +#if 0 +static void +print_cache_stats(struct got_object_cache *cache, const char *name) +{ + fprintf(stderr, "%s cache: %d elements, %d hits, %d missed\n", + name, got_object_idcache_num_elements(cache->idcache), + cache->cache_hit, cache->cache_miss); +} + +void check_refcount(struct got_object_id *id, void *data, void *arg) +{ + struct got_object_cache *cache = arg; + struct got_object_cache_entry *ce = data; + struct got_object *obj; + struct got_tree_object *tree; + struct got_commit_object *commit; + char *id_str; + + if (got_object_id_str(&id_str, id) != NULL) + return; + + switch (cache->type) { + case GOT_OBJECT_CACHE_TYPE_OBJ: + obj = ce->data.obj; + if (obj->refcnt == 1) + break; + fprintf(stderr, "object %s has %d unclaimed references\n", + id_str, obj->refcnt - 1); + break; + case GOT_OBJECT_CACHE_TYPE_TREE: + tree = ce->data.tree; + if (tree->refcnt == 1) + break; + fprintf(stderr, "tree %s has %d unclaimed references\n", + id_str, tree->refcnt - 1); + break; + case GOT_OBJECT_CACHE_TYPE_COMMIT: + commit = ce->data.commit; + if (commit->refcnt == 1) + break; + fprintf(stderr, "commit %s has %d unclaimed references\n", + id_str, commit->refcnt); + break; + } + free(id_str); +} +#endif + +void +got_object_cache_close(struct got_object_cache *cache) +{ +#if 0 + switch (cache->type) { + case GOT_OBJECT_CACHE_TYPE_OBJ: + print_cache_stats(cache, "object"); + break; + case GOT_OBJECT_CACHE_TYPE_TREE: + print_cache_stats(cache, "tree"); + break; + case GOT_OBJECT_CACHE_TYPE_COMMIT: + print_cache_stats(cache, "commit"); + break; + } + + got_object_idcache_for_each(cache->idcache, check_refcount, cache); +#endif + + if (cache->idcache) { + got_object_idcache_free(cache->idcache); + cache->idcache = NULL; + } + cache->size = 0; +} blob - fc364fdac12e464e94cb9080000d585d44d3d3b1 blob + 091877528d84ffeecce69bcaa5d7a92d7cf41a75 --- lib/object_parse.c +++ lib/object_parse.c @@ -46,6 +46,7 @@ #include "got_lib_pack.h" #include "got_lib_inflate.h" #include "got_lib_object.h" +#include "got_lib_object_cache.h" #include "got_lib_repository.h" #ifndef nitems blob - f0fb85579ae6052de9bd7214f47e96826c6d1577 blob + 682e940922ba11be438043238488405228f75f38 --- lib/repository.c +++ lib/repository.c @@ -46,9 +46,9 @@ #include "got_lib_object.h" #include "got_lib_pack.h" #include "got_lib_privsep.h" -#include "got_lib_repository.h" #include "got_lib_worktree.h" -#include "got_lib_object_idcache.h" +#include "got_lib_object_cache.h" +#include "got_lib_repository.h" #ifndef nitems #define nitems(_a) (sizeof(_a) / sizeof((_a)[0])) @@ -164,62 +164,7 @@ done: free(path_head); return ret; -} - -#ifndef GOT_NO_OBJ_CACHE -static const struct got_error * -cache_add(struct got_object_cache *cache, struct got_object_id *id, void *item) -{ - const struct got_error *err = NULL; - struct got_object_cache_entry *ce; - int nelem; - - nelem = got_object_idcache_num_elements(cache->idcache); - if (nelem >= cache->size) { - err = got_object_idcache_remove_least_used((void **)&ce, - cache->idcache); - if (err) - return err; - switch (cache->type) { - case GOT_OBJECT_CACHE_TYPE_OBJ: - got_object_close(ce->data.obj); - break; - case GOT_OBJECT_CACHE_TYPE_TREE: - got_object_tree_close(ce->data.tree); - break; - case GOT_OBJECT_CACHE_TYPE_COMMIT: - got_object_commit_close(ce->data.commit); - break; - } - free(ce); - } - - ce = calloc(1, sizeof(*ce)); - if (ce == NULL) - return got_error_from_errno(); - memcpy(&ce->id, id, sizeof(ce->id)); - switch (cache->type) { - case GOT_OBJECT_CACHE_TYPE_OBJ: - ce->data.obj = (struct got_object *)item; - break; - case GOT_OBJECT_CACHE_TYPE_TREE: - ce->data.tree = (struct got_tree_object *)item; - break; - case GOT_OBJECT_CACHE_TYPE_COMMIT: - ce->data.commit = (struct got_commit_object *)item; - break; - } - - err = got_object_idcache_add(cache->idcache, id, ce); - if (err) { - if (err->code == GOT_ERR_OBJ_EXISTS) { - free(ce); - err = NULL; - } - } - return err; } -#endif const struct got_error * got_repo_cache_object(struct got_repository *repo, struct got_object_id *id, @@ -227,7 +172,7 @@ got_repo_cache_object(struct got_repository *repo, str { #ifndef GOT_NO_OBJ_CACHE const struct got_error *err = NULL; - err = cache_add(&repo->objcache, id, obj); + err = got_object_cache_add(&repo->objcache, id, obj); if (err) return err; obj->refcnt++; @@ -239,16 +184,7 @@ struct got_object * got_repo_get_cached_object(struct got_repository *repo, struct got_object_id *id) { - struct got_object_cache_entry *ce; - - ce = got_object_idcache_get(repo->objcache.idcache, id); - if (ce) { - repo->objcache.cache_hit++; - return ce->data.obj; - } - - repo->objcache.cache_miss++; - return NULL; + return (struct got_object *)got_object_cache_get(&repo->objcache, id); } const struct got_error * @@ -257,7 +193,7 @@ got_repo_cache_tree(struct got_repository *repo, struc { #ifndef GOT_NO_OBJ_CACHE const struct got_error *err = NULL; - err = cache_add(&repo->treecache, id, tree); + err = got_object_cache_add(&repo->treecache, id, tree); if (err) return err; tree->refcnt++; @@ -269,16 +205,8 @@ struct got_tree_object * got_repo_get_cached_tree(struct got_repository *repo, struct got_object_id *id) { - struct got_object_cache_entry *ce; - - ce = got_object_idcache_get(repo->treecache.idcache, id); - if (ce) { - repo->treecache.cache_hit++; - return ce->data.tree; - } - - repo->treecache.cache_miss++; - return NULL; + return (struct got_tree_object *)got_object_cache_get( + &repo->treecache, id); } const struct got_error * @@ -287,7 +215,7 @@ got_repo_cache_commit(struct got_repository *repo, str { #ifndef GOT_NO_OBJ_CACHE const struct got_error *err = NULL; - err = cache_add(&repo->commitcache, id, commit); + err = got_object_cache_add(&repo->commitcache, id, commit); if (err) return err; @@ -300,16 +228,8 @@ struct got_commit_object * got_repo_get_cached_commit(struct got_repository *repo, struct got_object_id *id) { - struct got_object_cache_entry *ce; - - ce = got_object_idcache_get(repo->commitcache.idcache, id); - if (ce) { - repo->commitcache.cache_hit++; - return ce->data.commit; - } - - repo->commitcache.cache_miss++; - return NULL; + return (struct got_commit_object *)got_object_cache_get( + &repo->commitcache, id); } const struct got_error * @@ -423,31 +343,18 @@ got_repo_open(struct got_repository **repop, const cha repo->privsep_children[i].imsg_fd = -1; } - repo->objcache.type = GOT_OBJECT_CACHE_TYPE_OBJ; - repo->objcache.size = GOT_OBJECT_CACHE_SIZE_OBJ; - repo->objcache.idcache = got_object_idcache_alloc(repo->objcache.size); - if (repo->objcache.idcache == NULL) { - err = got_error_from_errno(); + err = got_object_cache_init(&repo->objcache, + GOT_OBJECT_CACHE_TYPE_OBJ); + if (err) goto done; - } - - repo->treecache.type = GOT_OBJECT_CACHE_TYPE_TREE; - repo->treecache.size = GOT_OBJECT_CACHE_SIZE_TREE; - repo->treecache.idcache = - got_object_idcache_alloc(repo->treecache.size); - if (repo->treecache.idcache == NULL) { - err = got_error_from_errno(); + err = got_object_cache_init(&repo->treecache, + GOT_OBJECT_CACHE_TYPE_TREE); + if (err) goto done; - } - - repo->commitcache.type = GOT_OBJECT_CACHE_TYPE_COMMIT; - repo->commitcache.size = GOT_OBJECT_CACHE_SIZE_COMMIT; - repo->commitcache.idcache = - got_object_idcache_alloc(repo->commitcache.size); - if (repo->commitcache.idcache == NULL) { - err = got_error_from_errno(); + err = got_object_cache_init(&repo->commitcache, + GOT_OBJECT_CACHE_TYPE_COMMIT); + if (err) goto done; - } normpath = got_path_normalize(abspath); if (normpath == NULL) { @@ -483,54 +390,6 @@ done: return err; } -#if 0 -static void -print_cache_stats(struct got_object_cache *cache, const char *name) -{ - fprintf(stderr, "%s cache: %d elements, %d hits, %d missed\n", - name, got_object_idcache_num_elements(cache->idcache), - cache->cache_hit, cache->cache_miss); -} - -void check_refcount(struct got_object_id *id, void *data, void *arg) -{ - struct got_object_cache *cache = arg; - struct got_object_cache_entry *ce = data; - struct got_object *obj; - struct got_tree_object *tree; - struct got_commit_object *commit; - char *id_str; - - if (got_object_id_str(&id_str, id) != NULL) - return; - - switch (cache->type) { - case GOT_OBJECT_CACHE_TYPE_OBJ: - obj = ce->data.obj; - if (obj->refcnt == 1) - break; - fprintf(stderr, "object %s has %d unclaimed references\n", - id_str, obj->refcnt - 1); - break; - case GOT_OBJECT_CACHE_TYPE_TREE: - tree = ce->data.tree; - if (tree->refcnt == 1) - break; - fprintf(stderr, "tree %s has %d unclaimed references\n", - id_str, tree->refcnt - 1); - break; - case GOT_OBJECT_CACHE_TYPE_COMMIT: - commit = ce->data.commit; - if (commit->refcnt == 1) - break; - fprintf(stderr, "commit %s has %d unclaimed references\n", - id_str, commit->refcnt); - break; - } - free(id_str); -} -#endif - const struct got_error * got_repo_close(struct got_repository *repo) { @@ -552,24 +411,9 @@ got_repo_close(struct got_repository *repo) free(repo->path); free(repo->path_git_dir); -#if 0 - print_cache_stats(&repo->objcache, "object"); - print_cache_stats(&repo->treecache, "tree"); - print_cache_stats(&repo->commitcache, "commit"); - got_object_idcache_for_each(repo->objcache.idcache, check_refcount, - &repo->objcache); - got_object_idcache_for_each(repo->treecache.idcache, check_refcount, - &repo->treecache); - got_object_idcache_for_each(repo->commitcache.idcache, check_refcount, - &repo->commitcache); -#endif - - if (repo->objcache.idcache) - got_object_idcache_free(repo->objcache.idcache); - if (repo->treecache.idcache) - got_object_idcache_free(repo->treecache.idcache); - if (repo->commitcache.idcache) - got_object_idcache_free(repo->commitcache.idcache); + got_object_cache_close(&repo->objcache); + got_object_cache_close(&repo->treecache); + got_object_cache_close(&repo->commitcache); for (i = 0; i < nitems(repo->privsep_children); i++) { if (repo->privsep_children[i].imsg_fd == -1) blob - 2b4ff87db84d484f641901960fee64e2c10a7483 blob + f2a6a6e7f0c92f9293824327b06abd22fd96eb18 --- regress/idset/Makefile +++ regress/idset/Makefile @@ -2,7 +2,7 @@ PROG = idset_test SRCS = error.c object.c privsep.c sha1.c pack.c inflate.c path.c opentemp.c \ - delta.c repository.c reference.c worktree.c fileindex.c \ + delta.c repository.c reference.c worktree.c fileindex.c object_cache.c \ object_idcache.c object_idset.c object_parse.c idset_test.c CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib blob - babe3897b60847cc3b147a3c7ed92e9764521a5e blob + a1659fdf01d1a4f3b580149ba7a7b6085bf74947 --- regress/repository/Makefile +++ regress/repository/Makefile @@ -1,10 +1,10 @@ .PATH:${.CURDIR}/../../lib PROG = repository_test -SRCS = path.c repository.c error.c reference.c object.c object_idcache.c \ - object_idset.c object_parse.c opentemp.c sha1.c diff.c diffreg.c \ - pack.c privsep.c delta.c fileindex.c worktree.c inflate.c \ - repository_test.c +SRCS = path.c repository.c error.c reference.c object.c object_cache.c \ + object_idcache.c object_idset.c object_parse.c opentemp.c sha1.c \ + diff.c diffreg.c pack.c privsep.c delta.c fileindex.c worktree.c \ + inflate.c repository_test.c CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib \ -DGOT_LIBEXECDIR=${GOT_LIBEXECDIR} blob - c4b341e66ed438112421e3ff381e37f61759a950 blob + 325c30c3d1008e148dd347d12d236e406a822a8a --- regress/worktree/Makefile +++ regress/worktree/Makefile @@ -1,9 +1,9 @@ .PATH:${.CURDIR}/../../lib PROG = worktree_test -SRCS = worktree.c repository.c object.c object_idcache.c object_idset.c \ - object_parse.c opentemp.c path.c error.c reference.c sha1.c pack.c \ - privsep.c delta.c inflate.c fileindex.c worktree_test.c +SRCS = worktree.c repository.c object.c object_cache.c object_idcache.c \ + object_idset.c object_parse.c opentemp.c path.c error.c reference.c \ + sha1.c pack.c privsep.c delta.c inflate.c fileindex.c worktree_test.c CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib \ -DGOT_LIBEXECDIR=${GOT_LIBEXECDIR} blob - ae6ee6919a93d2cc6297ebeea7282af4b325ba5b blob + 8b38788f426c570b7a06035a85bd800f07ef7cc3 --- tog/Makefile +++ tog/Makefile @@ -2,10 +2,10 @@ PROG= tog SRCS= tog.c blame.c commit_graph.c delta.c diff.c diffoffset.c \ - diffreg.c error.c fileindex.c object.c object_idcache.c \ - object_idset.c object_parse.c opentemp.c path.c pack.c \ - privsep.c reference.c repository.c sha1.c worktree.c \ - utf8.c inflate.c + diffreg.c error.c fileindex.c object.c object_cache.c \ + object_idcache.c object_idset.c object_parse.c opentemp.c \ + path.c pack.c privsep.c reference.c repository.c sha1.c \ + worktree.c utf8.c inflate.c CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib \ -DGOT_LIBEXECDIR=${GOT_LIBEXECDIR}