Skip to content

Commit

Permalink
use find_library for finding up pkgconf libs
Browse files Browse the repository at this point in the history
This makes pkgconf and cc.find_library use the same code path
  • Loading branch information
annacrombie committed Dec 20, 2024
1 parent ee316de commit d205c17
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 123 deletions.
8 changes: 8 additions & 0 deletions include/functions/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#define MUON_FUNCTIONS_COMPILER_H
#include "lang/func_lookup.h"


enum find_library_flag {
find_library_flag_only_static = 1 << 0,
find_library_flag_prefer_static = 1 << 0,
};

obj find_library(struct workspace *wk, const char *name, obj libdirs, enum find_library_flag flags);

extern const struct func_impl impl_tbl_compiler[];
extern const struct func_impl impl_tbl_compiler_internal[];
#endif
86 changes: 8 additions & 78 deletions src/external/libpkgconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include <stdlib.h>
#include <string.h>

#include "buf_size.h"
#include "external/libpkgconf.h"
#include "functions/compiler.h"
#include "lang/object.h"
#include "lang/workspace.h"
#include "log.h"
Expand Down Expand Up @@ -121,82 +121,6 @@ struct pkgconf_lookup_ctx {
bool is_static;
};

struct find_lib_path_ctx {
bool is_static;
bool found;
const char *name;
struct sbuf *buf, *name_buf;
};

static bool
check_lib_path(struct workspace *wk, struct find_lib_path_ctx *ctx, const char *lib_path)
{
enum ext { ext_a, ext_so, ext_dll_a, ext_count };
static const char *ext[] = { [ext_a] = ".a", [ext_so] = ".so", [ext_dll_a] = ".dll.a" };
static const uint8_t ext_order_static[] = { ext_a, ext_so, ext_dll_a },
ext_order_dynamic[] = { ext_so, ext_dll_a, ext_a }, *ext_order;

if (ctx->is_static) {
ext_order = ext_order_static;
} else {
ext_order = ext_order_dynamic;
}

uint32_t i;

/*
* TODO
* on Windows, ld is searching for several library names when direct
* linking to a DLL, not necessarly 'lib***.dll.a".
* Also, ld is searching for '*.dll' in $prefix/bin, not $prefix/lib
* See https://sourceware.org/binutils/docs/ld/WIN32.html
* section "direct linking to a dll"
*/
for (i = 0; i < ext_count; ++i) {
sbuf_clear(ctx->name_buf);
sbuf_pushf(wk, ctx->name_buf, "lib%s%s", ctx->name, ext[ext_order[i]]);

path_join(wk, ctx->buf, lib_path, ctx->name_buf->buf);

if (fs_file_exists(ctx->buf->buf)) {
ctx->found = true;
return true;
}
}

return false;
}

static enum iteration_result
find_lib_path_iter(struct workspace *wk, void *_ctx, obj val_id)
{
struct find_lib_path_ctx *ctx = _ctx;

if (check_lib_path(wk, ctx, get_cstr(wk, val_id))) {
return ir_done;
}

return ir_cont;
}

static obj
find_lib_path(pkgconf_client_t *client, struct pkgconf_lookup_ctx *ctx, const char *name)
{
SBUF(buf);
SBUF(name_buf);

struct find_lib_path_ctx find_lib_path_ctx
= { .buf = &buf, .name_buf = &name_buf, .name = name, .is_static = ctx->is_static };

if (!obj_array_foreach(ctx->wk, ctx->libdirs, &find_lib_path_ctx, find_lib_path_iter)) {
return 0;
} else if (!find_lib_path_ctx.found) {
return 0;
}

return sbuf_into_str(ctx->wk, &buf);
}

static bool
apply_and_collect(pkgconf_client_t *client, pkgconf_pkg_t *world, void *_ctx, int maxdepth)
{
Expand Down Expand Up @@ -236,7 +160,12 @@ apply_and_collect(pkgconf_client_t *client, pkgconf_pkg_t *world, void *_ctx, in
break;
case 'l': {
obj path;
if ((path = find_lib_path(client, ctx, frag->data))) {
enum find_library_flag flags = 0;
if (ctx->is_static) {
flags |= find_library_flag_prefer_static;
}

if ((path = find_library(ctx->wk, frag->data, ctx->libdirs, flags))) {
if (!obj_array_in(ctx->wk, ctx->info->libs, str)) {
L("library '%s' found for dependency '%s'",
get_cstr(ctx->wk, path),
Expand Down Expand Up @@ -300,6 +229,7 @@ muon_pkgconf_define(struct workspace *wk, const char *key, const char *value)
bool
muon_pkgconf_lookup(struct workspace *wk, obj name, bool is_static, struct pkgconf_info *info)
{
L("looking up: %d", is_static);
if (!pkgconf_ctx.init) {
if (!muon_pkgconf_init(wk)) {
return false;
Expand Down
111 changes: 66 additions & 45 deletions src/functions/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1938,42 +1938,69 @@ func_compiler_get_argument_syntax(struct workspace *wk, obj self, obj *res)
return true;
}

struct compiler_find_library_ctx {
struct sbuf *path;
obj lib_name;
bool only_static;
bool found;
};
obj
find_library(struct workspace *wk, const char *name, obj libdirs, enum find_library_flag flags)
{
enum ext {
ext_a,
ext_so,
ext_dylib,
ext_dll_a,
ext_count,
};
static const char *ext[] = {
[ext_a] = ".a",
[ext_so] = ".so",
[ext_dylib] = ".dylib",
[ext_dll_a] = ".dll.a",
};

static enum iteration_result
compiler_find_library_iter(struct workspace *wk, void *_ctx, obj libdir)
{
struct compiler_find_library_ctx *ctx = _ctx;
#define EXT_DYNAMIC ext_so, ext_dylib, ext_dll_a
#define EXT_STATIC ext_a, ext_dll_a

static const enum ext ext_order_static_preferred[] = { EXT_STATIC, EXT_DYNAMIC },
ext_order_static_only[] = { EXT_STATIC },
ext_order_dynamic_preferred[] = { EXT_DYNAMIC, EXT_STATIC };

#undef EXT_STATIC
#undef EXT_DYNAMIC

static const char *pref[] = { "", "lib" };
const enum ext *ext_order;
uint32_t ext_order_len;

SBUF(path);
SBUF(lib);
static const char *pref[] = { "", "lib", NULL };
const char *suf[] = { ".so", ".a", NULL };

if (ctx->only_static) {
suf[0] = ".a";
suf[1] = NULL;
if (flags & find_library_flag_only_static) {
ext_order = ext_order_static_only;
ext_order_len = ARRAY_LEN(ext_order_static_only);
} else if (flags & find_library_flag_prefer_static) {
ext_order = ext_order_static_preferred;
ext_order_len = ARRAY_LEN(ext_order_static_preferred);
} else {
ext_order = ext_order_dynamic_preferred;
ext_order_len = ARRAY_LEN(ext_order_dynamic_preferred);
}

uint32_t i, j;
for (i = 0; suf[i]; ++i) {
for (j = 0; pref[j]; ++j) {
sbuf_clear(&lib);
sbuf_pushf(wk, &lib, "%s%s%s", pref[j], get_cstr(wk, ctx->lib_name), suf[i]);
obj libdir;
obj_array_for(wk, libdirs, libdir) {
for (i = 0; i < ext_order_len; ++i) {
for (j = 0; j < ARRAY_LEN(pref); ++j) {
sbuf_clear(&lib);
sbuf_pushf(wk, &lib, "%s%s%s", pref[j], name, ext[ext_order[i]]);

path_join(wk, ctx->path, get_cstr(wk, libdir), lib.buf);
path_join(wk, &path, get_cstr(wk, libdir), lib.buf);

if (fs_file_exists(ctx->path->buf)) {
ctx->found = true;
return ir_done;
if (fs_file_exists(path.buf)) {
return sbuf_into_str(wk, &path);
}
}
}
}

return ir_cont;
return 0;
}

struct compiler_find_library_check_headers_ctx {
Expand Down Expand Up @@ -2069,32 +2096,27 @@ func_compiler_find_library(struct workspace *wk, obj self, obj *res)
get_option_value(wk, current_project(wk), "prefer_static", &akw[kw_static].val);
}

struct compiler_find_library_ctx ctx = {
.path = &library_path,
.lib_name = an[0].val,
.only_static = get_obj_bool(wk, akw[kw_static].val),
};
enum find_library_flag flags = 0;
if (get_obj_bool(wk, akw[kw_static].val)) {
flags |= find_library_flag_only_static;
}

struct obj_compiler *comp = get_obj_compiler(wk, self);

obj found = 0;
bool found_from_dirs_kw = false;

if (akw[kw_dirs].set) {
if (!obj_array_foreach(wk, akw[kw_dirs].val, &ctx, compiler_find_library_iter)) {
return false;
}

if (ctx.found) {
if ((found = find_library(wk, get_cstr(wk, an[0].val), akw[kw_dirs].val, flags))) {
found_from_dirs_kw = true;
}
}

if (!ctx.found) {
if (!obj_array_foreach(wk, comp->libdirs, &ctx, compiler_find_library_iter)) {
return false;
}
if (!found) {
found = find_library(wk, get_cstr(wk, an[0].val), comp->libdirs, flags);
}

if (ctx.found && akw[kw_has_headers].set) {
if (found && akw[kw_has_headers].set) {
struct args_kw header_kwargs[cc_kwargs_count + 1] = {
[cc_kw_args] = akw[kw_header_args],
[cc_kw_dependencies] = akw[kw_header_dependencies],
Expand All @@ -2116,11 +2138,11 @@ func_compiler_find_library(struct workspace *wk, obj self, obj *res)
wk, akw[kw_has_headers].val, &check_headers_ctx, compiler_find_library_check_headers_iter);

if (!check_headers_ctx.ok) {
ctx.found = false;
found = false;
}
}

if (!ctx.found) {
if (!found) {
if (requirement == requirement_required) {
vm_error_at(wk, an[0].node, "library not found");
return false;
Expand All @@ -2133,15 +2155,14 @@ func_compiler_find_library(struct workspace *wk, obj self, obj *res)
return true;
}

compiler_log(wk, self, "found library '%s' at '%s'", get_cstr(wk, an[0].val), ctx.path->buf);
compiler_log(wk, self, "found library '%s' at '%s'", get_cstr(wk, an[0].val), get_cstr(wk, found));
dep->flags |= dep_flag_found;
make_obj(wk, &dep->dep.link_with, obj_array);
obj path_str = make_str(wk, ctx.path->buf);
obj_array_push(wk, dep->dep.link_with, path_str);
obj_array_push(wk, dep->dep.link_with, found);

if (found_from_dirs_kw) {
make_obj(wk, &dep->dep.rpath, obj_array);
obj_array_push(wk, dep->dep.rpath, path_str);
obj_array_push(wk, dep->dep.rpath, found);
}

dep->dep.link_language = comp->lang;
Expand Down

0 comments on commit d205c17

Please sign in to comment.