`add_definitions(${LLVM_DEFINITIONS})` after `include(HandleLLVMOptions)` produces mangled compile definitions on CMake 3.31
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The [MLIR standalone example](https://github.com/llvm/llvm-project/blob/main/mlir/examples/standalone/CMakeLists.txt) pattern of calling both `include(HandleLLVMOptions)` and `add_definitions(${LLVM_DEFINITIONS})` produces mangled compile definitions under CMake 3.31, when building against a static Release LLVM artifact.
The root cause is a CMake `add_definitions()` deduplication bug: when the first definition in the merged compile-definitions list contains `=` (e.g. `_GLIBCXX_USE_CXX11_ABI=1`), duplicates are not properly deduplicated and instead produce a mangled quoted string. This is **not specific to the Ninja generator** — it reproduces identically with both `-G Ninja` and `-G "Unix Makefiles"` (verified on CMake 3.31.10).
This only manifests with Release LLVM builds (no assertions) because `HandleLLVMOptions` does not add `_DEBUG` or `_GLIBCXX_ASSERTIONS` in that case — so `_GLIBCXX_USE_CXX11_ABI=1` ends up as the first definition in the list, triggering the bug. With Debug/assertions builds, `_DEBUG` (no `=`) is first and CMake deduplicates correctly.
## Minimal CMake reproducer
```cmake
cmake_minimum_required(VERSION 3.21)
project(test LANGUAGES CXX)
# Simulates what include(HandleLLVMOptions) does:
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1)
add_compile_definitions(__STDC_CONSTANT_MACROS)
add_compile_definitions(__STDC_FORMAT_MACROS)
add_compile_definitions(__STDC_LIMIT_MACROS)
# Simulates what add_definitions(${LLVM_DEFINITIONS}) does:
set(LLVM_DEFINITIONS "-D_GLIBCXX_USE_CXX11_ABI=1 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
add_definitions(${LLVM_DEFINITIONS})
add_executable(test_exe main.cpp)
```
```cpp
// main.cpp
int main() { return 0; }
```
```bash
# Reproduces with both generators:
cmake -S . -B build_ninja -G Ninja
grep "DEFINES" build_ninja/build.ninja
cmake -S . -B build_make -G "Unix Makefiles"
grep "CXX_DEFINES" build_make/CMakeFiles/test_exe.dir/flags.make
```
### Expected output (both generators)
```
DEFINES = -D_GLIBCXX_USE_CXX11_ABI=1 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
```
### Actual output (CMake 3.31.10, both Ninja and Unix Makefiles)
```
DEFINES = -D_GLIBCXX_USE_CXX11_ABI=1 -D_GLIBCXX_USE_CXX11_ABI="1 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS" -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
```
The second `_GLIBCXX_USE_CXX11_ABI` definition has a mangled value (`"1 -D__STDC_CONSTANT_MACROS ..."`), and `__STDC_CONSTANT_MACROS` etc. are duplicated. The identical mangled output appears in both `build.ninja` and `flags.make`.
### Workaround
Adding a `add_compile_definitions` call without `=` **before** `include(HandleLLVMOptions)` ensures the first entry in the compile definitions list doesn't contain `=`, which prevents the bug:
```cmake
# Workaround: ensures a no-'=' definition is first in the list,
# preventing CMake 3.31 add_definitions() dedup bug.
add_compile_definitions(_GNU_SOURCE)
include(HandleLLVMOptions)
# ...
add_definitions(${LLVM_DEFINITIONS})
```
This works because `_GNU_SOURCE` is already in `LLVM_DEFINITIONS` (set by `LLVMConfig.cmake`) but is not added by `HandleLLVMOptions` via `add_compile_definitions`. Placing it first ensures the merged definitions list starts with a simple definition (no `=`), which CMake deduplicates correctly.
## Impact
This breaks any out-of-tree MLIR project that follows the standalone example pattern and builds against a static Release LLVM, when compiled with `-Werror` (GCC errors on the macro redefinition with a different value).
## Environment
- CMake 3.31.10
- Generators tested: Ninja 1.13, Unix Makefiles (both reproduce)
- GCC 13/14 with `-Werror`
- LLVM/MLIR built with `CMAKE_BUILD_TYPE=Release` (no assertions)
Contributor guide
Research direction
Start with mlir/examples/standalone/CMakeLists.txt and reproduce the issue using the minimal CMake project on CMake 3.31.10 with both Ninja and Unix Makefiles. Inspect the generated build.ninja and CMakeFiles/test_exe.dir/flags.make outputs, then verify that the chosen correction prevents mangled or duplicated definitions for a static Release LLVM build with -Werror.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100