@@ -24,6 +24,7 @@ SRCS := \
2424 core/stack.c \
2525 core/vdso.c \
2626 core/bootstrap.c \
27+ core/launch.c \
2728 core/sysroot.c \
2829 runtime/thread.c \
2930 runtime/futex.c \
@@ -74,7 +75,17 @@ SRCS := \
7475 oci/fetch.c \
7576 oci/store.c \
7677 oci/pull.c \
77- oci/inspect.c
78+ oci/inspect.c \
79+ oci/tar.c \
80+ oci/decompress.c \
81+ oci/layer-meta.c \
82+ oci/layer-apply.c \
83+ oci/volume.c \
84+ oci/clone-rootfs.c \
85+ oci/unpack.c \
86+ oci/runspec.c \
87+ oci/path-resolve.c \
88+ oci/run.c
7889
7990SRCS := $(addprefix src/,$(SRCS ) )
8091OBJS := $(patsubst src/% .c,$(BUILD_DIR ) /% .o,$(SRCS ) )
@@ -91,10 +102,34 @@ $(CJSON_OBJ): $(CJSON_DIR)/cJSON.c $(CJSON_DIR)/cJSON.h | $(BUILD_DIR)
91102 @echo " CC $<"
92103 $(Q )$(CC ) $(CFLAGS ) -c -o $@ $<
93104
105+ # Vendored zstd v1.5.6 (decode-only). Phase 2 OCI layer unpack consumes
106+ # zstd-compressed layer media types. Compression, dictBuilder, deprecated,
107+ # and legacy v01-v06 paths are NOT vendored; do not call ZSTD_compress*.
108+ # Only src/oci/decompress.c includes externals/zstd/lib/zstd.h.
109+ ZSTD_DIR := externals/zstd
110+ ZSTD_SRCS := $(wildcard $(ZSTD_DIR ) /lib/common/* .c) \
111+ $(wildcard $(ZSTD_DIR ) /lib/decompress/* .c)
112+ ZSTD_OBJS := $(patsubst $(ZSTD_DIR ) /% .c,$(BUILD_DIR ) /externals/zstd/% .o,$(ZSTD_SRCS ) )
113+ OBJS += $(ZSTD_OBJS )
114+
115+ ZSTD_CFLAGS := -DZSTD_DISABLE_ASM=1 -DZSTD_LEGACY_SUPPORT=0 \
116+ -DZSTD_MULTITHREAD=0 -DZSTDLIB_VISIBILITY= \
117+ -Wno-pedantic -Wno-shadow -Wno-strict-prototypes \
118+ -Wno-missing-prototypes -Wno-unused-parameter \
119+ -Wno-cast-align -Wno-implicit-fallthrough \
120+ -I$(ZSTD_DIR ) /lib -I$(ZSTD_DIR ) /lib/common
121+
122+ $(BUILD_DIR ) /externals/zstd/% .o : $(ZSTD_DIR ) /% .c | $(BUILD_DIR )
123+ @mkdir -p $(dir $@ )
124+ @echo " CC $<"
125+ $(Q )$(CC ) $(CFLAGS ) $(ZSTD_CFLAGS ) -c -o $@ $<
126+
94127DISPATCH_MANIFEST := src/syscall/dispatch.tbl
95128DISPATCH_GENERATOR := scripts/gen-syscall-dispatch.py
96129DISPATCH_HEADER := $(BUILD_DIR ) /dispatch.h
97- HVF_LDFLAGS := -framework Hypervisor -arch arm64 -lcurl
130+ # -lz: gzip-compressed OCI layers route through zlib (system library).
131+ # -lcurl: HTTPS fetch for the Phase 1 oci pull path.
132+ HVF_LDFLAGS := -framework Hypervisor -arch arm64 -lcurl -lz
98133
99134# Generated headers under build/ that must exist before compiling sources that
100135# include them.
@@ -198,8 +233,9 @@ $(BUILD_DIR)/test-oci-fetch: $(BUILD_DIR)/test-oci-fetch.o $(BUILD_DIR)/lib/oci-
198233 $(Q )$(CC ) $(CFLAGS ) -o $@ $^ -lcurl -lpthread $(OPENSSL_LDFLAGS )
199234
200235# # Build the OCI local store unit test (native macOS, no HVF). Pure C; links
201- # # against the store wrapper plus its blob-store and digest dependencies.
202- $(BUILD_DIR ) /test-oci-store : $(BUILD_DIR ) /test-oci-store.o $(BUILD_DIR ) /oci/store.o $(BUILD_DIR ) /oci/blob-store.o $(BUILD_DIR ) /oci/digest.o $(BUILD_DIR ) /oci/ref.o | $(BUILD_DIR )
236+ # # against the store wrapper plus its blob-store, digest, and cJSON deps.
237+ # # cJSON is required because store.c now reads / writes index.json.
238+ $(BUILD_DIR ) /test-oci-store : $(BUILD_DIR ) /test-oci-store.o $(BUILD_DIR ) /oci/store.o $(BUILD_DIR ) /oci/blob-store.o $(BUILD_DIR ) /oci/digest.o $(BUILD_DIR ) /oci/ref.o $(CJSON_OBJ ) | $(BUILD_DIR )
203239 @echo " LD $@ "
204240 $(Q )$(CC ) $(CFLAGS ) -o $@ $^
205241
@@ -217,6 +253,98 @@ $(BUILD_DIR)/test-oci-inspect: $(BUILD_DIR)/test-oci-inspect.o $(BUILD_DIR)/oci/
217253 @echo " LD $@ "
218254 $(Q )$(CC ) $(CFLAGS ) -o $@ $^
219255
256+ # # Build the OCI tar reader unit test (native macOS, no HVF). Pure C; the
257+ # # test constructs ustar / GNU long-name streams in memory and drives them
258+ # # through the reader via a callback that exercises short-read chunking.
259+ $(BUILD_DIR ) /test-oci-tar : $(BUILD_DIR ) /test-oci-tar.o $(BUILD_DIR ) /oci/tar.o | $(BUILD_DIR )
260+ @echo " LD $@ "
261+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
262+
263+ # # Build the OCI runspec unit test (native macOS, no HVF). Pure-data
264+ # # merge of image-config runtime block + CLI overrides; the test feeds
265+ # # oci_image_runtime_t literals directly through oci_runspec_build with
266+ # # no filesystem or libcurl dependency.
267+ $(BUILD_DIR ) /test-oci-runspec : $(BUILD_DIR ) /test-oci-runspec.o $(BUILD_DIR ) /oci/runspec.o | $(BUILD_DIR )
268+ @echo " LD $@ "
269+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
270+
271+ # # Build the OCI path-resolve unit test (native macOS, no HVF). Touches
272+ # # the host filesystem to build a small fake sysroot tree and drives
273+ # # oci_path_resolve through realpath / stat / symlink-follow scenarios.
274+ # # Pure C; no libcurl, no zstd, no HVF.
275+ $(BUILD_DIR ) /test-oci-path-resolve : $(BUILD_DIR ) /test-oci-path-resolve.o $(BUILD_DIR ) /oci/path-resolve.o | $(BUILD_DIR )
276+ @echo " LD $@ "
277+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
278+
279+ # # Build the OCI run orchestrator unit test (native macOS, no HVF). Links
280+ # # the same OCI graph the unpack test pulls in, plus oci/run.o,
281+ # # oci/runspec.o, and oci/path-resolve.o. Does NOT link core/launch.o:
282+ # # the test ships an in-file elfuse_launch stub that aborts when called,
283+ # # and every case installs a launch hook via oci_run_set_launch_for_testing
284+ # # before invoking oci_run, so the real VM bring-up never runs from a test.
285+ $(BUILD_DIR ) /test-oci-run : $(BUILD_DIR ) /test-oci-run.o $(BUILD_DIR ) /oci/run.o $(BUILD_DIR ) /oci/runspec.o $(BUILD_DIR ) /oci/path-resolve.o $(BUILD_DIR ) /oci/unpack.o $(BUILD_DIR ) /oci/volume.o $(BUILD_DIR ) /oci/clone-rootfs.o $(BUILD_DIR ) /oci/layer-apply.o $(BUILD_DIR ) /oci/layer-meta.o $(BUILD_DIR ) /oci/decompress.o $(BUILD_DIR ) /oci/tar.o $(BUILD_DIR ) /oci/store.o $(BUILD_DIR ) /oci/blob-store.o $(BUILD_DIR ) /oci/digest.o $(BUILD_DIR ) /oci/manifest.o $(BUILD_DIR ) /oci/media-type.o $(BUILD_DIR ) /oci/ref.o $(BUILD_DIR ) /core/sysroot.o $(BUILD_DIR ) /debug/log.o $(CJSON_OBJ ) $(ZSTD_OBJS ) | $(BUILD_DIR )
286+ @echo " LD $@ "
287+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^ -lz
288+
289+ # # Build the OCI fixture builder (Phase 3 compat tests). Standalone tool
290+ # # that synthesises a complete OCI store from uncompressed-tar layers
291+ # # plus image-config flags. Used by tests/test-oci-compat.sh and
292+ # # available standalone for one-off "shape an image from local files"
293+ # # experiments.
294+ $(BUILD_DIR ) /oci-fixture-builder : $(BUILD_DIR ) /lib/oci-fixture-builder.o $(BUILD_DIR ) /oci/store.o $(BUILD_DIR ) /oci/blob-store.o $(BUILD_DIR ) /oci/digest.o $(BUILD_DIR ) /oci/ref.o $(CJSON_OBJ ) | $(BUILD_DIR )
295+ @echo " LD $@ "
296+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
297+
298+ # # decompress.c is the only translation unit in elfuse that includes
299+ # # externals/zstd/lib/zstd.h. Attach the zstd include path as a target-
300+ # # specific CFLAG so the rest of the codebase never sees zstd headers.
301+ $(BUILD_DIR ) /oci/decompress.o : CFLAGS += -I$(ZSTD_DIR ) /lib
302+
303+ # # Build the OCI sidecar metadata unit test (native macOS, no HVF). Pure
304+ # # C; links against cJSON for the JSON round-trip plus the layer-meta
305+ # # translation unit.
306+ $(BUILD_DIR ) /test-oci-meta : $(BUILD_DIR ) /test-oci-meta.o $(BUILD_DIR ) /oci/layer-meta.o $(CJSON_OBJ ) | $(BUILD_DIR )
307+ @echo " LD $@ "
308+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
309+
310+ # # Build the OCI layer applier unit test (native macOS, no HVF). Builds
311+ # # tar payloads in memory, drives them through oci_layer_apply into a
312+ # # tmp tree, and verifies filesystem state via lstat/readlink.
313+ $(BUILD_DIR ) /test-oci-layer-apply : $(BUILD_DIR ) /test-oci-layer-apply.o $(BUILD_DIR ) /oci/layer-apply.o $(BUILD_DIR ) /oci/layer-meta.o $(BUILD_DIR ) /oci/tar.o $(CJSON_OBJ ) | $(BUILD_DIR )
314+ @echo " LD $@ "
315+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
316+
317+ # # Build the OCI volume bootstrap unit test (native macOS, no HVF).
318+ # # Default-volume test is gated behind OCI_VOLUME_TEST=1 because it
319+ # # costs ~150 ms of hdiutil orchestration on first run. Links
320+ # # src/core/sysroot.o for the hdiutil wrappers PR #33 introduced.
321+ $(BUILD_DIR ) /test-oci-volume : $(BUILD_DIR ) /test-oci-volume.o $(BUILD_DIR ) /oci/volume.o $(BUILD_DIR ) /core/sysroot.o $(BUILD_DIR ) /debug/log.o | $(BUILD_DIR )
322+ @echo " LD $@ "
323+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
324+
325+ # # Build the OCI clone-rootfs unit test (native macOS, no HVF). The
326+ # # test skips itself if clonefile returns ENOTSUP (non-APFS scratch).
327+ $(BUILD_DIR ) /test-oci-clone : $(BUILD_DIR ) /test-oci-clone.o $(BUILD_DIR ) /oci/clone-rootfs.o | $(BUILD_DIR )
328+ @echo " LD $@ "
329+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^
330+
331+ # # Build the OCI unpack orchestrator integration smoke (native macOS,
332+ # # no HVF). Pulls in the full Phase 2 OCI stack so the dependency
333+ # # edges between modules are exercised at link time.
334+ $(BUILD_DIR ) /test-oci-unpack : $(BUILD_DIR ) /test-oci-unpack.o $(BUILD_DIR ) /oci/unpack.o $(BUILD_DIR ) /oci/volume.o $(BUILD_DIR ) /oci/clone-rootfs.o $(BUILD_DIR ) /oci/layer-apply.o $(BUILD_DIR ) /oci/layer-meta.o $(BUILD_DIR ) /oci/decompress.o $(BUILD_DIR ) /oci/tar.o $(BUILD_DIR ) /oci/store.o $(BUILD_DIR ) /oci/blob-store.o $(BUILD_DIR ) /oci/digest.o $(BUILD_DIR ) /oci/manifest.o $(BUILD_DIR ) /oci/media-type.o $(BUILD_DIR ) /oci/ref.o $(BUILD_DIR ) /core/sysroot.o $(BUILD_DIR ) /debug/log.o $(CJSON_OBJ ) $(ZSTD_OBJS ) | $(BUILD_DIR )
335+ @echo " LD $@ "
336+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^ -lz
337+
338+ # # Build the OCI decompression dispatch unit test (native macOS, no HVF).
339+ # # Links zstd objects + system zlib so gzip and zstd payloads both round-
340+ # # trip through oci_stream_t. The gzip fixture is generated at test time
341+ # # via zlib; the zstd fixture is an embedded byte array because the
342+ # # vendored libzstd is decode-only.
343+ $(BUILD_DIR ) /test-oci-decompress.o : CFLAGS += -I$(ZSTD_DIR ) /lib
344+ $(BUILD_DIR ) /test-oci-decompress : $(BUILD_DIR ) /test-oci-decompress.o $(BUILD_DIR ) /oci/decompress.o $(ZSTD_OBJS ) | $(BUILD_DIR )
345+ @echo " LD $@ "
346+ $(Q )$(CC ) $(CFLAGS ) -o $@ $^ -lz
347+
220348# Guest test binaries (cross-compiled, aarch64-linux)
221349# Only used when GUEST_TEST_BINARIES is not set.
222350
0 commit comments