← All tasks
cppgoogle/sentencepiece #1239Not a task: already works

CMake: `-fPIC` and other Unix flags injected for Clang on Windows

envgap__google__sentencepiece-1239

01 / FAILURE SIGNATURE

As reported upstream

The MSVC ABI is position-independent by definition, so `-fPIC` is a no-op (or hard error) there even for MSVC; on Clang-on-Windows it is rejected outright.
Not a benchmark task.
  • The project already builds and runs before the fix, so there is nothing to repair.

02 / ENVIRONMENT RECIPE

Base commit
6cc43b55016f17486291033e8da4a6cd1614ecec
Manifest
CMakeLists.txt
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / ORIGINAL ISSUE TEXT

google/sentencepiece #1239 · read the original issue
**Describe the bug**

On Windows, several Unix-toolchain compiler flags are injected unconditionally for any compiler that is not MSVC's `cl.exe`. The gates use `if (NOT MSVC)`, but `MSVC` is `FALSE` for `clang.exe` (whether it is invoked as `clang-cl` on x64 Windows or as `clang` driven by a toolchain file targeting the MSVC ABI). As a result, building sentencepiece with native Clang on Windows fails because Clang rejects flags such as `-fPIC` and `-pthread` on the MSVC ABI.

There are three injection sites, all driven by the same root cause:

1. `CMakeLists.txt:47–49` — sets `CMAKE_POSITION_INDEPENDENT_CODE ON` whenever `SPM_ENABLE_SHARED` is on. CMake translates this to `-fPIC` for non-MSVC compilers. The block at `CMakeLists.txt:60–62` (`if(WIN32) set(SPM_ENABLE_SHARED OFF)`) runs *after* this, so on Windows the global is set first and only later does `SPM_ENABLE_SHARED` get forced off.
2. `src/CMakeLists.txt:254` — `if (NOT MSVC) set(CMAKE_CXX_FLAGS "-O3 -Wall -fPIC ${CMAKE_CXX_FLAGS}")` plus a few `-Wno-*` sets. Fires for Clang-on-Windows.
3. `src/CMakeLists.txt:56–60` — in the internal-protobuf branch, `if (MSVC) /DHAVE_PTHREAD ... else() -pthread -DHAVE_PTHREAD=1 -Wno-sign-compare -Wno-deprecated-declarations`. Same gate, same problem.

The MSVC ABI is position-independent by definition, so `-fPIC` is a no-op (or hard error) there even for MSVC; on Clang-on-Windows it is rejected outright.

**To Reproduce**

- OS: Windows 10/11 (any Windows host with native Clang reproduces).
- Compiler: any of the following triggers it:
  - `clang-cl` from a recent LLVM release (e.g. 17+).
  - `clang.exe` driven by a CMake toolchain file that targets the MSVC ABI (for example a Windows-on-arm64 toolchain that sets `CMAKE_CXX_COMPILER_TARGET=arm64-pc-windows-msvc`).
- CMake: 3.27+, Ninja or NMake generator (Visual Studio + ClangCL toolset also reproduces).
- Commands (toolchain-file form):

  ```
  cmake -S . -B build ^
    -G Ninja ^
    -DCMAKE_TOOLCHAIN_FILE=<path/to/clang-windows.cmake> ^
    -DCMAKE_BUILD_TYPE=Release
  cmake --build build
  ```

- Observed: configure succeeds, build fails with Clang errors on `-fPIC` (and warnings → errors on `-pthread` / GCC-style `-Wno-*` depending on `-Werror` policy).

A minimal reproducer of the gate logic, without sentencepiece-specific knobs:

```cmake
# CMAKE_CXX_COMPILER_ID == "Clang", MSVC == FALSE, WIN32 == TRUE
if (NOT MSVC)
  set(CMAKE_CXX_FLAGS "-fPIC ${CMAKE_CXX_FLAGS}")  # injected on Clang-Windows
endif()
```

**Expected behavior**

On Windows, regardless of which compiler is in use, the build should not inject `-fPIC`, `-pthread`, `-O3 -Wall`, or other Unix-toolchain flags. The check should be against the *platform* (Windows vs. Unix), not against `MSVC` (the compiler frontend), since these flags are defined by the platform/ABI rather than by the compiler.

**Proposed fix**

Switch the three gates from `NOT MSVC` to `NOT WIN32` (and the corresponding `if (MSVC)` to `if (WIN32)` in site #3), and additionally gate the `CMAKE_POSITION_INDEPENDENT_CODE` global on `NOT WIN32`:

- `CMakeLists.txt`: `if (SPM_ENABLE_SHARED AND NOT WIN32)` around the PIC global.
- `src/CMakeLists.txt:254`: `if (NOT MSVC)` → `if (NOT WIN32)`.
- `src/CMakeLists.txt:56–60`: `if (MSVC) ... else() ...` → `if (WIN32) ... else() ...`.

No behavior change on Linux/macOS or under MSVC `cl.exe`.
Continue on GitHub ↗

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]