diff --git a/src/bsys.c b/src/bsys.c index f7671bb2..9a51a622 100644 --- a/src/bsys.c +++ b/src/bsys.c @@ -27,8 +27,12 @@ bsys_t const* bsys_identify(void) { } int bsys_dep_tree(bsys_t const* bsys, int argc, char* argv[]) { + dep_node_t* tree = NULL; + int rv = -1; + if (bsys->dep_tree == NULL) { - return 0; + rv = 0; + goto no_tree; } // Parse the arguments as a list of hashes. @@ -43,27 +47,29 @@ int bsys_dep_tree(bsys_t const* bsys, int argc, char* argv[]) { // Create dependency tree. bool circular; - dep_node_t* const tree = bsys->dep_tree(argc, hashes, &circular); + tree = bsys->dep_tree(argc, hashes, &circular); free(hashes); - if (tree == NULL) { - if (circular) { - printf(BOB_DEPS_CIRCULAR); - return 0; - } + if (tree == NULL && circular) { + printf(BOB_DEPS_CIRCULAR); + return 0; + } - return -1; + if (tree != NULL) { + rv = 0; } assert(!circular); // Serialize and output it. - char* const STR_CLEANUP serialized = dep_node_serialize(tree); +no_tree:; + + char* const STR_CLEANUP serialized = tree == NULL ? strdup("") : dep_node_serialize(tree); printf(DEP_TAG_START "%s" DEP_TAG_END, serialized); deps_tree_free(tree); - return 0; + return rv; } static int do_build_deps(bsys_t const* bsys) { @@ -117,16 +123,12 @@ int bsys_build(bsys_t const* bsys) { // TODO Do this with mkdir_recursive? Do this in main.c? if (bsys->key != NULL) { - char* STR_CLEANUP path; - asprintf(&path, "%s/%s", out_path, bsys->key); - assert(path != NULL); - - if (mkdir_wrapped(path, 0755) < 0 && errno != EEXIST) { - LOG_FATAL("mkdir(\"%s\"): %s", path, strerror(errno)); + if (mkdir_wrapped(bsys_out_path, 0755) < 0 && errno != EEXIST) { + LOG_FATAL("mkdir(\"%s\"): %s", bsys_out_path, strerror(errno)); return -1; } - set_owner(path); + set_owner(bsys_out_path); } // Actually build. diff --git a/src/bsys/meson/main.c b/src/bsys/meson/main.c index c3e6098f..c32f68a4 100644 --- a/src/bsys/meson/main.c +++ b/src/bsys/meson/main.c @@ -1,18 +1,100 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2024 Aymeric Wibo +#include + #include +#include +#include +#include +#include + +#include +#include +#include + +#define BUILD_PATH "meson.build" static bool identify(void) { - return false; + return access(BUILD_PATH, F_OK) != -1; +} + +static int setup(void) { + if (!cmd_exists("meson")) { + LOG_FATAL("Couldn't find 'meson' executable in PATH. Meson is something you must install separately."); + return -1; + } + + if (!cmd_exists("ninja")) { + LOG_FATAL("Couldn't find 'ninja' executable in PATH. Ninja is something you must install separately, and is necessary for the Meson BSYS."); + return -1; + } + + return 0; } static int build(void) { + LOG_INFO("Meson setup..."); + + char* STR_CLEANUP prefix = NULL; + asprintf(&prefix, "-Dprefix=%s", install_prefix); + assert(prefix != NULL); + + cmd_t CMD_CLEANUP cmd = {0}; + cmd_create(&cmd, "meson", "setup", bsys_out_path, prefix, NULL); + cmd_set_redirect(&cmd, false); + + if (cmd_exec(&cmd) < 0) { + LOG_FATAL("Meson setup failed."); + return -1; + } + + else { + LOG_SUCCESS("Meson setup succeeded."); + } + + LOG_INFO("Ninja build..."); + + cmd_free(&cmd); + cmd_create(&cmd, "ninja", "-C", bsys_out_path, NULL); + cmd_set_redirect(&cmd, false); + + if (cmd_exec(&cmd) < 0) { + LOG_FATAL("Ninja build failed."); + return -1; + } + + else { + LOG_SUCCESS("Ninja build succeeded."); + } + + return 0; +} + +static int install(void) { + LOG_SUCCESS("Ninja install..."); + + cmd_t CMD_CLEANUP cmd = {0}; + cmd_create(&cmd, "ninja", "-C", bsys_out_path, "install", NULL); + cmd_set_redirect(&cmd, false); + + if (cmd_exec(&cmd) < 0) { + LOG_FATAL("Ninja install failed."); + return -1; + } + + else { + LOG_SUCCESS("Ninja install succeeded."); + } + return 0; } bsys_t const BSYS_MESON = { .name = "Meson", + .key = "meson", .identify = identify, + .setup = setup, .build = build, + .install = install, }; diff --git a/src/class/linker.c b/src/class/linker.c index 69e27be6..9758133a 100644 --- a/src/class/linker.c +++ b/src/class/linker.c @@ -207,7 +207,7 @@ static int prep_link(state_t* state, flamingo_arg_list_t* args, flamingo_val_t** } char* STR_CLEANUP cookie = NULL; - asprintf(&cookie, "%s/bob/linker.%s.cookie.%" PRIx64 ".%s", out_path, infinitive, total_hash, archive ? "a" : "l"); + asprintf(&cookie, "%s/linker.%s.cookie.%" PRIx64 ".%s", bsys_out_path, infinitive, total_hash, archive ? "a" : "l"); assert(cookie != NULL); *rv = flamingo_val_make_cstr(cookie); diff --git a/src/common.h b/src/common.h index 6d3338cb..e0067ad8 100644 --- a/src/common.h +++ b/src/common.h @@ -23,6 +23,7 @@ extern char const* bootstrap_import_path; extern char const* out_path; extern char const* abs_out_path; +extern char* bsys_out_path; extern char* deps_path; extern _Bool build_deps; diff --git a/src/cookie.c b/src/cookie.c index c4b152df..ed5eabc5 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -15,10 +15,10 @@ char* gen_cookie(char* path, size_t path_size, char const* ext) { char* cookie = NULL; - asprintf(&cookie, "%s/bob/%.*s.cookie.%" PRIx64 ".%s", out_path, (int) path_size, path, str_hash(path, path_size), ext); + asprintf(&cookie, "%s/%.*s.cookie.%" PRIx64 ".%s", bsys_out_path, (int) path_size, path, str_hash(path, path_size), ext); assert(cookie != NULL); - size_t const prefix_len = strlen(out_path) + strlen("/bob/"); + size_t const prefix_len = strlen(bsys_out_path) + strlen("/"); for (size_t i = prefix_len; i < prefix_len + path_size; i++) { if (cookie[i] == '/') { diff --git a/src/main.c b/src/main.c index 39cd0869..326eb49f 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,7 @@ char const* bootstrap_import_path = "import"; char const* out_path = ".bob"; // Default output path. char const* abs_out_path = NULL; +char* bsys_out_path = NULL; char* deps_path = NULL; bool build_deps = true; @@ -284,6 +285,11 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } + if (bsys->key != NULL) { + asprintf(&bsys_out_path, "%s/%s", out_path, bsys->key); + assert(bsys_out_path != NULL); + } + if (bsys->setup && bsys->setup() < 0) { return EXIT_FAILURE; } diff --git a/tests/dep_tree.sh b/tests/dep_tree.sh index b2a8f0fa..448357fb 100644 --- a/tests/dep_tree.sh +++ b/tests/dep_tree.sh @@ -125,3 +125,17 @@ elif ! echo $out | grep -q "Could not find local dependency at 'this-dep-doesnt- echo "Another issue occurred when attempting to create a dependency tree with a dependency which doesn't exist: $out" >&2 exit 1 fi + +# Test that we output an empty tree if there are no dependencies. +# Regression test for d1619dd "bsys: Output empty dependency tree if bsys doesn't have `dep_tree` function". + +cp tests/deps/build.none.fl tests/deps/build.fl +out=$(bob -C tests/deps dep-tree 2>&1) + +if [ $? != 0 ]; then + echo "Failed when attempting to create a dependency tree with no dependencies: $out" >&2 + exit 1 +elif ! echo $out | grep -q " "; then + echo "Dependency tree not empty when attempting to create a dependency tree with no dependencies: $out" >&2 + exit 1 +fi diff --git a/tests/deps/build.none.fl b/tests/deps/build.none.fl new file mode 100644 index 00000000..745a085d --- /dev/null +++ b/tests/deps/build.none.fl @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2025 Aymeric Wibo + +import bob + +deps = []