build(rust): add legacy feature scaffolding
The legacy decoders (lib/legacy/zstd_v01.c .. zstd_v07.c) are next in the Rust migration. Each of those files is a frozen snapshot of the FSE/Huff0 entropy coders and frame logic of one historical release, so their ports must not reuse the modern Rust entropy modules and must not share code with each other: outputs and error codes have to stay byte-identical to the frozen C forever. This commit installs the build-system scaffolding so seven per-version ports can land independently, each adding only its own module file plus a one-line registration in rust/src/legacy/mod.rs. Cargo grows features legacy-v01 .. legacy-v07. They are never default features: the C build defaults differ per build system, so each build system passes the list explicitly, derived from its own legacy configuration: - lib/Makefile and programs/Makefile map ZSTD_LEGACY_SUPPORT=N to the features for versions N..7 (0 disables legacy), mirroring the ZSTD_LEGACY_FILES selection in lib/libzstd.mk. - tests/Makefile always enables all seven features because its ZSTDLEGACY_FILES wildcard compiles every lib/legacy/*.c regardless of the dispatch level. - build/meson maps legacy_level exactly like the makefiles; build/cmake enables all seven whenever ZSTD_LEGACY_SUPPORT is ON because it always compiles all seven C files (ZSTD_LEGACY_LEVEL only selects the C dispatch). Every build system also encodes the legacy selection in the Rust target directory name (e.g. c1-d1-default-legacy5), for the same reason the HUF mode is encoded there: a cached archive built for one configuration must never be linked into a build expecting another. In tests/Makefile the legacy level additionally flows into the existing HUF C-mode stamp, so the flat C test objects (which bake -DZSTD_LEGACY_SUPPORT into the dispatch) are rebuilt whenever the level changes. In programs/Makefile the compress-only, decompress-only, and CLI archives keep level-independent directories (RUST_HUF_MODE) because they are only linked into ZSTD_LEGACY_SUPPORT=0 program variants and carry no legacy features. A feature whose version has not been ported yet gates nothing: the module registration in rust/src/legacy/mod.rs is added by each port, so enabling e.g. legacy-v05 today simply leaves that decoder in C. This is what makes mixed C/Rust legacy levels link cleanly while the seven ports land in any order. Test plan: - cd rust && cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test --all-targets - cargo clippy with --no-default-features --features decompression,legacy-v01 and with all seven legacy features - make -C tests fuzzer && ./tests/fuzzer -i1 --no-big-tests - make -C tests test-rust-lib-smoke; make -C tests test-legacy - make -C lib libzstd.a with ZSTD_LEGACY_SUPPORT=0, 1 and default (5) - cmake configure and meson setup (including -Dlegacy_level=1) emit the expected --features lists and legacy-suffixed target directories
This commit is contained in:
@@ -169,6 +169,18 @@ elseif(_zstd_huf_force_x2)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# This CMake build compiles every lib/legacy/zstd_v0N.c whenever legacy
|
||||||
|
# support is enabled (ZSTD_LEGACY_LEVEL only selects the C dispatch), so the
|
||||||
|
# Rust archive enables every per-version legacy feature to match. The build
|
||||||
|
# configuration encodes the switch so archives never mix.
|
||||||
|
set(_zstd_rust_legacy 0)
|
||||||
|
if(ZSTD_LEGACY_SUPPORT)
|
||||||
|
set(_zstd_rust_legacy 1)
|
||||||
|
list(APPEND _zstd_rust_features
|
||||||
|
legacy-v01 legacy-v02 legacy-v03 legacy-v04
|
||||||
|
legacy-v05 legacy-v06 legacy-v07)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(_zstd_rust_target "${ZSTD_RUST_TARGET}")
|
set(_zstd_rust_target "${ZSTD_RUST_TARGET}")
|
||||||
if(NOT _zstd_rust_target AND CMAKE_SYSTEM_NAME STREQUAL "Linux"
|
if(NOT _zstd_rust_target AND CMAKE_SYSTEM_NAME STREQUAL "Linux"
|
||||||
AND CMAKE_SIZEOF_VOID_P EQUAL 4)
|
AND CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
@@ -195,7 +207,7 @@ if(_zstd_rust_features)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(_zstd_rust_build_config
|
set(_zstd_rust_build_config
|
||||||
"c${_zstd_rust_compression}-d${_zstd_rust_decompression}-b${_zstd_rust_dictbuilder}-${_zstd_rust_huf_mode}")
|
"c${_zstd_rust_compression}-d${_zstd_rust_decompression}-b${_zstd_rust_dictbuilder}-${_zstd_rust_huf_mode}-legacy${_zstd_rust_legacy}")
|
||||||
set(ZSTD_RUST_MANIFEST "${ZSTD_SOURCE_DIR}/rust/Cargo.toml")
|
set(ZSTD_RUST_MANIFEST "${ZSTD_SOURCE_DIR}/rust/Cargo.toml")
|
||||||
set(ZSTD_RUST_TARGET_DIR
|
set(ZSTD_RUST_TARGET_DIR
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/rust-target/${_zstd_rust_build_config}")
|
"${CMAKE_CURRENT_BINARY_DIR}/rust-target/${_zstd_rust_build_config}")
|
||||||
|
|||||||
@@ -88,6 +88,16 @@ elif rust_huf_force_x2
|
|||||||
rust_huf_c_args += '-DHUF_FORCE_DECOMPRESS_X2'
|
rust_huf_c_args += '-DHUF_FORCE_DECOMPRESS_X2'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Mirror the legacy source selection below: legacy_level N compiles
|
||||||
|
# lib/legacy/zstd_v0N.c .. zstd_v07.c, so the Rust archive enables the
|
||||||
|
# matching per-version features. The build configuration encodes the level
|
||||||
|
# so archives built for different legacy levels never mix.
|
||||||
|
foreach i : [1, 2, 3, 4, 5, 6, 7]
|
||||||
|
if legacy_level != 0 and legacy_level <= i
|
||||||
|
rust_features += 'legacy-v0@0@'.format(i)
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
|
||||||
rust_target = get_option('zstd_rust_target')
|
rust_target = get_option('zstd_rust_target')
|
||||||
if rust_target == ''
|
if rust_target == ''
|
||||||
if host_machine_os == os_linux and \
|
if host_machine_os == os_linux and \
|
||||||
@@ -98,7 +108,7 @@ if rust_target == ''
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
rust_build_config = 'c1-d1-b1-' + rust_huf_mode
|
rust_build_config = 'c1-d1-b1-' + rust_huf_mode + '-legacy@0@'.format(legacy_level)
|
||||||
rust_target_dir = join_paths(meson.current_build_dir(), 'rust-target', rust_build_config)
|
rust_target_dir = join_paths(meson.current_build_dir(), 'rust-target', rust_build_config)
|
||||||
is_msvc = cc_id == compiler_msvc or cc_id == 'clang-cl'
|
is_msvc = cc_id == compiler_msvc or cc_id == 'clang-cl'
|
||||||
rust_staticlib_name = is_msvc ? 'zstd_rs.lib' : 'libzstd_rs.a'
|
rust_staticlib_name = is_msvc ? 'zstd_rs.lib' : 'libzstd_rs.a'
|
||||||
|
|||||||
@@ -104,6 +104,18 @@ ifneq ($(ZSTD_LIB_DECOMPRESSION),0)
|
|||||||
RUST_CARGO_FEATURES += $(RUST_HUF_FEATURE)
|
RUST_CARGO_FEATURES += $(RUST_HUF_FEATURE)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Legacy decoders follow the ZSTD_LEGACY_FILES selection exactly: level N
|
||||||
|
# enables versions v0.N .. v0.7 (0 disables legacy). The build directory
|
||||||
|
# also encodes the level, so archives for different legacy levels never mix.
|
||||||
|
RUST_LEGACY_FEATURES :=
|
||||||
|
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||||
|
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
||||||
|
RUST_LEGACY_FEATURES := $(addprefix legacy-v0,$(wordlist $(ZSTD_LEGACY_SUPPORT),7,1 2 3 4 5 6 7))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
RUST_CARGO_FEATURES += $(RUST_LEGACY_FEATURES)
|
||||||
|
RUST_BUILD_CONFIG := $(RUST_BUILD_CONFIG)-legacy$(ZSTD_LEGACY_SUPPORT)
|
||||||
RUST_CARGO_FEATURES := $(subst $(space),$(comma),$(strip $(RUST_CARGO_FEATURES)))
|
RUST_CARGO_FEATURES := $(subst $(space),$(comma),$(strip $(RUST_CARGO_FEATURES)))
|
||||||
|
|
||||||
RUST_TARGET ?=
|
RUST_TARGET ?=
|
||||||
|
|||||||
+29
-9
@@ -56,16 +56,33 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
RUST_HUF_FEATURE :=
|
RUST_HUF_FEATURE :=
|
||||||
RUST_BUILD_CONFIG := default
|
RUST_HUF_MODE := default
|
||||||
ifneq ($(RUST_HUF_FORCE_X1),0)
|
ifneq ($(RUST_HUF_FORCE_X1),0)
|
||||||
RUST_HUF_FEATURE := huf-force-decompress-x1
|
RUST_HUF_FEATURE := huf-force-decompress-x1
|
||||||
RUST_BUILD_CONFIG := huf-force-decompress-x1
|
RUST_HUF_MODE := huf-force-decompress-x1
|
||||||
endif
|
endif
|
||||||
ifneq ($(RUST_HUF_FORCE_X2),0)
|
ifneq ($(RUST_HUF_FORCE_X2),0)
|
||||||
RUST_HUF_FEATURE := huf-force-decompress-x2
|
RUST_HUF_FEATURE := huf-force-decompress-x2
|
||||||
RUST_BUILD_CONFIG := huf-force-decompress-x2
|
RUST_HUF_MODE := huf-force-decompress-x2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# The full-featured zstd program mirrors libzstd.mk's legacy file selection:
|
||||||
|
# ZSTD_LEGACY_SUPPORT=N compiles v0.N .. v0.7, so the Rust archive enables the
|
||||||
|
# matching per-version features. The archive directory encodes the level so
|
||||||
|
# builds for different legacy levels never share cached Rust outputs. The
|
||||||
|
# compress-only, decompress-only, and CLI archives further below are used
|
||||||
|
# solely by ZSTD_LEGACY_SUPPORT=0 program variants and stay legacy-free.
|
||||||
|
empty :=
|
||||||
|
space := $(empty) $(empty)
|
||||||
|
comma := ,
|
||||||
|
RUST_LEGACY_FEATURES :=
|
||||||
|
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||||
|
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
||||||
|
RUST_LEGACY_FEATURES := $(addprefix legacy-v0,$(wordlist $(ZSTD_LEGACY_SUPPORT),7,1 2 3 4 5 6 7))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
RUST_BUILD_CONFIG := $(RUST_HUF_MODE)-legacy$(ZSTD_LEGACY_SUPPORT)
|
||||||
|
|
||||||
RUST_TARGET_DIR := $(RUST_DIR)/target/$(RUST_BUILD_CONFIG)
|
RUST_TARGET_DIR := $(RUST_DIR)/target/$(RUST_BUILD_CONFIG)
|
||||||
RUST_STATICLIB := $(RUST_TARGET_DIR)/release/libzstd_rs.a
|
RUST_STATICLIB := $(RUST_TARGET_DIR)/release/libzstd_rs.a
|
||||||
RUST_TARGET_32 ?= i686-unknown-linux-gnu
|
RUST_TARGET_32 ?= i686-unknown-linux-gnu
|
||||||
@@ -76,6 +93,9 @@ RUST_CARGO_FLAGS += --features compression,decompression,dict-builder
|
|||||||
ifneq ($(RUST_HUF_FEATURE),)
|
ifneq ($(RUST_HUF_FEATURE),)
|
||||||
RUST_CARGO_FLAGS += --features $(RUST_HUF_FEATURE)
|
RUST_CARGO_FLAGS += --features $(RUST_HUF_FEATURE)
|
||||||
endif
|
endif
|
||||||
|
ifneq ($(RUST_LEGACY_FEATURES),)
|
||||||
|
RUST_CARGO_FLAGS += --features $(subst $(space),$(comma),$(strip $(RUST_LEGACY_FEATURES)))
|
||||||
|
endif
|
||||||
|
|
||||||
$(RUST_STATICLIB): $(RUST_SOURCES)
|
$(RUST_STATICLIB): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_CARGO_FLAGS)
|
$(CARGO) build $(RUST_CARGO_FLAGS)
|
||||||
@@ -83,7 +103,7 @@ $(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)
|
||||||
|
|
||||||
RUST_CLI_BUILD_CONFIG := cli-c1-d1-$(RUST_BUILD_CONFIG)
|
RUST_CLI_BUILD_CONFIG := cli-c1-d1-$(RUST_HUF_MODE)
|
||||||
RUST_CLI_TARGET_DIR := $(RUST_DIR)/target/$(RUST_CLI_BUILD_CONFIG)
|
RUST_CLI_TARGET_DIR := $(RUST_DIR)/target/$(RUST_CLI_BUILD_CONFIG)
|
||||||
RUST_CLI_STATICLIB := $(RUST_CLI_TARGET_DIR)/release/libzstd_cli_rs.a
|
RUST_CLI_STATICLIB := $(RUST_CLI_TARGET_DIR)/release/libzstd_cli_rs.a
|
||||||
RUST_CLI_STATICLIB_32 := $(RUST_CLI_TARGET_DIR)/$(RUST_TARGET_32)/release/libzstd_cli_rs.a
|
RUST_CLI_STATICLIB_32 := $(RUST_CLI_TARGET_DIR)/$(RUST_TARGET_32)/release/libzstd_cli_rs.a
|
||||||
@@ -97,7 +117,7 @@ $(RUST_CLI_STATICLIB): $(RUST_CLI_SOURCES)
|
|||||||
$(RUST_CLI_STATICLIB_32): $(RUST_CLI_SOURCES)
|
$(RUST_CLI_STATICLIB_32): $(RUST_CLI_SOURCES)
|
||||||
$(CARGO) build $(RUST_CLI_CARGO_FLAGS) --target $(RUST_TARGET_32)
|
$(CARGO) build $(RUST_CLI_CARGO_FLAGS) --target $(RUST_TARGET_32)
|
||||||
|
|
||||||
RUST_DECOMPRESS_BUILD_CONFIG := lib-c0-d1-b0-$(RUST_BUILD_CONFIG)
|
RUST_DECOMPRESS_BUILD_CONFIG := lib-c0-d1-b0-$(RUST_HUF_MODE)
|
||||||
RUST_DECOMPRESS_TARGET_DIR := $(RUST_DIR)/target/$(RUST_DECOMPRESS_BUILD_CONFIG)
|
RUST_DECOMPRESS_TARGET_DIR := $(RUST_DIR)/target/$(RUST_DECOMPRESS_BUILD_CONFIG)
|
||||||
RUST_DECOMPRESS_STATICLIB := $(RUST_DECOMPRESS_TARGET_DIR)/release/libzstd_rs.a
|
RUST_DECOMPRESS_STATICLIB := $(RUST_DECOMPRESS_TARGET_DIR)/release/libzstd_rs.a
|
||||||
RUST_DECOMPRESS_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
RUST_DECOMPRESS_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
||||||
@@ -110,7 +130,7 @@ endif
|
|||||||
$(RUST_DECOMPRESS_STATICLIB): $(RUST_SOURCES)
|
$(RUST_DECOMPRESS_STATICLIB): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_DECOMPRESS_CARGO_FLAGS)
|
$(CARGO) build $(RUST_DECOMPRESS_CARGO_FLAGS)
|
||||||
|
|
||||||
RUST_DECOMPRESS_CLI_BUILD_CONFIG := cli-c0-d1-$(RUST_BUILD_CONFIG)
|
RUST_DECOMPRESS_CLI_BUILD_CONFIG := cli-c0-d1-$(RUST_HUF_MODE)
|
||||||
RUST_DECOMPRESS_CLI_TARGET_DIR := $(RUST_DIR)/target/$(RUST_DECOMPRESS_CLI_BUILD_CONFIG)
|
RUST_DECOMPRESS_CLI_TARGET_DIR := $(RUST_DIR)/target/$(RUST_DECOMPRESS_CLI_BUILD_CONFIG)
|
||||||
RUST_DECOMPRESS_CLI_STATICLIB := $(RUST_DECOMPRESS_CLI_TARGET_DIR)/release/libzstd_cli_rs.a
|
RUST_DECOMPRESS_CLI_STATICLIB := $(RUST_DECOMPRESS_CLI_TARGET_DIR)/release/libzstd_cli_rs.a
|
||||||
RUST_DECOMPRESS_CLI_CARGO_FLAGS := --manifest-path $(RUST_CLI_MANIFEST) --release \
|
RUST_DECOMPRESS_CLI_CARGO_FLAGS := --manifest-path $(RUST_CLI_MANIFEST) --release \
|
||||||
@@ -120,7 +140,7 @@ RUST_DECOMPRESS_CLI_CARGO_FLAGS := --manifest-path $(RUST_CLI_MANIFEST) --releas
|
|||||||
$(RUST_DECOMPRESS_CLI_STATICLIB): $(RUST_CLI_SOURCES)
|
$(RUST_DECOMPRESS_CLI_STATICLIB): $(RUST_CLI_SOURCES)
|
||||||
$(CARGO) build $(RUST_DECOMPRESS_CLI_CARGO_FLAGS)
|
$(CARGO) build $(RUST_DECOMPRESS_CLI_CARGO_FLAGS)
|
||||||
|
|
||||||
RUST_COMPRESS_BUILD_CONFIG := lib-c1-d0-b0-$(RUST_BUILD_CONFIG)
|
RUST_COMPRESS_BUILD_CONFIG := lib-c1-d0-b0-$(RUST_HUF_MODE)
|
||||||
RUST_COMPRESS_TARGET_DIR := $(RUST_DIR)/target/$(RUST_COMPRESS_BUILD_CONFIG)
|
RUST_COMPRESS_TARGET_DIR := $(RUST_DIR)/target/$(RUST_COMPRESS_BUILD_CONFIG)
|
||||||
RUST_COMPRESS_STATICLIB := $(RUST_COMPRESS_TARGET_DIR)/release/libzstd_rs.a
|
RUST_COMPRESS_STATICLIB := $(RUST_COMPRESS_TARGET_DIR)/release/libzstd_rs.a
|
||||||
RUST_COMPRESS_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
RUST_COMPRESS_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
||||||
@@ -130,7 +150,7 @@ RUST_COMPRESS_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
|||||||
$(RUST_COMPRESS_STATICLIB): $(RUST_SOURCES)
|
$(RUST_COMPRESS_STATICLIB): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_COMPRESS_CARGO_FLAGS)
|
$(CARGO) build $(RUST_COMPRESS_CARGO_FLAGS)
|
||||||
|
|
||||||
RUST_DICTBUILDER_BUILD_CONFIG := lib-c1-d0-b1-$(RUST_BUILD_CONFIG)
|
RUST_DICTBUILDER_BUILD_CONFIG := lib-c1-d0-b1-$(RUST_HUF_MODE)
|
||||||
RUST_DICTBUILDER_TARGET_DIR := $(RUST_DIR)/target/$(RUST_DICTBUILDER_BUILD_CONFIG)
|
RUST_DICTBUILDER_TARGET_DIR := $(RUST_DIR)/target/$(RUST_DICTBUILDER_BUILD_CONFIG)
|
||||||
RUST_DICTBUILDER_STATICLIB := $(RUST_DICTBUILDER_TARGET_DIR)/release/libzstd_rs.a
|
RUST_DICTBUILDER_STATICLIB := $(RUST_DICTBUILDER_TARGET_DIR)/release/libzstd_rs.a
|
||||||
RUST_DICTBUILDER_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
RUST_DICTBUILDER_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
||||||
@@ -141,7 +161,7 @@ RUST_DICTBUILDER_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
|||||||
$(RUST_DICTBUILDER_STATICLIB): $(RUST_SOURCES)
|
$(RUST_DICTBUILDER_STATICLIB): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_DICTBUILDER_CARGO_FLAGS)
|
$(CARGO) build $(RUST_DICTBUILDER_CARGO_FLAGS)
|
||||||
|
|
||||||
RUST_COMPRESS_CLI_BUILD_CONFIG := cli-c1-d0-$(RUST_BUILD_CONFIG)
|
RUST_COMPRESS_CLI_BUILD_CONFIG := cli-c1-d0-$(RUST_HUF_MODE)
|
||||||
RUST_COMPRESS_CLI_TARGET_DIR := $(RUST_DIR)/target/$(RUST_COMPRESS_CLI_BUILD_CONFIG)
|
RUST_COMPRESS_CLI_TARGET_DIR := $(RUST_DIR)/target/$(RUST_COMPRESS_CLI_BUILD_CONFIG)
|
||||||
RUST_COMPRESS_CLI_STATICLIB := $(RUST_COMPRESS_CLI_TARGET_DIR)/release/libzstd_cli_rs.a
|
RUST_COMPRESS_CLI_STATICLIB := $(RUST_COMPRESS_CLI_TARGET_DIR)/release/libzstd_cli_rs.a
|
||||||
RUST_COMPRESS_CLI_CARGO_FLAGS := --manifest-path $(RUST_CLI_MANIFEST) --release \
|
RUST_COMPRESS_CLI_CARGO_FLAGS := --manifest-path $(RUST_CLI_MANIFEST) --release \
|
||||||
|
|||||||
@@ -13,6 +13,18 @@ decompression = []
|
|||||||
dict-builder = []
|
dict-builder = []
|
||||||
huf-force-decompress-x1 = []
|
huf-force-decompress-x1 = []
|
||||||
huf-force-decompress-x2 = []
|
huf-force-decompress-x2 = []
|
||||||
|
# Legacy-format decoders (zstd v0.1 .. v0.7). Never default features: the
|
||||||
|
# build systems map ZSTD_LEGACY_SUPPORT=N to the features for versions >= N,
|
||||||
|
# exactly mirroring which lib/legacy/zstd_v0N.c files the C build compiles.
|
||||||
|
# A feature whose version is not yet ported to Rust gates nothing; the
|
||||||
|
# original C file still provides that decoder.
|
||||||
|
legacy-v01 = []
|
||||||
|
legacy-v02 = []
|
||||||
|
legacy-v03 = []
|
||||||
|
legacy-v04 = []
|
||||||
|
legacy-v05 = []
|
||||||
|
legacy-v06 = []
|
||||||
|
legacy-v07 = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|||||||
+42
-5
@@ -57,6 +57,9 @@ zstd ABI:
|
|||||||
- `pool` implements the bounded worker pool used by multithreaded compression.
|
- `pool` implements the bounded worker pool used by multithreaded compression.
|
||||||
- Dictionary support
|
- Dictionary support
|
||||||
- `zstd_ddict` owns, loads, copies, and references decode dictionaries.
|
- `zstd_ddict` owns, loads, copies, and references decode dictionaries.
|
||||||
|
- Legacy decoding
|
||||||
|
- `legacy` hosts one frozen module per historical format (v0.1 through
|
||||||
|
v0.7). No version has been ported yet; all decoders are still C.
|
||||||
- Block decompression
|
- Block decompression
|
||||||
- `zstd_decompress_block` decodes literal and sequence sections, maintains
|
- `zstd_decompress_block` decodes literal and sequence sections, maintains
|
||||||
FSE/Huffman repeat state, and executes compressed-block sequences.
|
FSE/Huffman repeat state, and executes compressed-block sequences.
|
||||||
@@ -80,11 +83,45 @@ zstd ABI:
|
|||||||
Rust parser through the `ZSTD_NOBENCH`-gated bridge in `zstdcli.c`.
|
Rust parser through the `ZSTD_NOBENCH`-gated bridge in `zstdcli.c`.
|
||||||
|
|
||||||
The optimal block matcher, high-level frame compression, dictionary-building
|
The optimal block matcher, high-level frame compression, dictionary-building
|
||||||
except suffix-array construction, legacy decoding callbacks, benchmark
|
except suffix-array construction, the legacy v0.1-v0.7 decoders, benchmark
|
||||||
orchestration (`benchzstd`), and the CLI
|
orchestration (`benchzstd`), and the CLI file-I/O backend are still C. They
|
||||||
file-I/O backend are still C. They must move before the rewrite is complete.
|
must move before the rewrite is complete. Keeping that boundary explicit
|
||||||
Keeping that boundary explicit prevents a passing hybrid build from being
|
prevents a passing hybrid build from being mistaken for the final all-Rust
|
||||||
mistaken for the final all-Rust result.
|
result.
|
||||||
|
|
||||||
|
## Legacy decoding
|
||||||
|
|
||||||
|
Each `lib/legacy/zstd_v0N.c` file is a frozen snapshot of the entropy coders
|
||||||
|
and frame logic of one historical release. The Rust ports in `src/legacy/`
|
||||||
|
keep that property: every version owns its own frozen FSE/Huff0 and frame
|
||||||
|
logic, ported line by line, and must never reuse the modern entropy modules
|
||||||
|
or share code with other legacy versions. Outputs and error codes must be
|
||||||
|
byte-identical to the original C files. Their only shared dependency is the
|
||||||
|
`errors` module, matching the C files' `error_private.h` include.
|
||||||
|
|
||||||
|
Cargo features `legacy-v01` .. `legacy-v07` gate the per-version modules and
|
||||||
|
are never default features. The build systems derive the feature list from
|
||||||
|
the C configuration:
|
||||||
|
|
||||||
|
- `lib/Makefile` and `programs/Makefile` map `ZSTD_LEGACY_SUPPORT=N` to the
|
||||||
|
features for versions >= N (0 disables legacy), matching the
|
||||||
|
`ZSTD_LEGACY_FILES` selection in `lib/libzstd.mk`.
|
||||||
|
- `tests/Makefile` always enables all seven features because the test
|
||||||
|
objects compile every `lib/legacy/*.c` file regardless of dispatch level.
|
||||||
|
- `build/meson` maps `legacy_level` like the makefiles; `build/cmake`
|
||||||
|
enables all seven whenever `ZSTD_LEGACY_SUPPORT` is on because it always
|
||||||
|
compiles all seven C files.
|
||||||
|
|
||||||
|
Every build system also encodes the legacy selection in the Rust target
|
||||||
|
directory name (for example `c1-d1-default-legacy5`), for the same reason the
|
||||||
|
HUF mode is encoded there: a cached archive built for one configuration must
|
||||||
|
never be linked into a build that expects another.
|
||||||
|
|
||||||
|
A feature whose version has not been ported yet gates nothing; the original
|
||||||
|
C file still provides that decoder, so mixed C/Rust legacy levels link
|
||||||
|
cleanly. Porting a version means adding `src/legacy/zstd_v0N.rs`, registering
|
||||||
|
it in `src/legacy/mod.rs` behind its feature, and reducing
|
||||||
|
`lib/legacy/zstd_v0N.c` to a declaration-only shim.
|
||||||
|
|
||||||
## Compatibility boundary
|
## Compatibility boundary
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
//! Frozen decoders for the legacy zstd formats (v0.1 through v0.7).
|
||||||
|
//!
|
||||||
|
//! Frozen-decoder policy
|
||||||
|
//! =====================
|
||||||
|
//!
|
||||||
|
//! Each `lib/legacy/zstd_v0N.c` translation unit is a self-contained snapshot
|
||||||
|
//! of the entropy coders and frame logic of that historical release. The
|
||||||
|
//! Rust ports mirror that property:
|
||||||
|
//!
|
||||||
|
//! - Every version keeps its own frozen FSE/Huff0 and frame logic. The
|
||||||
|
//! modern `fse_decompress`, `huf_decompress`, `bitstream`, or `mem`
|
||||||
|
//! modules must NOT be reused here, and legacy versions must not share
|
||||||
|
//! code with each other, even where functions look identical. The legacy
|
||||||
|
//! formats are frozen; the modern modules keep evolving.
|
||||||
|
//! - Ports are line-by-line translations of the corresponding C file: same
|
||||||
|
//! table layouts, same arithmetic, same error codes. Outputs must be
|
||||||
|
//! byte-identical to the C implementation, including error behavior.
|
||||||
|
//! - The only shared dependency is `crate::errors`, because the C files
|
||||||
|
//! include `error_private.h` for the public `ZSTD_ErrorCode` values.
|
||||||
|
//!
|
||||||
|
//! Registration
|
||||||
|
//! ============
|
||||||
|
//!
|
||||||
|
//! Cargo features `legacy-v01` .. `legacy-v07` are all declared in
|
||||||
|
//! `Cargo.toml`. The build systems always pass the feature list derived
|
||||||
|
//! from the C configuration (`ZSTD_LEGACY_SUPPORT=N` enables versions N
|
||||||
|
//! and newer), so a feature may be enabled before its port exists. A version
|
||||||
|
//! without a Rust module simply stays implemented by its C file.
|
||||||
|
//!
|
||||||
|
//! To port version `v0N`: add `zstd_v0N.rs` next to this file, reduce
|
||||||
|
//! `lib/legacy/zstd_v0N.c` to a declaration-only shim, and register the
|
||||||
|
//! module here with exactly one line:
|
||||||
|
//!
|
||||||
|
//! ```text
|
||||||
|
//! #[cfg(feature = "legacy-v0N")]
|
||||||
|
//! pub mod zstd_v0N;
|
||||||
|
//! ```
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ pub mod hist;
|
|||||||
pub mod huf_compress;
|
pub mod huf_compress;
|
||||||
#[cfg(feature = "decompression")]
|
#[cfg(feature = "decompression")]
|
||||||
pub mod huf_decompress;
|
pub mod huf_decompress;
|
||||||
|
pub mod legacy;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
pub mod threading;
|
pub mod threading;
|
||||||
|
|||||||
+12
-3
@@ -65,16 +65,24 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
RUST_HUF_FEATURE :=
|
RUST_HUF_FEATURE :=
|
||||||
RUST_BUILD_CONFIG := default
|
RUST_HUF_MODE := default
|
||||||
ifneq ($(RUST_HUF_FORCE_X1),0)
|
ifneq ($(RUST_HUF_FORCE_X1),0)
|
||||||
RUST_HUF_FEATURE := huf-force-decompress-x1
|
RUST_HUF_FEATURE := huf-force-decompress-x1
|
||||||
RUST_BUILD_CONFIG := huf-force-decompress-x1
|
RUST_HUF_MODE := huf-force-decompress-x1
|
||||||
endif
|
endif
|
||||||
ifneq ($(RUST_HUF_FORCE_X2),0)
|
ifneq ($(RUST_HUF_FORCE_X2),0)
|
||||||
RUST_HUF_FEATURE := huf-force-decompress-x2
|
RUST_HUF_FEATURE := huf-force-decompress-x2
|
||||||
RUST_BUILD_CONFIG := huf-force-decompress-x2
|
RUST_HUF_MODE := huf-force-decompress-x2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Test binaries compile every lib/legacy/*.c file regardless of the dispatch
|
||||||
|
# level (ZSTDLEGACY_FILES is a plain wildcard below), so the Rust archive must
|
||||||
|
# always carry all ported legacy decoders too. The build configuration still
|
||||||
|
# encodes the level because the flat C objects bake -DZSTD_LEGACY_SUPPORT into
|
||||||
|
# the dispatch code and must never outlive a level change.
|
||||||
|
RUST_LEGACY_FEATURES := legacy-v01,legacy-v02,legacy-v03,legacy-v04,legacy-v05,legacy-v06,legacy-v07
|
||||||
|
RUST_BUILD_CONFIG := $(RUST_HUF_MODE)-legacy$(ZSTD_LEGACY_SUPPORT)
|
||||||
|
|
||||||
RUST_TARGET_DIR := $(RUST_DIR)/target/$(RUST_BUILD_CONFIG)
|
RUST_TARGET_DIR := $(RUST_DIR)/target/$(RUST_BUILD_CONFIG)
|
||||||
RUST_STATICLIB := $(RUST_TARGET_DIR)/release/libzstd_rs.a
|
RUST_STATICLIB := $(RUST_TARGET_DIR)/release/libzstd_rs.a
|
||||||
RUST_TARGET_32 ?= i686-unknown-linux-gnu
|
RUST_TARGET_32 ?= i686-unknown-linux-gnu
|
||||||
@@ -86,6 +94,7 @@ RUST_CARGO_FLAGS := --manifest-path $(RUST_MANIFEST) --release \
|
|||||||
ifneq ($(RUST_HUF_FEATURE),)
|
ifneq ($(RUST_HUF_FEATURE),)
|
||||||
RUST_CARGO_FLAGS += --features $(RUST_HUF_FEATURE)
|
RUST_CARGO_FLAGS += --features $(RUST_HUF_FEATURE)
|
||||||
endif
|
endif
|
||||||
|
RUST_CARGO_FLAGS += --features $(RUST_LEGACY_FEATURES)
|
||||||
|
|
||||||
$(RUST_STATICLIB): $(RUST_SOURCES)
|
$(RUST_STATICLIB): $(RUST_SOURCES)
|
||||||
$(CARGO) build $(RUST_CARGO_FLAGS)
|
$(CARGO) build $(RUST_CARGO_FLAGS)
|
||||||
|
|||||||
Reference in New Issue
Block a user