llvm / llvm/llvm-project

`add_definitions(${LLVM_DEFINITIONS})` after `include(HandleLLVMOptions)` produces mangled compile definitions on CMake 3.31

Open
#210,072 0 comments 0 reactions 0 assignees View on GitHub
cmake
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.