# cmake picks up LDFLAGS from environment

**URL:** https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130
**Category:** Code
**Created:** [September 21, 2021, 3:24pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130 "2021-09-21T15:24:22Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 21, 2021, 3:24pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/1 "2021-09-21T15:24:22Z")

</div>

If LDFLAGS are set in environment, then cmake picks that up and adds it to the list of linker flags. What is the way to avoid that? I tried to define `CMAKE_EXE_LINKER_FLAGS_INIT`, `CMAKE_CXX_LINK_FLAGS` etc in the toolchain file, but it did not help.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [September 21, 2021, 4:54pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/2 "2021-09-21T16:54:54Z")

</div>

The [docs](https://cmake.org/cmake/help/latest/envvar/LDFLAGS.html) state that it happens, though setting `CMAKE_EXE_LINKER_FLAGS_INIT` should do it. Could you please provide a small example showing the issue?

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 21, 2021, 6:35pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/3 "2021-09-21T18:35:47Z")

</div>

> [@ben.boeckel](#):
>
> `CMAKE_EXE_LINKER_FLAGS_INIT`

```auto
$ cat CMakeLists.txt
project(helloworld)
add_executable(helloworld helloworld.cpp)
set(CMAKE_EXE_LINKER_FLAGS_INIT )

$ env | grep LDFLAGS
LDFLAGS=-Wl,--as-needed

```

If I build this I can see cmake passing LDFLAGS to the linker

```bash
[50%] Building CXX object CMakeFiles/helloworld.dir/helloworld.cpp.o
/usr/bin/c++ -o CMakeFiles/helloworld.dir/helloworld.cpp.o -c /usr/local/src/cmake_example/helloworld.cpp
[100%] Linking CXX executable helloworld
/usr/bin/cmake -E cmake_link_script CMakeFiles/helloworld.dir/link.txt --verbose=1
/usr/bin/c++ -Wl,--as-needed -rdynamic CMakeFiles/helloworld.dir/helloworld.cpp.o -o helloworld
make[2]: Leaving directory '/usr/local/src/cmake_example/build'
[100%] Built target helloworld
make[1]: Leaving directory '/usr/local/src/cmake_example/build'
/usr/bin/cmake -E cmake_progress_start /usr/local/src/cmake_example/build/CMakeFiles 0

```

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 21, 2021, 6:44pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/4 "2021-09-21T18:44:37Z")

</div>

I can see that the environment variable `LDFLAGS` is added to `CMAKE_EXE_LINKER_FLAGS` irrespective of `CMAKE_EXE_LINKER_FLAGS_INIT`. cmake also picks up `CFLAGS` from the environment.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [September 21, 2021, 6:50pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/5 "2021-09-21T18:50:54Z")

</div>

CMake initializes the flags in the `project()` call (which enables the `C` and `CXX` language toolchains), so your setting is too late in your example.

---

<div class="post-metadata">

### Author: ![Chrinkus](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chrinkus/32/1801_2.png) [@Chrinkus](https://discourse.cmake.org/u/Chrinkus)
#### Post date: [September 21, 2021, 6:50pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/6 "2021-09-21T18:50:54Z")

</div>

I thought that if you call `set` without a value then it clears whatever variable you’ve provided as a first argument. Try:

```auto
set(CMAKE_EXE_LINKER_FLAGS_INIT "")

```

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 21, 2021, 6:56pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/7 "2021-09-21T18:56:51Z")

</div>

Does not help to put `CMAKE_EXE_LINKER_FLAGS_INIT` before `project`.

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 21, 2021, 6:57pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/8 "2021-09-21T18:57:53Z")

</div>

Does not help to do

```auto
set(CMAKE_EXE_LINKER_FLAGS_INIT "")

```

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 21, 2021, 7:02pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/9 "2021-09-21T19:02:40Z")

</div>

Also tried to put `CMAKE_EXE_LINKER_FLAGS_INIT` in a toolchain file but cmake still picks up environment variable.

---

<div class="post-metadata">

### Author: ![jtxa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/jtxa/32/1535_2.png) [@jtxa](https://discourse.cmake.org/u/jtxa)
#### Post date: [September 21, 2021, 8:21pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/10 "2021-09-21T20:21:33Z")

</div>

I can confirm that the behavior differs from the documentation, so either the docs or implementation is buggy.

The content of `CMAKE_EXE_LINKER_FLAGS_INIT` and `LDFLAGS` seems to be concatened and used for initialization of `CMAKE_EXE_LINKER_FLAGS`. Only the latter one is stored in the cache file, the `_INIT` is not.

The easiest solution for you is to delete the environment variables. So you don’t need to know exactly how it is used by CMake.

```auto
set(ENV{LDFLAGS})

```

---

<div class="post-metadata">

### Author: ![Chrinkus](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chrinkus/32/1801_2.png) [@Chrinkus](https://discourse.cmake.org/u/Chrinkus)
#### Post date: [September 21, 2021, 9:07pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/11 "2021-09-21T21:07:00Z")

</div>

Wait, that’s a cache variable so you need the word CACHE in your set call. Or you can add them in your generation call with -D I believe…

---

<div class="post-metadata">

### Author: ![jtxa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/jtxa/32/1535_2.png) [@jtxa](https://discourse.cmake.org/u/jtxa)
#### Post date: [September 21, 2021, 11:00pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/12 "2021-09-21T23:00:22Z")

</div>

For this one both works. The last one defined seems to win.

Please try and play with this self-contained example:

```auto
cmake_minimum_required(VERSION 3.7)

set(ENV{LDFLAGS} "--illegal-flag-via-env")
set(CMAKE_EXE_LINKER_FLAGS_INIT "--illegal-flag-via-cache" CACHE STRING "")
set(CMAKE_EXE_LINKER_FLAGS_INIT "--illegal-flag-via-var")

project(helloworld LANGUAGES CXX)
add_executable(helloworld helloworld.cpp)
file(GENERATE OUTPUT helloworld.cpp CONTENT "")

```

Calling the following command

```auto
cmake . ; cat CMakeCache.txt | grep illegal

```

will fail at the compiler check and you can see `--illegal-flag-via-var --illegal-flag-via-env` used on the command line by CMake.  
This is also the value used in the cache file for `CMAKE_EXE_LINKER_FLAGS`

I think the `*_INIT` variables are never written to the cache file by CMake itself, because they are used only once on the first configure for initializing the cache variable without the \_INIT suffix. That makes them irrelevant for future configure calls.

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 22, 2021, 11:13am UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/13 "2021-09-22T11:13:28Z")

</div>

I removed the environment variables `CFLAGS` and `LDFLAGS` to avoid them being picked up by cmake.

This cmake behavior is quite problematic and undesirable. In my case a build machine had these environment variables defined giving a different build result. This kind of behavior is not good for reproducible builds and can be hard to track down. A toolchain file should be the input to the compiler and linker flags.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [September 22, 2021, 8:21pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/14 "2021-09-22T20:21:20Z")

</div>

> [@cmak](#):
>
> This cmake behavior is quite problematic and undesirable

Please file [an issue](https://gitlab.kitware.com/cmake/cmake/-/issues) with your example. However, pulling `{C,CXX,CPP,LD}FLAGS` from the environment has a _long_ history. Changing this will almost certainly need a policy (and docs/tests to demonstrate the old and new behaviors).

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [September 22, 2021, 10:07pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/15 "2021-09-22T22:07:17Z")

</div>

> [@ben.boeckel](#):
>
> Changing this will almost certainly need a policy

Rather than changing the behavior and requiring a policy, another choice is to add support for a new variable which can be set to true in a toolchain file to say “Don’t pick up flags like CFLAGS, LDFLAGS, etc. from the environment, ignore them”.

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 23, 2021, 7:29am UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/16 "2021-09-23T07:29:18Z")

</div>

A variable telling cmake to not pick up compiler and linker flags from environment sounds good. Although I thought that was the intent with the variable `CMAKE_EXE_LINKER_FLAGS_INIT `? Maybe fixing or describing how those variables work is sufficient?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [September 23, 2021, 1:17pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/17 "2021-09-23T13:17:03Z")

</div>

> [@cmak](#):
>
> Maybe fixing or describing how those variables work is sufficient?

Fixing the docs is certainly required, but I don’t think that gets you the _behavior_ you’re looking for. That is what will require a policy (or just a brand-new mechanism since policy manipulations in toolchain files are…probably also a little odd).

---

<div class="post-metadata">

### Author: ![cmak](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/c/eb8c5e/32.png) [@cmak](https://discourse.cmake.org/u/cmak)
#### Post date: [September 23, 2021, 7:13pm UTC](https://discourse.cmake.org/t/cmake-picks-up-ldflags-from-environment/4130/18 "2021-09-23T19:13:06Z")

</div>

Created issue

[https://gitlab.kitware.com/cmake/cmake/-/issues/22674](https://gitlab.kitware.com/cmake/cmake/-/issues/22674)
