nbos
nbos
https://git.tonybtw.com/nbos.git
git://git.tonybtw.com/nbos.git
updated makefile, changed pkgs folder structure
Diff
diff --git a/.gitignore b/.gitignore
index 10e7215..8b0a7a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.clangd
.cache/
build/
+.build/
notes/
compile_commands.json
nb
diff --git a/Makefile b/Makefile
index dcee192..debd4a6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,3 @@
-# Nb Makefile. C23, strict warnings, sanitizer-ready.
-
CC ?= cc
CFLAGS ?= -std=c23 -O2 -g \
-Wall -Wextra -Wpedantic -Wshadow -Wconversion \
@@ -8,11 +6,15 @@ CFLAGS ?= -std=c23 -O2 -g \
-fno-strict-aliasing
LDFLAGS ?=
+PROFILE ?= release
ifdef SANITIZE
+ PROFILE := sanitize
CFLAGS += -fsanitize=address,undefined -fno-omit-frame-pointer
LDFLAGS += -fsanitize=address,undefined
endif
+BUILD_DIR := .build/$(PROFILE)
+
INCLUDES = -Iinclude -Isrc
SRC_FILES = \
@@ -31,20 +33,27 @@ SRC_FILES = \
src/activate.c
PKG_FILES = $(shell find pkgs -name '*.c')
-
CONFIG_FILE ?= etc-example/config.c
-OBJ_FILES = $(SRC_FILES:.c=.o) $(PKG_FILES:.c=.o)
+ALL_SRCS = $(SRC_FILES) $(PKG_FILES) $(CONFIG_FILE)
+OBJ_FILES = $(patsubst %.c,$(BUILD_DIR)/%.o,$(ALL_SRCS))
+DEP_FILES = $(OBJ_FILES:.o=.d)
.PHONY: all clean registry switch
all: nb
-nb: $(OBJ_FILES) $(CONFIG_FILE:.c=.o) pkgs/all.o
+nb: $(BUILD_DIR)/nb
+ @ln -sf $< $@
+
+$(BUILD_DIR)/nb: $(OBJ_FILES)
$(CC) $(LDFLAGS) -o $@ $^
-%.o: %.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+$(BUILD_DIR)/%.o: %.c
+ @mkdir -p $(@D)
+ $(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c -o $@ $<
+
+-include $(DEP_FILES)
registry:
./tools/gen-registry.sh > pkgs/all.h.tmp
@@ -53,8 +62,7 @@ registry:
mv pkgs/all.c.tmp pkgs/all.c
clean:
- find . -name '*.o' -delete
- rm -f nb
+ rm -rf .build nb
switch: nb
./nb switch
diff --git a/etc-example/config.c b/etc-example/config.c
index fae9322..c41feb3 100644
--- a/etc-example/config.c
+++ b/etc-example/config.c
@@ -1,11 +1,11 @@
/* /etc/nb/config.c */
#include "../include/nbos.h"
-#include "../pkgs/core/glibc/glibc.h"
-#include "../pkgs/core/linux/linux.h"
-#include "../pkgs/editor/neovim/neovim.h"
-#include "../pkgs/wm/oxwm/oxwm.h"
-#include "../pkgs/shell/dash/dash.h"
-#include "../pkgs/browser/firefox/firefox.h"
+#include "../pkgs/glibc/glibc.h"
+#include "../pkgs/linux/linux.h"
+#include "../pkgs/neovim/neovim.h"
+#include "../pkgs/oxwm/oxwm.h"
+#include "../pkgs/dash/dash.h"
+#include "../pkgs/firefox/firefox.h"
static const pkg *const my_pkgs[] = {
&pkgs_glibc,
diff --git a/pkgs/shell/dash/build.sh b/pkgs/dash/build.sh
similarity index 100%
rename from pkgs/shell/dash/build.sh
rename to pkgs/dash/build.sh
diff --git a/pkgs/shell/dash/dash.c b/pkgs/dash/dash.c
similarity index 93%
rename from pkgs/shell/dash/dash.c
rename to pkgs/dash/dash.c
index 8f1689e..200f3f2 100644
--- a/pkgs/shell/dash/dash.c
+++ b/pkgs/dash/dash.c
@@ -1,5 +1,5 @@
#include "dash.h"
-#include "../../core/glibc/glibc.h"
+#include "../glibc/glibc.h"
static const pkg *const dash_deps[] = { &pkgs_glibc };
diff --git a/pkgs/shell/dash/dash.h b/pkgs/dash/dash.h
similarity index 68%
rename from pkgs/shell/dash/dash.h
rename to pkgs/dash/dash.h
index 9b94c2a..648e920 100644
--- a/pkgs/shell/dash/dash.h
+++ b/pkgs/dash/dash.h
@@ -1,5 +1,5 @@
#ifndef PKGS_DASH_H
#define PKGS_DASH_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_dash;
#endif
diff --git a/pkgs/browser/firefox/build.sh b/pkgs/firefox/build.sh
similarity index 100%
rename from pkgs/browser/firefox/build.sh
rename to pkgs/firefox/build.sh
diff --git a/pkgs/browser/firefox/firefox.c b/pkgs/firefox/firefox.c
similarity index 93%
rename from pkgs/browser/firefox/firefox.c
rename to pkgs/firefox/firefox.c
index cad79a3..dcc51f1 100644
--- a/pkgs/browser/firefox/firefox.c
+++ b/pkgs/firefox/firefox.c
@@ -1,5 +1,5 @@
#include "firefox.h"
-#include "../../core/glibc/glibc.h"
+#include "../glibc/glibc.h"
static const pkg *const firefox_deps[] = { &pkgs_glibc };
diff --git a/pkgs/browser/firefox/firefox.h b/pkgs/firefox/firefox.h
similarity index 70%
rename from pkgs/browser/firefox/firefox.h
rename to pkgs/firefox/firefox.h
index 7c2676c..b5975f1 100644
--- a/pkgs/browser/firefox/firefox.h
+++ b/pkgs/firefox/firefox.h
@@ -1,5 +1,5 @@
#ifndef PKGS_FIREFOX_H
#define PKGS_FIREFOX_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_firefox;
#endif
diff --git a/pkgs/core/glibc/build.sh b/pkgs/glibc/build.sh
similarity index 100%
rename from pkgs/core/glibc/build.sh
rename to pkgs/glibc/build.sh
diff --git a/pkgs/core/glibc/glibc.c b/pkgs/glibc/glibc.c
similarity index 100%
rename from pkgs/core/glibc/glibc.c
rename to pkgs/glibc/glibc.c
diff --git a/pkgs/core/glibc/glibc.h b/pkgs/glibc/glibc.h
similarity index 69%
rename from pkgs/core/glibc/glibc.h
rename to pkgs/glibc/glibc.h
index c0eab6a..fd41f35 100644
--- a/pkgs/core/glibc/glibc.h
+++ b/pkgs/glibc/glibc.h
@@ -1,5 +1,5 @@
#ifndef PKGS_GLIBC_H
#define PKGS_GLIBC_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_glibc;
#endif
diff --git a/pkgs/core/linux/build.sh b/pkgs/linux/build.sh
similarity index 100%
rename from pkgs/core/linux/build.sh
rename to pkgs/linux/build.sh
diff --git a/pkgs/core/linux/linux.c b/pkgs/linux/linux.c
similarity index 100%
rename from pkgs/core/linux/linux.c
rename to pkgs/linux/linux.c
diff --git a/pkgs/core/linux/linux.h b/pkgs/linux/linux.h
similarity index 69%
rename from pkgs/core/linux/linux.h
rename to pkgs/linux/linux.h
index 5295fc6..a7334b8 100644
--- a/pkgs/core/linux/linux.h
+++ b/pkgs/linux/linux.h
@@ -1,5 +1,5 @@
#ifndef PKGS_LINUX_H
#define PKGS_LINUX_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_linux;
#endif
diff --git a/pkgs/lang/lua/build.sh b/pkgs/lua/build.sh
similarity index 100%
rename from pkgs/lang/lua/build.sh
rename to pkgs/lua/build.sh
diff --git a/pkgs/lang/lua/lua.c b/pkgs/lua/lua.c
similarity index 92%
rename from pkgs/lang/lua/lua.c
rename to pkgs/lua/lua.c
index 219a78b..cc1e122 100644
--- a/pkgs/lang/lua/lua.c
+++ b/pkgs/lua/lua.c
@@ -1,5 +1,5 @@
#include "lua.h"
-#include "../../core/glibc/glibc.h"
+#include "../glibc/glibc.h"
static const pkg *const lua_deps[] = { &pkgs_glibc };
diff --git a/pkgs/lang/lua/lua.h b/pkgs/lua/lua.h
similarity index 67%
rename from pkgs/lang/lua/lua.h
rename to pkgs/lua/lua.h
index e82370d..8d95525 100644
--- a/pkgs/lang/lua/lua.h
+++ b/pkgs/lua/lua.h
@@ -1,5 +1,5 @@
#ifndef PKGS_LUA_H
#define PKGS_LUA_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_lua;
#endif
diff --git a/pkgs/editor/neovim/build.sh b/pkgs/neovim/build.sh
similarity index 100%
rename from pkgs/editor/neovim/build.sh
rename to pkgs/neovim/build.sh
diff --git a/pkgs/editor/neovim/neovim.c b/pkgs/neovim/neovim.c
similarity index 88%
rename from pkgs/editor/neovim/neovim.c
rename to pkgs/neovim/neovim.c
index dae3833..bf27b0e 100644
--- a/pkgs/editor/neovim/neovim.c
+++ b/pkgs/neovim/neovim.c
@@ -1,6 +1,6 @@
#include "neovim.h"
-#include "../../core/glibc/glibc.h"
-#include "../../lang/lua/lua.h"
+#include "../glibc/glibc.h"
+#include "../lua/lua.h"
static const pkg *const neovim_deps[] = {
&pkgs_glibc,
diff --git a/pkgs/editor/neovim/neovim.h b/pkgs/neovim/neovim.h
similarity index 69%
rename from pkgs/editor/neovim/neovim.h
rename to pkgs/neovim/neovim.h
index c78de21..8a32cd0 100644
--- a/pkgs/editor/neovim/neovim.h
+++ b/pkgs/neovim/neovim.h
@@ -1,5 +1,5 @@
#ifndef PKGS_NEOVIM_H
#define PKGS_NEOVIM_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_neovim;
#endif
diff --git a/pkgs/wm/oxwm/build.sh b/pkgs/oxwm/build.sh
similarity index 100%
rename from pkgs/wm/oxwm/build.sh
rename to pkgs/oxwm/build.sh
diff --git a/pkgs/wm/oxwm/oxwm.c b/pkgs/oxwm/oxwm.c
similarity index 88%
rename from pkgs/wm/oxwm/oxwm.c
rename to pkgs/oxwm/oxwm.c
index aadb31c..f231af1 100644
--- a/pkgs/wm/oxwm/oxwm.c
+++ b/pkgs/oxwm/oxwm.c
@@ -1,6 +1,6 @@
#include "oxwm.h"
-#include "../../core/glibc/glibc.h"
-#include "../../lang/lua/lua.h"
+#include "../glibc/glibc.h"
+#include "../lua/lua.h"
static const pkg *const oxwm_deps[] = {
&pkgs_glibc,
diff --git a/pkgs/wm/oxwm/oxwm.h b/pkgs/oxwm/oxwm.h
similarity index 68%
rename from pkgs/wm/oxwm/oxwm.h
rename to pkgs/oxwm/oxwm.h
index b83b879..02dbe7a 100644
--- a/pkgs/wm/oxwm/oxwm.h
+++ b/pkgs/oxwm/oxwm.h
@@ -1,5 +1,5 @@
#ifndef PKGS_OXWM_H
#define PKGS_OXWM_H
-#include "../../../include/nbos.h"
+#include "../../include/nbos.h"
extern const pkg pkgs_oxwm;
#endif
diff --git a/src/build.h b/src/build.h
index 2bfd43d..44f439e 100644
--- a/src/build.h
+++ b/src/build.h
@@ -11,6 +11,7 @@
const pkg *p,
const pkg_refs *all_pkgs,
const resolved *resolved_pkgs,
- size_t pkg_idx);
+ size_t pkg_idx
+);
#endif
diff --git a/src/error.c b/src/error.c
index 95e0494..b22f278 100644
--- a/src/error.c
+++ b/src/error.c
@@ -16,6 +16,9 @@ void resolve_error_print(const resolve_error *e) {
case RESOLVE_E_DUPLICATE_NAME:
fprintf(stderr, "nb: duplicate package name '%s' (two recipes export the same name)\n", e->pkg_name);
return;
+ case RESOLVE_E_OOM:
+ fprintf(stderr, "nb: out of memory while resolving packages\n");
+ return;
}
}
diff --git a/src/error.h b/src/error.h
index 18fa73a..795936e 100644
--- a/src/error.h
+++ b/src/error.h
@@ -9,6 +9,7 @@ typedef enum : uint8_t {
RESOLVE_E_CYCLE,
RESOLVE_E_MISSING_DEP,
RESOLVE_E_DUPLICATE_NAME,
+ RESOLVE_E_OOM,
} resolve_error_kind;
typedef struct {
diff --git a/src/fetch.c b/src/fetch.c
index 9ab7bdb..4243142 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -19,6 +19,7 @@
* Return: FETCH_OK_VAL on success, a tagged error otherwise.
*/
fetch_error fetch(const pkg *p, const char *dest_path) {
+ // TODO: replace this with execvpe or libcurl
char *const argv[] = {
"/usr/bin/curl",
"-fsSL",
diff --git a/src/main.c b/src/main.c
index a97cc03..6dcd071 100644
--- a/src/main.c
+++ b/src/main.c
@@ -110,7 +110,8 @@ static void usage(void) {
" validate check the current config without activating\n"
" rollback activate the previous generation\n"
" diff diff two generations (default: previous vs current)\n"
- " gc remove store paths not referenced by any generation\n");
+ " gc remove store paths not referenced by any generation\n"
+ );
}
int main(int argc, char **argv) {
diff --git a/src/realize.c b/src/realize.c
index 4aa3b01..ece3aa3 100644
--- a/src/realize.c
+++ b/src/realize.c
@@ -15,14 +15,16 @@
realize_error realize(
arena *a,
const pkg_refs *all_pkgs,
- const resolved_list *resolved)
-{
+ const resolved_list *resolved
+) {
for (size_t i = 0; i < resolved->len; i++) {
- realize_error err = build_pkg(a,
- resolved->data[i].def,
- all_pkgs,
- resolved->data,
- i);
+ realize_error err = build_pkg(
+ a,
+ resolved->data[i].def,
+ all_pkgs,
+ resolved->data,
+ i
+ );
if (err.kind != REALIZE_OK) return err;
}
return REALIZE_OK_VAL;
diff --git a/src/resolve.c b/src/resolve.c
index 74625ae..e07ea8a 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -4,7 +4,6 @@
#include <stdalign.h>
#include <string.h>
-#include "hash.h"
#include "store.h"
typedef enum : uint8_t {
@@ -13,63 +12,95 @@ typedef enum : uint8_t {
VISITED,
} visit_state;
-static size_t find_pkg(const pkg_refs *pkgs, const pkg *needle) {
- for (size_t i = 0; i < pkgs->len; i++) {
- if (pkgs->data[i] == needle) return i;
+typedef struct closure_node closure_node;
+struct closure_node {
+ const pkg *p;
+ closure_node *next;
+};
+
+static bool closure_contains(const closure_node *head, const pkg *p) {
+ for (const closure_node *n = head; n != nullptr; n = n->next) {
+ if (n->p == p) return true;
+ }
+ return false;
+}
+
+static bool closure_collect(
+ arena *a,
+ const pkg *p,
+ closure_node **head,
+ size_t *count
+ ) {
+ if (closure_contains(*head, p)) return true;
+
+ closure_node *node = arena_alloc(a, sizeof(closure_node), alignof(closure_node));
+ if (node == nullptr) return false;
+ node->p = p;
+ node->next = *head;
+ *head = node;
+ (*count)++;
+
+ for (size_t i = 0; i < p->deps.len; i++) {
+ if (!closure_collect(a, p->deps.data[i], head, count)) return false;
+ }
+ return true;
+}
+
+static size_t closure_index(
+ const pkg *const *closure,
+ size_t n,
+ const pkg *target)
+{
+ for (size_t i = 0; i < n; i++) {
+ if (closure[i] == target) return i;
}
return SIZE_MAX;
}
static resolve_error visit(
- arena *a,
- const pkg_refs *pkgs,
- size_t idx,
- visit_state *state,
- resolved *out)
+ arena *a,
+ const pkg *const *closure,
+ size_t n_closure,
+ size_t idx,
+ visit_state *state,
+ resolved *out,
+ size_t *out_len)
{
switch (state[idx]) {
case VISITED: return RESOLVE_OK_VAL;
case VISITING: return (resolve_error){
.kind = RESOLVE_E_CYCLE,
- .pkg_name = pkgs->data[idx]->name,
+ .pkg_name = closure[idx]->name,
};
case UNVISITED: break;
}
state[idx] = VISITING;
- const pkg *p = pkgs->data[idx];
+ const pkg *p = closure[idx];
for (size_t i = 0; i < p->deps.len; i++) {
- const pkg *dep = p->deps.data[i];
- size_t dep_idx = find_pkg(pkgs, dep);
- if (dep_idx == SIZE_MAX) {
- return (resolve_error){
- .kind = RESOLVE_E_MISSING_DEP,
- .pkg_name = p->name,
- .dep_name = dep->name,
- };
- }
-
- resolve_error err = visit(a, pkgs, dep_idx, state, out);
+ size_t dep_idx = closure_index(closure, n_closure, p->deps.data[i]);
+ resolve_error err = visit(a, closure, n_closure, dep_idx, state, out, out_len);
if (err.kind != RESOLVE_OK) return err;
}
- out[idx].def = p;
- out[idx].store_path = store_path_compute(a, p, pkgs, out);
-
+ out[*out_len].def = p;
+ out[*out_len].store_path = store_path_compute(a, p, out, *out_len);
+ (*out_len)++;
state[idx] = VISITED;
return RESOLVE_OK_VAL;
}
/**
- * resolve() - Topologically sort packages and compute their store paths.
- * @a: Arena holding the resulting visit-state and resolved arrays.
- * @cfg: System configuration providing the package list.
+ * resolve() - Compute the build closure and topologically sort it.
+ * @a: Arena holding the resulting closure, visit-state, and resolved arrays.
+ * @cfg: System configuration providing the package roots.
* @out: Filled with topologically-sorted &resolved entries on success.
*
- * Rejects duplicate package names up front, then performs a DFS that
- * detects cycles and missing deps. Each entry's store path depends on
- * its deps' store paths, so children must be resolved first.
+ * Roots are everything the config references directly: @cfg->pkgs entries,
+ * @cfg->boot.kernel, and each @cfg->users[i].shell. Transitive deps are
+ * auto-discovered into the closure. The output is in post-order so
+ * &realize can iterate it directly.
*
* Return: RESOLVE_OK_VAL on success, a tagged error otherwise.
*/
@@ -89,20 +120,51 @@ resolve_error resolve(
}
}
- visit_state *state = arena_alloc(a, cfg->pkgs.len * sizeof(visit_state),
- alignof(visit_state));
- resolved *res = arena_alloc(a, cfg->pkgs.len * sizeof(resolved),
- alignof(resolved));
- if (state == nullptr || res == nullptr) {
- return (resolve_error){ .kind = RESOLVE_E_MISSING_DEP };
+ closure_node *head = nullptr;
+ size_t n_closure = 0;
+ for (size_t i = 0; i < cfg->pkgs.len; i++) {
+ if (!closure_collect(a, cfg->pkgs.data[i], &head, &n_closure)) {
+ return (resolve_error){ .kind = RESOLVE_E_OOM };
+ }
+ }
+ if (cfg->boot.kernel != nullptr) {
+ if (!closure_collect(a, cfg->boot.kernel, &head, &n_closure)) {
+ return (resolve_error){ .kind = RESOLVE_E_OOM };
+ }
+ }
+ for (size_t i = 0; i < cfg->users.len; i++) {
+ const pkg *shell = cfg->users.data[i].shell;
+ if (shell != nullptr) {
+ if (!closure_collect(a, shell, &head, &n_closure)) {
+ return (resolve_error){ .kind = RESOLVE_E_OOM };
+ }
+ }
+ }
+
+ const pkg **closure = arena_alloc(a, n_closure * sizeof(const pkg *),
+ alignof(const pkg *));
+ visit_state *state = arena_alloc(a, n_closure * sizeof(visit_state),
+ alignof(visit_state));
+ resolved *res = arena_alloc(a, n_closure * sizeof(resolved),
+ alignof(resolved));
+ if (closure == nullptr || state == nullptr || res == nullptr) {
+ return (resolve_error){ .kind = RESOLVE_E_OOM };
}
- for (size_t i = 0; i < cfg->pkgs.len; i++) {
- resolve_error err = visit(a, &cfg->pkgs, i, state, res);
+ {
+ size_t i = 0;
+ for (closure_node *n = head; n != nullptr; n = n->next) {
+ closure[i++] = n->p;
+ }
+ }
+
+ size_t res_len = 0;
+ for (size_t i = 0; i < n_closure; i++) {
+ resolve_error err = visit(a, closure, n_closure, i, state, res, &res_len);
if (err.kind != RESOLVE_OK) return err;
}
out->data = res;
- out->len = cfg->pkgs.len;
+ out->len = res_len;
return RESOLVE_OK_VAL;
}
diff --git a/src/sandbox.c b/src/sandbox.c
index 8acbfdb..173a83d 100644
--- a/src/sandbox.c
+++ b/src/sandbox.c
@@ -28,8 +28,8 @@ int sandbox_setup(
const char *sandbox_root,
const pkg_refs *deps,
const resolved *resolved_deps,
- const char *src_dir)
-{
+ const char *src_dir
+) {
(void)sandbox_root;
(void)deps;
(void)resolved_deps;
diff --git a/src/store.c b/src/store.c
index eeb4b9d..e621653 100644
--- a/src/store.c
+++ b/src/store.c
@@ -34,26 +34,16 @@ static void base32_encode(const uint8_t *in, size_t len, char *out) {
out[out_idx] = '\0';
}
-static const char *resolved_path_for(
- const pkg *target,
- const pkg_refs *all_pkgs,
- const resolved *resolved_pkgs)
-{
- for (size_t i = 0; i < all_pkgs->len; i++) {
- if (all_pkgs->data[i] == target) {
- return resolved_pkgs[i].store_path;
- }
- }
- return nullptr;
-}
+
+
/**
* store_path_compute() - Compute the content-addressed store path for @p.
* @a: Arena that owns the returned string.
* @p: Package whose inputs determine the path.
- * @all_pkgs: Full package list, used to look up dep store paths.
- * @resolved_pkgs: Parallel array of resolved entries; deps must already
+ * @resolved_pkgs: Resolved entries already topo-sorted; deps must already
* have @store_path populated.
+ * @n_resolved: Number of valid entries in @resolved_pkgs.
*
* Hashes a length-prefixed canonical encoding of the package inputs
* (name, version, src URL, source sha256, build flags, build system,
@@ -66,8 +56,8 @@ static const char *resolved_path_for(
const char *store_path_compute(
arena *a,
const pkg *p,
- const pkg_refs *all_pkgs,
- const resolved *resolved_pkgs)
+ const resolved *resolved_pkgs,
+ size_t n_resolved)
{
sha256_ctx ctx;
sha256_init(&ctx);
@@ -90,9 +80,14 @@ const char *store_path_compute(
sha256_update(&ctx, "\0", 1);
for (size_t i = 0; i < p->deps.len; i++) {
- const char *dep_path = resolved_path_for(p->deps.data[i],
- all_pkgs,
- resolved_pkgs);
+ const pkg *target = p->deps.data[i];
+ const char *dep_path = nullptr;
+ for (size_t j = 0; j < n_resolved; j++) {
+ if (resolved_pkgs[j].def == target) {
+ dep_path = resolved_pkgs[j].store_path;
+ break;
+ }
+ }
if (dep_path == nullptr) return nullptr;
HASH_FIELD(dep_path);
}
diff --git a/src/store.h b/src/store.h
index 3b396ec..dde1b17 100644
--- a/src/store.h
+++ b/src/store.h
@@ -10,8 +10,8 @@
[[nodiscard]] const char *store_path_compute(
arena *a,
const pkg *p,
- const pkg_refs *all_pkgs,
- const resolved *resolved_pkgs);
+ const resolved *resolved_pkgs,
+ size_t n_resolved);
[[nodiscard]] bool store_path_exists(const char *store_path);
diff --git a/src/validate.c b/src/validate.c
index 04548de..3e519dd 100644
--- a/src/validate.c
+++ b/src/validate.c
@@ -3,13 +3,6 @@
#include <stdio.h>
#include <string.h>
-static bool pkg_in_list(const pkg *p, const pkg_refs *list) {
- for (size_t i = 0; i < list->len; i++) {
- if (list->data[i] == p) return true;
- }
- return false;
-}
-
static bool is_known_bootloader(const char *name) {
return strcmp(name, "limine") == 0
|| strcmp(name, "grub") == 0
@@ -21,8 +14,11 @@ static bool is_known_bootloader(const char *name) {
* @cfg: Configuration to inspect.
*
* Covers what resolve() does not: hostname presence, bootloader
- * recognition, kernel/shell pointers belong to the package list, and
- * uniqueness of user and service names. Errors are printed to stderr.
+ * recognition, non-null kernel/shell pointers, and uniqueness of user
+ * and service names. Pkg references (kernel, shells, declared pkgs)
+ * are all closure roots — resolve() auto-discovers transitive deps,
+ * so no "is in the package list" check is needed. Errors are printed
+ * to stderr.
*
* Return: true if every check passes.
*/
@@ -42,10 +38,6 @@ bool validate(const system_cfg *cfg) {
if (cfg->boot.kernel == nullptr) {
fprintf(stderr, "nb: boot.kernel is null\n");
ok = false;
- } else if (!pkg_in_list(cfg->boot.kernel, &cfg->pkgs)) {
- fprintf(stderr, "nb: boot.kernel '%s' is not in the package list\n",
- cfg->boot.kernel->name);
- ok = false;
}
for (size_t i = 0; i < cfg->users.len; i++) {
@@ -60,10 +52,6 @@ bool validate(const system_cfg *cfg) {
if (u->shell == nullptr) {
fprintf(stderr, "nb: user '%s' has null shell\n", u->name);
ok = false;
- } else if (!pkg_in_list(u->shell, &cfg->pkgs)) {
- fprintf(stderr, "nb: user '%s' shell '%s' is not in the package list\n",
- u->name, u->shell->name);
- ok = false;
}
for (size_t j = i + 1; j < cfg->users.len; j++) {
diff --git a/tools/gen-registry.sh b/tools/gen-registry.sh
index 26b68fe..1e7a545 100755
--- a/tools/gen-registry.sh
+++ b/tools/gen-registry.sh
@@ -10,7 +10,7 @@ set -eu
PKGS_DIR="${PKGS_DIR:-pkgs}"
MODE="${1:-h}"
-recipes=$(find "$PKGS_DIR" -mindepth 3 -maxdepth 3 -name '*.h' \
+recipes=$(find "$PKGS_DIR" -mindepth 2 -maxdepth 2 -name '*.h' \
! -name 'all.h' | sort)
if [ "$MODE" = "h" ] || [ "$MODE" = "--h" ]; then