From 9381823059cc4eed2e9604ceb9eceb60887b63c7 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Mon, 6 Jan 2025 22:04:38 +0100 Subject: [PATCH 01/10] bsys: Meson building --- src/bsys/meson/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/bsys/meson/main.c b/src/bsys/meson/main.c index c3e6098f..e9e0d175 100644 --- a/src/bsys/meson/main.c +++ b/src/bsys/meson/main.c @@ -1,18 +1,65 @@ // 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 build(void) { + char* STR_CLEANUP meson_path = NULL; + asprintf(&meson_path, "%s/meson", out_path); + assert(meson_path != NULL); + + LOG_INFO("Meson setup..."); + + cmd_t CMD_CLEANUP cmd = {0}; + cmd_create(&cmd, "meson", "setup", meson_path); + 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", meson_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; } bsys_t const BSYS_MESON = { .name = "Meson", + .key = "meson", .identify = identify, .build = build, }; From b7525c329f2fffb836e04f7f2d8680d1d86428a9 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Mon, 6 Jan 2025 22:12:52 +0100 Subject: [PATCH 02/10] bsys/meson: Installation --- src/bsys/meson/main.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/bsys/meson/main.c b/src/bsys/meson/main.c index e9e0d175..be5f820f 100644 --- a/src/bsys/meson/main.c +++ b/src/bsys/meson/main.c @@ -26,8 +26,12 @@ 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", meson_path); + cmd_create(&cmd, "meson", "setup", meson_path, prefix, NULL); cmd_set_redirect(&cmd, false); if (cmd_exec(&cmd) < 0) { @@ -57,9 +61,33 @@ static int build(void) { return 0; } +static int install(void) { + char* STR_CLEANUP meson_path = NULL; + asprintf(&meson_path, "%s/meson", out_path); + assert(meson_path != NULL); + + LOG_SUCCESS("Ninja install..."); + + cmd_t CMD_CLEANUP cmd = {0}; + cmd_create(&cmd, "ninja", "-C", meson_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, .build = build, + .install = install, }; From d1619dd9a624b3558d30f1b654b4f1d332e400ca Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Mon, 6 Jan 2025 22:38:30 +0100 Subject: [PATCH 03/10] bsys: Output empty dependency tree if bsys doesn't have `dep_tree` function --- src/bsys.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bsys.c b/src/bsys.c index f7671bb2..0833a2cc 100644 --- a/src/bsys.c +++ b/src/bsys.c @@ -27,8 +27,10 @@ bsys_t const* bsys_identify(void) { } int bsys_dep_tree(bsys_t const* bsys, int argc, char* argv[]) { + dep_node_t* tree = NULL; + if (bsys->dep_tree == NULL) { - return 0; + goto no_tree; } // Parse the arguments as a list of hashes. @@ -43,23 +45,21 @@ 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; - } - - return -1; + if (tree == NULL && circular) { + printf(BOB_DEPS_CIRCULAR); + return 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); From 876affe25d57c42ca8bff4acb0f518b65279ab19 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Mon, 6 Jan 2025 22:47:03 +0100 Subject: [PATCH 04/10] dep-tree: Fail correctly when dependency tree don't exist --- src/bsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bsys.c b/src/bsys.c index 0833a2cc..ce1f7407 100644 --- a/src/bsys.c +++ b/src/bsys.c @@ -63,7 +63,7 @@ no_tree:; printf(DEP_TAG_START "%s" DEP_TAG_END, serialized); deps_tree_free(tree); - return 0; + return tree == NULL ? -1 : 0; } static int do_build_deps(bsys_t const* bsys) { From 5f8e5f5225d5d2cefe360f8bf6ae3450b2cd36d4 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Tue, 7 Jan 2025 00:30:10 +0100 Subject: [PATCH 05/10] dep-tree: Fix return values --- src/bsys.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bsys.c b/src/bsys.c index ce1f7407..55008d68 100644 --- a/src/bsys.c +++ b/src/bsys.c @@ -28,8 +28,10 @@ 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) { + rv = 0; goto no_tree; } @@ -53,6 +55,10 @@ int bsys_dep_tree(bsys_t const* bsys, int argc, char* argv[]) { return 0; } + if (tree != NULL) { + rv = 0; + } + assert(!circular); // Serialize and output it. @@ -63,7 +69,7 @@ no_tree:; printf(DEP_TAG_START "%s" DEP_TAG_END, serialized); deps_tree_free(tree); - return tree == NULL ? -1 : 0; + return rv; } static int do_build_deps(bsys_t const* bsys) { From e1f30bafeadd03f5f230d624c61fae243cccce88 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Sat, 11 Jan 2025 11:06:28 +0100 Subject: [PATCH 06/10] bsys: Set global `bsys_out_path` to BSYS-specific out path --- src/bsys.c | 10 +++------- src/bsys/meson/main.c | 14 +++----------- src/class/linker.c | 2 +- src/common.h | 1 + src/cookie.c | 4 ++-- src/main.c | 6 ++++++ 6 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/bsys.c b/src/bsys.c index 55008d68..9a51a622 100644 --- a/src/bsys.c +++ b/src/bsys.c @@ -123,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 be5f820f..c9b1a695 100644 --- a/src/bsys/meson/main.c +++ b/src/bsys/meson/main.c @@ -20,10 +20,6 @@ static bool identify(void) { } static int build(void) { - char* STR_CLEANUP meson_path = NULL; - asprintf(&meson_path, "%s/meson", out_path); - assert(meson_path != NULL); - LOG_INFO("Meson setup..."); char* STR_CLEANUP prefix = NULL; @@ -31,7 +27,7 @@ static int build(void) { assert(prefix != NULL); cmd_t CMD_CLEANUP cmd = {0}; - cmd_create(&cmd, "meson", "setup", meson_path, prefix, NULL); + cmd_create(&cmd, "meson", "setup", bsys_out_path, prefix, NULL); cmd_set_redirect(&cmd, false); if (cmd_exec(&cmd) < 0) { @@ -46,7 +42,7 @@ static int build(void) { LOG_INFO("Ninja build..."); cmd_free(&cmd); - cmd_create(&cmd, "ninja", "-C", meson_path, NULL); + cmd_create(&cmd, "ninja", "-C", bsys_out_path, NULL); cmd_set_redirect(&cmd, false); if (cmd_exec(&cmd) < 0) { @@ -62,14 +58,10 @@ static int build(void) { } static int install(void) { - char* STR_CLEANUP meson_path = NULL; - asprintf(&meson_path, "%s/meson", out_path); - assert(meson_path != NULL); - LOG_SUCCESS("Ninja install..."); cmd_t CMD_CLEANUP cmd = {0}; - cmd_create(&cmd, "ninja", "-C", meson_path, "install", NULL); + cmd_create(&cmd, "ninja", "-C", bsys_out_path, "install", NULL); cmd_set_redirect(&cmd, false); if (cmd_exec(&cmd) < 0) { 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..95b9edc8 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", abs_out_path, bsys->key); + assert(bsys_out_path != NULL); + } + if (bsys->setup && bsys->setup() < 0) { return EXIT_FAILURE; } From e9cd47b631e39009f23439917af88ae197bec3f1 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Sat, 11 Jan 2025 11:08:29 +0100 Subject: [PATCH 07/10] meson: Check for Meson and Ninja binaries before doing anything --- src/bsys/meson/main.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/bsys/meson/main.c b/src/bsys/meson/main.c index c9b1a695..c32f68a4 100644 --- a/src/bsys/meson/main.c +++ b/src/bsys/meson/main.c @@ -19,6 +19,20 @@ static bool identify(void) { 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..."); @@ -80,6 +94,7 @@ bsys_t const BSYS_MESON = { .name = "Meson", .key = "meson", .identify = identify, + .setup = setup, .build = build, .install = install, }; From 8e3610e6de576293bd71c427ca021b9e92eba512 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Sat, 11 Jan 2025 11:18:29 +0100 Subject: [PATCH 08/10] bsys: Make `bsys_out_path` based on relative out path --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 95b9edc8..326eb49f 100644 --- a/src/main.c +++ b/src/main.c @@ -286,7 +286,7 @@ int main(int argc, char* argv[]) { } if (bsys->key != NULL) { - asprintf(&bsys_out_path, "%s/%s", abs_out_path, bsys->key); + asprintf(&bsys_out_path, "%s/%s", out_path, bsys->key); assert(bsys_out_path != NULL); } From cf4c87b9a7d15b03894869241154f85130c73e75 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Sat, 11 Jan 2025 17:33:44 +0100 Subject: [PATCH 09/10] tests/dep_tree: Regression test for empty tree --- tests/dep_tree.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 From ccc18d13ca5a07999089500a9d37df8f5def6077 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Sat, 11 Jan 2025 17:35:00 +0100 Subject: [PATCH 10/10] tests/dep_tree: Add `build.none.fl` --- tests/deps/build.none.fl | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/deps/build.none.fl 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 = []