M bootstrap.sh => bootstrap.sh +0 -1
@@ 92,7 92,6 @@ cat \
src/machine_file.c \
src/main.c \
src/opts.c \
- src/platform/dirs.c \
src/platform/filesystem.c \
src/platform/mem.c \
src/platform/path.c \
M include/backend/common_args.h => include/backend/common_args.h +9 -3
@@ 6,10 6,16 @@
bool setup_compiler_args(struct workspace *wk, const struct obj *tgt,
const struct project *proj, obj include_dirs, obj dep_args,
obj *joined_args);
+
+struct setup_linker_args_ctx {
+ enum linker_type linker;
+ enum compiler_language link_lang;
+ struct dep_args_ctx *args;
+ obj implicit_deps;
+};
+
void setup_linker_args(struct workspace *wk, const struct project *proj,
- const struct obj *tgt, enum linker_type linker,
- enum compiler_language link_lang,
- obj rpaths, obj link_args, obj link_with);
+ const struct obj *tgt, struct setup_linker_args_ctx *ctx);
struct setup_compiler_args_includes_ctx {
obj args;
M include/compilers.h => include/compilers.h +1 -0
@@ 77,6 77,7 @@ struct compiler {
struct linker {
struct {
+ compiler_get_arg_func_1s lib;
compiler_get_arg_func_0 as_needed;
compiler_get_arg_func_0 no_undefined;
compiler_get_arg_func_0 start_group;
M include/external/libpkgconf.h => include/external/libpkgconf.h +1 -1
@@ 7,7 7,7 @@
struct pkgconf_info {
char version[MAX_VERSION_LEN + 1];
- uint32_t includes, libs;
+ obj includes, libs, not_found_libs, link_args, compile_args;
};
extern const bool have_libpkgconf;
M include/functions/dependency.h => include/functions/dependency.h +6 -1
@@ 3,7 3,12 @@
#include "functions/common.h"
struct dep_args_ctx {
- obj compile_args, include_dirs, link_with, link_args, rpath;
+ obj compile_args,
+ include_dirs,
+ link_with,
+ link_with_not_found,
+ link_args,
+ rpath;
bool relativize, recursive;
};
M include/lang/object.h => include/lang/object.h +2 -0
@@ 161,6 161,7 @@ struct obj {
obj name; // obj_string
obj version; // obj_string
obj link_with; // obj_array
+ obj link_with_not_found; // obj_array
obj link_args; // obj_array
obj include_directories; // obj_array
obj variables; // obj_dict
@@ 201,6 202,7 @@ struct obj {
struct {
obj name;
obj ver;
+ obj libdirs;
enum compiler_type type;
enum compiler_language lang;
} compiler;
D include/platform/dirs.h => include/platform/dirs.h +0 -4
@@ 1,4 0,0 @@
-#ifndef MUON_PLATFORM_DIRS_H
-#define MUON_PLATFORM_DIRS_H
-extern const char *libdirs[];
-#endif
M src/backend/common_args.c => src/backend/common_args.c +38 -28
@@ 6,6 6,7 @@
#include "args.h"
#include "backend/common_args.h"
#include "functions/default/options.h"
+#include "functions/dependency.h"
#include "log.h"
#include "platform/filesystem.h"
#include "platform/path.h"
@@ 287,17 288,12 @@ setup_compiler_args(struct workspace *wk, const struct obj *tgt,
return true;
}
-struct setup_linker_args_ctx {
- enum linker_type linker;
- obj link_args;
-};
-
static enum iteration_result
process_rpath_iter(struct workspace *wk, void *_ctx, obj v)
{
struct setup_linker_args_ctx *ctx = _ctx;
- push_args(wk, ctx->link_args, linkers[ctx->linker].args.rpath(get_cstr(wk, v)));
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.rpath(get_cstr(wk, v)));
return ir_cont;
}
@@ 320,51 316,65 @@ setup_optional_b_args_linker(struct workspace *wk, const struct project *proj,
return true;
}
+static enum iteration_result
+push_not_found_lib_iter(struct workspace *wk, void *_ctx, obj v)
+{
+ struct setup_linker_args_ctx *ctx = _ctx;
+
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.lib(get_cstr(wk, v)));
+ return ir_cont;
+}
+
void
setup_linker_args(struct workspace *wk, const struct project *proj,
- const struct obj *tgt, enum linker_type linker,
- enum compiler_language link_lang,
- obj rpaths, obj link_args, obj link_with)
+ const struct obj *tgt, struct setup_linker_args_ctx *ctx)
{
- struct setup_linker_args_ctx ctx = {
- .linker = linker,
- .link_args = link_args,
- };
+ obj link_with;
+ obj_array_dedup(wk, ctx->args->link_with, &link_with);
+ ctx->args->link_with = link_with;
- push_args(wk, link_args, linkers[linker].args.as_needed());
- push_args(wk, link_args, linkers[linker].args.no_undefined());
+ obj link_with_not_found;
+ obj_array_dedup(wk, ctx->args->link_with_not_found, &link_with_not_found);
+ ctx->args->link_with_not_found = link_with_not_found;
+
+ make_obj(wk, &ctx->implicit_deps, obj_array);
+
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.as_needed());
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.no_undefined());
if (proj) {
if (tgt->dat.tgt.flags & build_tgt_flag_export_dynamic) {
- push_args(wk, link_args, linkers[linker].args.export_dynamic());
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.export_dynamic());
}
- setup_optional_b_args_linker(wk, proj, link_args, linker);
+ setup_optional_b_args_linker(wk, proj, ctx->args->link_args, ctx->linker);
/* global args */
obj global_args, global_args_dup;
- if (obj_dict_geti(wk, wk->global_link_args, link_lang, &global_args)) {
+ if (obj_dict_geti(wk, wk->global_link_args, ctx->link_lang, &global_args)) {
obj_array_dup(wk, global_args, &global_args_dup);
- obj_array_extend(wk, link_args, global_args_dup);
+ obj_array_extend(wk, ctx->args->link_args, global_args_dup);
}
/* project args */
obj proj_args, proj_args_dup;
- if (obj_dict_geti(wk, proj->link_args, link_lang, &proj_args)) {
+ if (obj_dict_geti(wk, proj->link_args, ctx->link_lang, &proj_args)) {
obj_array_dup(wk, proj_args, &proj_args_dup);
- obj_array_extend(wk, link_args, proj_args_dup);
+ obj_array_extend(wk, ctx->args->link_args, proj_args_dup);
}
}
- obj_array_foreach(wk, rpaths, &ctx, process_rpath_iter);
+ obj_array_foreach(wk, ctx->args->rpath, ctx, process_rpath_iter);
+
+ if (get_obj(wk, ctx->args->link_with)->dat.arr.len) {
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.start_group());
- if (get_obj(wk, link_with)->dat.arr.len) {
- push_args(wk, link_args, linkers[linker].args.start_group());
+ obj dup;
+ obj_array_dup(wk, ctx->args->link_with, &dup);
+ obj_array_extend(wk, ctx->args->link_args, dup);
- obj arr;
- obj_array_dup(wk, link_with, &arr);
- obj_array_extend(wk, link_args, arr);
+ obj_array_foreach(wk, ctx->args->link_with_not_found, ctx, push_not_found_lib_iter);
- push_args(wk, link_args, linkers[linker].args.end_group());
+ push_args(wk, ctx->args->link_args, linkers[ctx->linker].args.end_group());
}
}
M src/backend/ninja/build_target.c => src/backend/ninja/build_target.c +8 -6
@@ 285,15 285,17 @@ ninja_write_build_tgt(struct workspace *wk, const struct project *proj, obj tgt_
obj implicit_deps = 0;
if (tgt->dat.tgt.type == tgt_executable) {
- obj link_with;
- obj_array_dedup(wk, ctx.args.link_with, &link_with);
+ struct setup_linker_args_ctx sctx = {
+ .linker = linker,
+ .link_lang = ctx.link_language,
+ .args = &ctx.args
+ };
+
+ setup_linker_args(wk, ctx.proj, tgt, &sctx);
if (get_obj(wk, ctx.args.link_with)->dat.arr.len) {
- implicit_deps = str_join(wk, make_str(wk, " | "), join_args_ninja(wk, link_with));
+ implicit_deps = str_join(wk, make_str(wk, " | "), join_args_ninja(wk, ctx.args.link_with));
}
-
- setup_linker_args(wk, ctx.proj, tgt, linker, ctx.link_language,
- ctx.args.rpath, ctx.args.link_args, link_with);
}
const char *linker_type, *link_args;
M src/compilers.c => src/compilers.c +70 -2
@@ 148,6 148,62 @@ detection_over:
return true;
}
+static bool
+compiler_get_libdirs(struct workspace *wk, struct obj *comp)
+{
+ struct run_cmd_ctx cmd_ctx = { 0 };
+ if (!run_cmd(&cmd_ctx, get_cstr(wk, comp->dat.compiler.name), (const char *[]){
+ get_cstr(wk, comp->dat.compiler.name), "--print-search-dirs", NULL,
+ }, NULL) || cmd_ctx.status) {
+ goto done;
+ }
+
+ const char *key = "libraries: ";
+ char *s, *e;
+ bool beginning_of_line = true;
+ for (s = cmd_ctx.out.buf; *s; ++s) {
+ if (beginning_of_line && strncmp(s, key, strlen(key)) == 0) {
+ s += strlen(key);
+ if (*s == '=') {
+ ++s;
+ }
+
+ e = strchr(s, '\n');
+
+ struct str str = {
+ .s = s,
+ .len = e ? (uint32_t)(e - s) : strlen(s),
+ };
+
+ comp->dat.compiler.libdirs = str_split(wk, &str, &WKSTR(":"));
+ goto done;
+ }
+
+ beginning_of_line = *s == '\n';
+ }
+
+done:
+ run_cmd_ctx_destroy(&cmd_ctx);
+
+ if (!comp->dat.compiler.libdirs) {
+ const char *libdirs[] = {
+ "/usr/lib",
+ "/usr/local/lib",
+ "/lib",
+ NULL
+ };
+
+ make_obj(wk, &comp->dat.compiler.libdirs, obj_array);
+
+ uint32_t i;
+ for (i = 0; libdirs[i]; ++i) {
+ obj_array_push(wk, comp->dat.compiler.libdirs, make_str(wk, libdirs[i]));
+ }
+ }
+
+ return true;
+}
+
bool
compiler_detect(struct workspace *wk, uint32_t *comp, enum compiler_language lang)
{
@@ 174,7 230,9 @@ compiler_detect(struct workspace *wk, uint32_t *comp, enum compiler_language lan
return false;
}
- get_obj(wk, *comp)->dat.compiler.lang = lang;
+ struct obj *compiler = get_obj(wk, *comp);
+ compiler_get_libdirs(wk, compiler);
+ compiler->dat.compiler.lang = lang;
return true;
default:
assert(false);
@@ 483,6 541,15 @@ build_compilers(void)
}
static const struct args *
+linker_posix_args_lib(const char *s)
+{
+ COMPILER_ARGS({ "-l", NULL });
+ argv[1] = s;
+
+ return &args;
+}
+
+static const struct args *
linker_gcc_args_as_needed(void)
{
COMPILER_ARGS({ "-Wl,--as-needed" });
@@ 505,7 572,6 @@ linker_gcc_args_start_group(void)
return &args;
}
-
static const struct args *
linker_gcc_args_end_group(void)
{
@@ 562,6 628,7 @@ build_linkers(void)
/* linkers */
struct linker empty = {
.args = {
+ .lib = compiler_arg_empty_1s,
.as_needed = compiler_arg_empty_0,
.no_undefined = compiler_arg_empty_0,
.start_group = compiler_arg_empty_0,
@@ 576,6 643,7 @@ build_linkers(void)
};
struct linker posix = empty;
+ posix.args.lib = linker_posix_args_lib;
struct linker gcc = posix;
gcc.args.as_needed = linker_gcc_args_as_needed;
M src/external/libpkgconf.c => src/external/libpkgconf.c +14 -12
@@ 8,7 8,6 @@
#include "lang/object.h"
#include "lang/workspace.h"
#include "log.h"
-#include "platform/dirs.h"
#include "platform/filesystem.h"
#include "platform/path.h"
@@ 23,7 22,7 @@ static bool init = false;
static bool
error_handler(const char *msg, const pkgconf_client_t *client, const void *data)
{
- /* log_plain("%s", msg); */
+ L("libpkgconf: %s", msg);
return true;
}
@@ 79,8 78,8 @@ struct pkgconf_lookup_ctx {
apply_func apply_func;
struct workspace *wk;
struct pkgconf_info *info;
- uint32_t libdirs;
- uint32_t name;
+ obj libdirs;
+ obj name;
bool is_static;
};
@@ 109,7 108,6 @@ check_lib_path(struct find_lib_path_ctx *ctx, const char *lib_path)
uint32_t i;
char name[PATH_MAX];
-
for (i = 0; i < ext_count; ++i) {
snprintf(name, PATH_MAX - 1, "lib%s%s", ctx->name, ext[ext_order[i]]);
@@ 209,14 207,15 @@ apply_and_collect(pkgconf_client_t *client, pkgconf_pkg_t *world, void *_ctx, in
obj_array_push(ctx->wk, ctx->info->libs, str);
}
} else {
- LOG_E("library '%s' not found for dependency '%s'", frag->data, get_cstr(ctx->wk, ctx->name));
- return false;
+ LOG_W("library '%s' not found for dependency '%s'", frag->data, get_cstr(ctx->wk, ctx->name));
+ obj_array_push(ctx->wk, ctx->info->not_found_libs, make_str(ctx->wk, frag->data));
}
break;
}
default:
if (frag->type) {
- L("skipping unknown pkgconf fragment: -%c '%s'", frag->type, frag->data);
+ obj_array_push(ctx->wk, ctx->info->compile_args,
+ make_strf(ctx->wk, "-%c%s", frag->type, frag->data));
} else {
L("skipping null pkgconf fragment: '%s'", frag->data);
}
@@ 270,14 269,17 @@ muon_pkgconf_lookup(struct workspace *wk, uint32_t name, bool is_static, struct
goto ret;
}
+ make_obj(wk, &info->compile_args, obj_array);
+ make_obj(wk, &info->link_args, obj_array);
make_obj(wk, &info->includes, obj_array);
make_obj(wk, &info->libs, obj_array);
+ make_obj(wk, &info->not_found_libs, obj_array);
make_obj(wk, &ctx.libdirs, obj_array);
- uint32_t i;
- for (i = 0; libdirs[i]; ++i) {
- obj_array_push(wk, ctx.libdirs, make_str(wk, libdirs[i]));
- }
+ /* uint32_t i; */
+ /* for (i = 0; libdirs[i]; ++i) { */
+ /* obj_array_push(wk, ctx.libdirs, make_str(wk, libdirs[i])); */
+ /* } */
ctx.apply_func = pkgconf_pkg_libs;
if (!pkgconf_queue_apply(&client, &pkgq, apply_and_collect, maxdepth, &ctx)) {
M src/functions/compiler.c => src/functions/compiler.c +51 -29
@@ 14,7 14,6 @@
#include "functions/dependency.h"
#include "lang/interpreter.h"
#include "log.h"
-#include "platform/dirs.h"
#include "platform/filesystem.h"
#include "platform/path.h"
#include "platform/run_cmd.h"
@@ 114,8 113,13 @@ compiler_check(struct workspace *wk, struct compiler_check_opts *opts,
return false;
}
- setup_linker_args(wk, NULL, NULL, compilers[t].linker,
- comp->dat.compiler.lang, da_ctx.rpath, da_ctx.link_args, da_ctx.link_with);
+ struct setup_linker_args_ctx sctx = {
+ .linker = compilers[t].linker,
+ .link_lang = comp->dat.compiler.lang,
+ .args = &da_ctx
+ };
+
+ setup_linker_args(wk, NULL, NULL, &sctx);
obj_array_extend(wk, compiler_args, da_ctx.link_args);
}
@@ 986,8 990,38 @@ func_compiler_get_id(struct workspace *wk, uint32_t rcvr, uint32_t args_node, ui
return true;
}
+struct compiler_find_library_ctx {
+ char path[PATH_MAX];
+ obj lib_name;
+ bool found;
+};
+
+static enum iteration_result
+compiler_find_library_iter(struct workspace *wk, void *_ctx, obj libdir)
+{
+ struct compiler_find_library_ctx *ctx = _ctx;
+ char lib[PATH_MAX];
+ static const char *suf[] = { "so", "a", NULL };
+
+ uint32_t i;
+ for (i = 0; suf[i]; ++i) {
+ snprintf(lib, PATH_MAX, "lib%s.%s", get_cstr(wk, ctx->lib_name), suf[i]);
+
+ if (!path_join(ctx->path, PATH_MAX, get_cstr(wk, libdir), lib)) {
+ return false;
+ }
+
+ if (fs_file_exists(ctx->path)) {
+ ctx->found = true;
+ return ir_done;
+ }
+ }
+
+ return ir_cont;
+}
+
static bool
-func_compiler_find_library(struct workspace *wk, uint32_t _, uint32_t args_node, uint32_t *obj)
+func_compiler_find_library(struct workspace *wk, obj rcvr, uint32_t args_node, obj *res)
{
struct args_norm an[] = { { obj_string }, ARG_TYPE_NULL };
enum kwargs {
@@ 1012,32 1046,20 @@ func_compiler_find_library(struct workspace *wk, uint32_t _, uint32_t args_node,
}
if (requirement == requirement_skip) {
- make_obj(wk, obj, obj_external_library)->dat.external_library.found = false;
+ make_obj(wk, res, obj_external_library)->dat.external_library.found = false;
return true;
}
- bool found = false;
- char lib[PATH_MAX], path[PATH_MAX];
- const char *suf[] = { "so", "a", NULL };
-
- uint32_t i, j;
- for (i = 0; libdirs[i]; ++i) {
- for (j = 0; suf[j]; ++j) {
- snprintf(lib, PATH_MAX, "lib%s.%s", get_cstr(wk, an[0].val), suf[j]);
-
- if (!path_join(path, PATH_MAX, libdirs[i], lib)) {
- return false;
- }
+ struct compiler_find_library_ctx ctx = {
+ .lib_name = an[0].val
+ };
+ struct obj *comp = get_obj(wk, rcvr);
- if (fs_file_exists(path)) {
- found = true;
- goto done;
- }
- }
+ if (!obj_array_foreach(wk, comp->dat.compiler.libdirs, &ctx, compiler_find_library_iter)) {
+ return false;
}
-done:
- if (!found) {
+ if (!ctx.found) {
if (requirement == requirement_required) {
interp_error(wk, an[0].node, "library not found");
return false;
@@ 1045,15 1067,15 @@ done:
LOG_W("library '%s' not found", get_cstr(wk, an[0].val));
if (akw[kw_disabler].set && get_obj(wk, akw[kw_disabler].val)->dat.boolean) {
- *obj = disabler_id;
+ *res = disabler_id;
} else {
- make_obj(wk, obj, obj_external_library)->dat.external_library.found = false;
+ make_obj(wk, res, obj_external_library)->dat.external_library.found = false;
}
} else {
- LOG_I("found library '%s' at '%s'", get_cstr(wk, an[0].val), path);
- struct obj *external_library = make_obj(wk, obj, obj_external_library);
+ LOG_I("found library '%s' at '%s'", get_cstr(wk, an[0].val), ctx.path);
+ struct obj *external_library = make_obj(wk, res, obj_external_library);
external_library->dat.external_library.found = true;
- external_library->dat.external_library.full_path = make_str(wk, path);
+ external_library->dat.external_library.full_path = make_str(wk, ctx.path);
}
return true;
M src/functions/default/dependency.c => src/functions/default/dependency.c +3 -0
@@ 129,7 129,10 @@ get_dependency_pkgconfig(struct workspace *wk, struct dep_lookup_ctx *ctx, bool
dep->dat.dep.version = ver_str;
dep->dat.dep.flags |= dep_flag_found | dep_flag_pkg_config;
dep->dat.dep.link_with = info.libs;
+ dep->dat.dep.link_with_not_found = info.not_found_libs;
dep->dat.dep.include_directories = info.includes;
+ dep->dat.dep.compile_args = info.compile_args;
+ dep->dat.dep.link_args = info.link_args;
*found = true;
return true;
M src/functions/dependency.c => src/functions/dependency.c +7 -0
@@ 154,6 154,12 @@ dep_args_iter(struct workspace *wk, void *_ctx, obj val)
}
}
+ if (dep->dat.dep.link_with_not_found) {
+ obj dup;
+ obj_array_dup(wk, dep->dat.dep.link_with_not_found, &dup);
+ obj_array_extend(wk, ctx->link_with_not_found, dup);
+ }
+
if (dep->dat.dep.include_directories) {
if (!obj_array_foreach_flat(wk, dep->dat.dep.include_directories,
_ctx, dep_args_includes_iter)) {
@@ 202,6 208,7 @@ dep_args_ctx_init(struct workspace *wk, struct dep_args_ctx *ctx)
make_obj(wk, &ctx->include_dirs, obj_array);
make_obj(wk, &ctx->link_with, obj_array);
+ make_obj(wk, &ctx->link_with_not_found, obj_array);
make_obj(wk, &ctx->link_args, obj_array);
make_obj(wk, &ctx->compile_args, obj_array);
make_obj(wk, &ctx->rpath, obj_array);
M src/meson.build => src/meson.build +0 -1
@@ 52,7 52,6 @@ src = (
'lang/serial.c',
'lang/string.c',
'lang/workspace.c',
- 'platform/dirs.c',
'platform/filesystem.c',
'platform/mem.c',
'platform/path.c',
D src/platform/dirs.c => src/platform/dirs.c +0 -10
@@ 1,10 0,0 @@
-#include "posix.h"
-
-#include <stddef.h>
-
-const char *libdirs[] = {
- "/usr/lib",
- "/usr/local/lib",
- "/lib",
- NULL
-};