#include "posix.h" #include "backend/ninja.h" #include "external/samu.h" #include "functions/default/setup.h" #include "lang/eval.h" #include "lang/interpreter.h" #include "log.h" #include "platform/filesystem.h" #include "platform/path.h" uint32_t func_setup_flags = 0; struct set_options_ctx { struct workspace *sub_wk; uint32_t err_node, parent; }; static enum iteration_result set_options_iter(struct workspace *wk, void *_ctx, uint32_t key, uint32_t val) { struct set_options_ctx *ctx = _ctx; switch (get_obj(wk, val)->type) { case obj_dict: if (ctx->parent) { interp_error(wk, ctx->err_node, "options nested too deep"); return ir_err; } ctx->parent = key; if (!obj_dict_foreach(wk, val, ctx, set_options_iter)) { return ir_err; } ctx->parent = 0; break; default: { struct option_override oo = { .obj_value = true }; if (ctx->parent) { oo.proj = wk_str_push(ctx->sub_wk, get_cstr(wk, ctx->parent)); } oo.name = str_clone(wk, ctx->sub_wk, key); if (!obj_clone(wk, ctx->sub_wk, val, &oo.val)) { return ir_err; } darr_push(&ctx->sub_wk->option_overrides, &oo); break; } } return ir_cont; } bool func_setup(struct workspace *wk, uint32_t _, uint32_t args_node, uint32_t *obj) { struct args_norm an[] = { { obj_string }, ARG_TYPE_NULL }; enum kwargs { kw_options, kw_source, kw_cross, }; struct args_kw akw[] = { [kw_source] = { "source", obj_string }, [kw_options] = { "options", obj_dict }, [kw_cross] = { "cross", obj_string }, 0 }; if (!interp_args(wk, args_node, an, NULL, akw)) { return false; } struct workspace sub_wk; bool ret = false; char build_ninja[PATH_MAX]; uint32_t project_id; if (akw[kw_source].set) { L("chdir to '%s'", get_cstr(wk, akw[kw_source].val)); if (!path_chdir(get_cstr(wk, akw[kw_source].val))) { return false; } } workspace_init(&sub_wk); if (!workspace_setup_dirs(&sub_wk, get_cstr(wk, an[0].val), wk->argv0, true)) { goto ret; } if (akw[kw_options].set) { struct set_options_ctx ctx = { .sub_wk = &sub_wk, .err_node = akw[kw_options].node }; if (!obj_dict_foreach(wk, akw[kw_options].val, &ctx, set_options_iter)) { goto ret; } } if (!path_join(build_ninja, PATH_MAX, sub_wk.build_root, "build.ninja")) { goto ret; } if ((func_setup_flags & func_setup_flag_force) || !fs_file_exists(build_ninja)) { if (!eval_project(&sub_wk, NULL, sub_wk.source_root, sub_wk.build_root, &project_id)) { goto ret; } if (!ninja_write_all(&sub_wk)) { goto ret; } } if (!(func_setup_flags & func_setup_flag_no_build) && have_samu) { if (!path_chdir(sub_wk.build_root)) { return false; } else if (!muon_samu(0, (char *[]){ "", NULL })) { return false; } else if (!path_chdir(sub_wk.source_root)) { return false; } } ret = true; ret: workspace_destroy(&sub_wk); if (akw[kw_source].set) { if (!path_chdir(wk->source_root)) { return false; } } return ret; }