fix(build): rebuild C outputs on HUF mode changes
Mode-specific Rust archives exposed the test makefiles' flat C-object cache:
switching from default to forced HUF mode could relink stale default C objects
with a newly built forced Rust archive. That hybrid has incompatible decoder
table expectations and can corrupt dictionary decompression.
Track each makefile's effective HUF mode with an empty archive stamp. It is a
safe normal linker prerequisite, and every mode transition advances its mtime
so cached C objects and direct-source binaries rebuild while unchanged modes
remain incremental.
Test Plan:
- cargo clippy; cargo clippy --benches; cargo clippy --tests
- cargo +nightly fmt, then repeat the Clippy checks
- cargo test --all-targets
- Default -> forced-X1 -> default fuzzer builds without -B, each running
./fuzzer -s5346 -i1 --no-big-tests
- Equivalent zstd-small default/forced/default rebuild and --version checks
Refs: rust/README.md
Fixes: d89ebb31
This commit is contained in:
@@ -77,6 +77,25 @@ $(RUST_STATICLIB): $(RUST_SOURCES)
|
|||||||
$(RUST_STATICLIB_32): $(RUST_SOURCES)
|
$(RUST_STATICLIB_32): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_CARGO_FLAGS) --target $(RUST_TARGET_32)
|
$(CARGO) build $(RUST_CARGO_FLAGS) --target $(RUST_TARGET_32)
|
||||||
|
|
||||||
|
# Most program objects use a configuration-hashed directory, but the compact
|
||||||
|
# direct-source variants below do not. Give their C outputs an independent
|
||||||
|
# mode stamp so they cannot outlive a different Rust HUF archive selection.
|
||||||
|
# The stamp is an empty archive, so normal linker `$^` recipes can consume it.
|
||||||
|
RUST_HUF_C_MODE_FILE := $(RUST_DIR)/target/.huf-c-mode-programs
|
||||||
|
RUST_HUF_C_MODE_STAMP := $(RUST_DIR)/target/.huf-c-mode-programs.a
|
||||||
|
.PHONY: FORCE_RUST_HUF_C_MODE
|
||||||
|
FORCE_RUST_HUF_C_MODE:
|
||||||
|
$(RUST_HUF_C_MODE_STAMP): FORCE_RUST_HUF_C_MODE
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@if test ! -r $(RUST_HUF_C_MODE_FILE) \
|
||||||
|
|| test "$$(cat $(RUST_HUF_C_MODE_FILE))" != "$(RUST_BUILD_CONFIG)" \
|
||||||
|
|| test ! -f $@; then \
|
||||||
|
printf '%s\n' "$(RUST_BUILD_CONFIG)" > $(RUST_HUF_C_MODE_FILE); \
|
||||||
|
$(AR) rcs $@; \
|
||||||
|
touch $@; \
|
||||||
|
fi
|
||||||
|
CLEAN += $(RUST_HUF_C_MODE_FILE) $(RUST_HUF_C_MODE_STAMP)
|
||||||
|
|
||||||
ifeq ($(shell $(CC) -v 2>&1 | $(GREP) -c "gcc version "), 1)
|
ifeq ($(shell $(CC) -v 2>&1 | $(GREP) -c "gcc version "), 1)
|
||||||
ALIGN_LOOP = -falign-loops=32
|
ALIGN_LOOP = -falign-loops=32
|
||||||
else
|
else
|
||||||
@@ -328,6 +347,10 @@ CLEAN += zstd-dictBuilder
|
|||||||
zstd-dictBuilder: $(ZSTDLIB_COMMON_SRC) $(ZSTDLIB_COMPRESS_SRC) $(ZDICT_SRC) zstdcli.c util.c timefn.c fileio.c fileio_asyncio.c dibio.c $(RUST_STATICLIB)
|
zstd-dictBuilder: $(ZSTDLIB_COMMON_SRC) $(ZSTDLIB_COMPRESS_SRC) $(ZDICT_SRC) zstdcli.c util.c timefn.c fileio.c fileio_asyncio.c dibio.c $(RUST_STATICLIB)
|
||||||
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODECOMPRESS -DZSTD_NOTRACE $^ -o $@$(EXT)
|
$(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODECOMPRESS -DZSTD_NOTRACE $^ -o $@$(EXT)
|
||||||
|
|
||||||
|
RUST_DIRECT_LINK_TARGETS := zstd32 zstd-nolegacy zstd-small zstd-frugal \
|
||||||
|
zstd-decompress zstd-compress zstd-dictBuilder
|
||||||
|
$(RUST_DIRECT_LINK_TARGETS): $(RUST_HUF_C_MODE_STAMP)
|
||||||
|
|
||||||
CLEAN += zstdmt
|
CLEAN += zstdmt
|
||||||
zstdmt: zstd
|
zstdmt: zstd
|
||||||
ln -sf zstd zstdmt
|
ln -sf zstd zstdmt
|
||||||
|
|||||||
+3
-3
@@ -45,9 +45,9 @@ preprocessor behavior stay available during the transition.
|
|||||||
|
|
||||||
The test and program makefiles select an archive directory for the active C
|
The test and program makefiles select an archive directory for the active C
|
||||||
configuration: default, forced HUF X1/X2, and the matching Rust target for
|
configuration: default, forced HUF X1/X2, and the matching Rust target for
|
||||||
32-bit C binaries. They rebuild the selected archive and relink the executable
|
32-bit C binaries. When the HUF mode changes, they also rebuild cached C
|
||||||
when a Rust source changes, so original C tests do not accidentally use a
|
outputs before linking. This prevents original C tests from using a stale or
|
||||||
stale or configuration-incompatible implementation.
|
configuration-incompatible implementation.
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,25 @@ $(RUST_STATICLIB): $(RUST_SOURCES)
|
|||||||
$(RUST_STATICLIB_32): $(RUST_SOURCES)
|
$(RUST_STATICLIB_32): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_CARGO_FLAGS) --target $(RUST_TARGET_32)
|
$(CARGO) build $(RUST_CARGO_FLAGS) --target $(RUST_TARGET_32)
|
||||||
|
|
||||||
|
# These test objects have flat filenames, unlike the configuration-hashed
|
||||||
|
# program objects. Track the HUF mode separately so a C object set compiled
|
||||||
|
# for one decoder is never relinked with a Rust archive for another decoder.
|
||||||
|
# The stamp is an empty archive, so normal linker `$^` recipes can consume it.
|
||||||
|
RUST_HUF_C_MODE_FILE := $(RUST_DIR)/target/.huf-c-mode-tests
|
||||||
|
RUST_HUF_C_MODE_STAMP := $(RUST_DIR)/target/.huf-c-mode-tests.a
|
||||||
|
.PHONY: FORCE_RUST_HUF_C_MODE
|
||||||
|
FORCE_RUST_HUF_C_MODE:
|
||||||
|
$(RUST_HUF_C_MODE_STAMP): FORCE_RUST_HUF_C_MODE
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@if test ! -r $(RUST_HUF_C_MODE_FILE) \
|
||||||
|
|| test "$$(cat $(RUST_HUF_C_MODE_FILE))" != "$(RUST_BUILD_CONFIG)" \
|
||||||
|
|| test ! -f $@; then \
|
||||||
|
printf '%s\n' "$(RUST_BUILD_CONFIG)" > $(RUST_HUF_C_MODE_FILE); \
|
||||||
|
$(AR) rcs $@; \
|
||||||
|
touch $@; \
|
||||||
|
fi
|
||||||
|
CLEAN += $(RUST_HUF_C_MODE_FILE) $(RUST_HUF_C_MODE_STAMP)
|
||||||
|
|
||||||
DEBUGFLAGS += -g -Wno-c++-compat
|
DEBUGFLAGS += -g -Wno-c++-compat
|
||||||
CPPFLAGS += -I$(LIB_SRCDIR) -I$(LIB_SRCDIR)/common -I$(LIB_SRCDIR)/compress -I$(LIB_SRCDIR)/legacy \
|
CPPFLAGS += -I$(LIB_SRCDIR) -I$(LIB_SRCDIR)/common -I$(LIB_SRCDIR)/compress -I$(LIB_SRCDIR)/legacy \
|
||||||
-I$(LIB_SRCDIR)/dictBuilder -I$(LIB_SRCDIR)/deprecated -I$(PRGDIR) \
|
-I$(LIB_SRCDIR)/dictBuilder -I$(LIB_SRCDIR)/deprecated -I$(PRGDIR) \
|
||||||
@@ -118,6 +137,8 @@ ZSTDMT_OBJ4 := $(subst $(LIB_SRCDIR)/legacy/,zstdmt_l_,$(ZSTDMT_OBJ3))
|
|||||||
ZSTDMT_OBJ5 := $(ZSTDMT_OBJ4:.c=.o)
|
ZSTDMT_OBJ5 := $(ZSTDMT_OBJ4:.c=.o)
|
||||||
ZSTDMT_OBJECTS := $(ZSTDMT_OBJ5:.S=.o)
|
ZSTDMT_OBJECTS := $(ZSTDMT_OBJ5:.S=.o)
|
||||||
|
|
||||||
|
$(ZSTD_OBJECTS) $(ZSTDMT_OBJECTS): $(RUST_HUF_C_MODE_STAMP)
|
||||||
|
|
||||||
# Define *.exe as extension for Windows systems
|
# Define *.exe as extension for Windows systems
|
||||||
ifneq (,$(filter Windows%,$(OS)))
|
ifneq (,$(filter Windows%,$(OS)))
|
||||||
EXT =.exe
|
EXT =.exe
|
||||||
@@ -311,6 +332,8 @@ $(RUST_LINK_TARGETS): $(RUST_STATICLIB)
|
|||||||
RUST_LINK_TARGETS_32 := fullbench32 fuzzer32 zstreamtest32
|
RUST_LINK_TARGETS_32 := fullbench32 fuzzer32 zstreamtest32
|
||||||
$(RUST_LINK_TARGETS_32): $(RUST_STATICLIB_32)
|
$(RUST_LINK_TARGETS_32): $(RUST_STATICLIB_32)
|
||||||
|
|
||||||
|
$(RUST_LINK_TARGETS) $(RUST_LINK_TARGETS_32): $(RUST_HUF_C_MODE_STAMP)
|
||||||
|
|
||||||
.PHONY: versionsTest
|
.PHONY: versionsTest
|
||||||
versionsTest: clean
|
versionsTest: clean
|
||||||
$(PYTHON) test-zstd-versions.py
|
$(PYTHON) test-zstd-versions.py
|
||||||
|
|||||||
Reference in New Issue
Block a user