Stop build_cc from defining options set to OFF - #873
Open
Alexander Theißen (athei) wants to merge 1 commit into
Open
Stop build_cc from defining options set to OFF#873Alexander Theißen (athei) wants to merge 1 commit into
Alexander Theißen (athei) wants to merge 1 commit into
Conversation
`build.rs` passes CMake-style booleans through `define(key, "ON"/"OFF")`. CMake reads `-DKEY=OFF` as "not enabled", but the C preprocessor does not: `-DKEY=OFF` defines `KEY`, and snmalloc guards these options with `#if defined(KEY)` / `#ifdef KEY`. On the `build_cc` path every one of them is therefore enabled precisely when it was meant to be disabled. Two have live consumers in the library: `SNMALLOC_QEMU_WORKAROUND` is on for every `build_cc` build. On 64-bit targets that takes the `sizeclassconfig.h` branch intended for QEMU CI, raising `MIN_CHUNK_BITS` from 14 to 17 and `MAX_SMALL_SIZECLASS_BITS` from 16 to 19, so the slab/chunk split moves from 64 KiB to 512 KiB. On Linux it also trips the `#ifndef` in `pal_linux.h`, dropping the `madvise(MADV_DONTNEED)` fast path for zeroing large blocks and falling back to `memset` on every target, 32-bit included. `SNMALLOC_RUST_LIBC_API` compiles the libc API shims in `rust.cc` unconditionally, exporting symbols the `libc-api` feature is supposed to gate. `USE_SNMALLOC_STATS` is defined too but only reaches test code, so it is harmless here. `SNMALLOC_ENABLE_DYNAMIC_LOADING` and `SNMALLOC_USE_CXX17` have no preprocessor consumer at all; they are CMake options, so on the cc path they are inert in either direction. All five go through the same call, so all five are converted. Adds `define_bool` to `BuilderDefine` rather than fixing the flags one at a time, so the next boolean option cannot reintroduce this. The cc impl emits a bare `-DKEY` only when enabled; the cmake impl keeps passing `ON`/`OFF`, unchanged. This follows what `SNMALLOC_CHECK_LOADS`, `SNMALLOC_PAGEID` and `SNMALLOC_USE_WAIT_ON_ADDRESS` already do by hand with per-flag `cfg(feature = "build_cc")` branches. Verified by grepping the compiler invocation under `CC_ENABLE_DEBUG_OUTPUT=1`. Before, a default `build_cc` build emitted `-DSNMALLOC_QEMU_WORKAROUND=OFF`, `-DSNMALLOC_RUST_LIBC_API=OFF`, `-DUSE_SNMALLOC_STATS=OFF`, `-DSNMALLOC_ENABLE_DYNAMIC_LOADING=OFF` and `-DSNMALLOC_USE_CXX17=OFF`. After, none of them appear; building with `--features qemu,libc-api` emits `-DSNMALLOC_QEMU_WORKAROUND` and `-DSNMALLOC_RUST_LIBC_API` with no value. Binding tests pass on both the cc and cmake paths.
Author
|
@microsoft-github-policy-service agree |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
snmalloc-sys/build.rspasses CMake-style booleans throughdefine(key, "ON"/"OFF"). CMake reads-DKEY=OFFas "not enabled", but the C preprocessor does not:-DKEY=OFFdefinesKEY, and snmalloc guards these options with#if defined(KEY)/#ifdef KEY. So on thebuild_ccpath every one of these options is enabled precisely when it was meant to be disabled. The cmake path is unaffected.Two of the five have live consumers in the library:
SNMALLOC_QEMU_WORKAROUNDis on for everybuild_ccbuild, noqemufeature required. On 64-bit targets that selects theds_core/sizeclassconfig.hbranch intended for QEMU CI, raisingMIN_CHUNK_BITSfrom 14 to 17 andMAX_SMALL_SIZECLASS_BITSfrom 16 to 19, which moves the slab/chunk split from 64 KiB to 512 KiB. On Linux it also trips the#ifndefinpal/pal_linux.h, sozero()loses themadvise(MADV_DONTNEED)fast path for large blocks and falls back tomemseton every architecture, 32-bit included.SNMALLOC_RUST_LIBC_APIcompiles the libc API shims inoverride/rust.ccunconditionally, exporting symbols thelibc-apifeature is meant to gate.The other three are benign but go through the same call:
USE_SNMALLOC_STATSonly reaches test code, andSNMALLOC_ENABLE_DYNAMIC_LOADING/SNMALLOC_USE_CXX17have no preprocessor consumer at all (they are CMake options, inert on the cc path in either direction).The fix
Adds
define_booltoBuilderDefinerather than patching the flags one at a time, so a future boolean option cannot reintroduce this. The cc impl emits a bare-DKEYonly when the option is on; the cmake impl keeps passingON/OFFexactly as before. This generalises whatSNMALLOC_CHECK_LOADS,SNMALLOC_PAGEIDandSNMALLOC_USE_WAIT_ON_ADDRESSalready do by hand with per-flagcfg(feature = "build_cc")branches.If you would prefer a smaller diff, the same bug can be fixed by giving those five flags the same per-flag branches the three above already use. I went with the trait method because it removes the failure mode rather than the instances, but I am happy to switch.
Verification
Grepping the compiler invocation under
CC_ENABLE_DEBUG_OUTPUT=1.Before,
cargo build -p snmalloc-sys --no-default-features --features build_cc,usewait-on-address:After, the same command:
And with
--features build_cc,qemu,libc-api, confirming the enabled direction still reaches the preprocessor:cargo testpasses on both the cc and the cmake path.How I ran into it
I maintain a D3D9 translation layer that uses snmalloc as the global allocator for a 32-bit PE running under Wine on macOS, and I was reading
sizeclassconfig.hto work out exactly which allocation sizes miss the per-thread cache. The 64-bit build's numbers did not match the source I was reading, which is what led here.