View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0016054CMakeCMakepublic2016-04-07 16:532016-06-10 14:31
ReporterDaniel Richard G. 
Assigned ToKitware Robot 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionmoved 
PlatformWindowsOSOS Version
Product VersionCMake 3.5.1 
Target VersionFixed in Version 
Summary0016054: Cannot override CMAKE_{C,CXX}_FLAGS* to allow compiler check to succeed
DescriptionI am attempting to build a project on a Windows system.

The development tools on this system are set up a little differently from the norm: Because my company always builds against the static C runtime library (i.e. using the /MT flag), the dynamic C runtime (/MD) stub library is not present at all. Any attempt to link an executable/DLL that was built with /MD will fail.

Now, CMake ships with /MD or /MDd in the default flags. I set my desired flags (including /MT) in CFLAGS/CXXFLAGS in the environment, start up cmake-gui, and hit "Configure".

"Error in configuration process, project files may be invalid"

The log window shows

    CMake Error at C:/.../Modules/CMakeTestCCompiler.cmake:61 (message):
      The C compiler "C:/.../icl.exe" is
      not able to compile a simple test program.

Lower down, after the compiler invocation, I see

    icl: command line warning #10121: overriding '/MT' with '/MDd'

CMake's flags are concatenated to my own, and /MDd wins out. Thus the linker fails to link the program, due to that missing stub library, and CMake reports the compiler as non-functional.

Okay, so I edit the CMAKE_{C,CXX}_FLAGS* variables to remove all the /MD and /MDd flags. Then I configure again. Same error. It's _still_ passing /MDd to the compiler!

At this point, I don't know where that flag is coming from. I grep through the nascent build tree to see if there are any instances of it still kicking around; the only hit is in CMakeError.log. I double-check that the project source isn't at fault: nope, the flag is nowhere to be found there either.

Turns out, the place where that flag is coming from is CMake's own Modules/Platform/Windows-MSVC.cmake file. If I edit the _INIT variable in there (e.g. add /Dhi_mom), then I see the result reflected in the compiler test.

The bug, then, is that I have no good way of overriding those flag variables in order to allow the compiler check to succeed. (Note that CMAKE_USER_MAKE_RULES_OVERRIDE is not applicable here, because I want to override those flags as a user, not modify the project to get the same effect.)

Perhaps the edited variables are used later on, when building the project, but they are certainly not used when checking the compiler. I believe this bug has gone unnoticed for so long due to this specific scenario (missing dynamic CRT stub library) being uncommon.

Note that this issue is reproducible with a trivial CMake project---I used one as described at cmake.org/examples---so the original project that exhibited this bug is not at issue.
Additional InformationBecause I need to use my company's exact compiler/linker flags, and will be given grief by my release-engineering group if I use anything else, it would be nice to be able to set some environment variable or the like that will tell CMake not to "help" with any default flags.

While I can always edit the Windows-MSVC.cmake file, that then imposes the ongoing burden of maintaining that file, merging in upstream changes, etc. My goal is to just set CFLAGS/LDFLAGS/etc. in the environment and have the tools work with that, as is the case in Unix. (Setting a CMAKE_NO_DEFAULT_FLAGS variable or the like would be a reasonable solution.)
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0040828)
Brad King (manager)
2016-04-08 08:29

One may pre-populate the cache with the CMAKE_*_FLAGS[*] variables and they will be used instead of the defaults.
(0040834)
Daniel Richard G. (reporter)
2016-04-08 15:36

But how would I do that, if I start up cmake-gui in an empty build directory? There's no variables to edit before hitting "Configure", and afterward, editing them has no effect.

I tried adding CMAKE_C_FLAGS_DEBUG ("/Dhi_mom") sight unseen before the first configure, and while that value does get used in the compiler check, it _still_ appends /MDd and the others, leading to the same failure as before.
(0040836)
Brad King (manager)
2016-04-11 11:30

Re 0016054:0040834: The "Add Entry" button can be used to add cache entries. Alternatively one can use the command-line tool with "-DCMAKE_C_FLAGS_DEBUG=...". The reason the flags need to be specified before the first run instead of edited afterward is that CMake uses them for some initial checks (via try_compile) that are not repeated later.

The problem here is that CMAKE_C_FLAGS_DEBUG is not propagated into the try_compile test project the way CMAKE_C_FLAGS is. Here are some changes to fix that:

 cmCoreTryCompile: Factor out config lookup for re-use
 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=82ef90fc [^]

 try_compile: Honor CMAKE_<LANG>_FLAGS_<CONFIG> changes
 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bd581a37 [^]
(0040844)
Brad King (manager)
2016-04-12 10:16

The changes linked in 0016054:0040836 are available in a nightly binary here:

  https://cmake.org/files/dev/?C=M;O=D [^]

as of cmake-3.5.20160411-gf5a87 or higher.
(0040846)
Daniel Richard G. (reporter)
2016-04-12 16:30

I tried out the gf5a87 snapshot. Unfortunately, there's no improvement yet. Here are my observations:

* CMAKE_C_FLAGS_DEBUG set in the environment does not appear in the cache variable;

* Editing the _DEBUG cache variable in the GUI does not affect the flags used in the compiler check in a subsequent configure;

* Possible regression: In CMakeError.log, the "Build Flags:" line only shows the flags I originally specified in the CFLAGS environment variable. It does not show the flags appended by CMake in CMAKE_C_FLAGS ("/DWIN32 /D_WINDOWS /W3"), nor anything from CMAKE_C_FLAGS_DEBUG, even though all those are used in the actual compiler invocation. (Note that I've unset CMAKE_{START,END}_TEMP FILE for debugging purposes.)
(0040847)
Brad King (manager)
2016-04-12 16:44

Re 0016054:0040846: Thanks for testing.

> CMAKE_C_FLAGS_DEBUG set in the environment does not appear in the cache variable;

We document no such behavior. There is no such environment variable.

> Editing the _DEBUG cache variable in the GUI does not affect the flags used in the compiler check in a subsequent configure;

Most checks are not re-executed. Results from the first time are saved in the cache in internal variables. The log files content you may be reading is left from the first time too.

> Possible regression: In CMakeError.log, the "Build Flags:" line only shows the flags I originally specified in the CFLAGS environment variable.

That line is only for the compiler id and in fact it does not use any of the other flags. The compiler id is a bootstrapping step done before we have enough information for a real try_compile.

In order to change the runtime library for the initial checks you need to pre-populate the cache with

  CMAKE_C_FLAGS_DEBUG="/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1"

before configuring the first time.
(0040848)
Daniel Richard G. (reporter)
2016-04-12 23:45

Re the CMakeError.log file content: The actual compiler invocation in the compiler check does, in fact, use the other flags. The bug is that the "Build Flags:" line does not reflect what is passed to the compiler. I don't know which of the two sets of flags should be used, but obviously they need to agree with each other.

I tried passing -DCMAKE_C_FLAGS_DEBUG="/MT" on the cmake-gui command line in a new build directory, but that was ignored.

I added an entry for CMAKE_C_FLAGS_DEBUG manually in the GUI before configuring for the first time. That, finally, did get used.

This isn't a good solution for users of CMake, however, as they are not likely to know about this specific variable ahead of its first appearance in the GUI, nor the special circumstances surrounding it that prevent them from editing the variable after the first configuration. (Also, how would you even pre-populate the cache if you're using the command-line "cmake", when a -D argument doesn't do the trick?)

At the very least, the compiler check should use the current flags in the cache, so that the user can edit the flags if the check fails and try again. No different than if some later check fails, you edit the flags to add the appropriate -D/-I/-L/-l flag or whatever, and re-configure. That's a basic thing that you're supposed to be able to do with CMake, and the compiler check breaks that pattern.

The reason why I bring up environment variables is because there really needs to be a more obvious way to do this. The goal is pretty simple---use my flags instead of the default ones---and this approach of pre-populating the cache assumes quite a bit of familiarity with CMake and its internal workings. (Even I, having used CMake for a long time, was not aware that this was a thing.) This is not going to work for a user whose interest in CMake is incidental, as a means to building the project that is their actual end goal.

Environment variables are the most obvious solution, in that there is ample precedent that users are likely to know (if they have experience with other build tools) and CC/CFLAGS/CXXFLAGS/etc. are already recognized. If I'm a casual CMake user, and I set CMAKE_C_FLAGS_DEBUG in the environment, and then see that not have any effect in the GUI, I'm going to be frustrated---that this common pattern with other tools doesn't apply to CMake, and that I'll have to dig into the CMake docs/lists/forums to find out what to do. Which is fine if it's something complicated, but what we're talking about here is something pretty darn basic.

A -DCMAKE_C_FLAGS_DEBUG=... flag is less obvious, but given that -D flags are a standard way of specifying variables to CMake, there's no good reason for this not to work either.
(0040857)
Daniel Richard G. (reporter)
2016-04-13 15:13

I am attempting to further debug the initial compiler tests. A couple questions:

* When linking CMake{C,CXX}CompilerId, isn't it supposed to use CMAKE_SHARED_LINKER_FLAGS? There are a couple of flags needed in order for the link to work, and even though they are in the variable, they do not appear to be passed on to the actual linker invocation. (In fact, it doesn't look like any of the CMAKE_*_LINKER_FLAGS* vars are being used...)

* I'm trying to determine why the testCCompiler program fails to build (all I see right now in the log is "RC Pass 1 failed to run"), but even though I passed in --debug-{trycompile,output}, the C source file for that is deleted. How do I tell CMake not to delete it so I can try running the compiler/linker on it myself?
(0040859)
Brad King (manager)
2016-04-13 15:30

Re 0016054:0040857: You're exploring new territory here. We've never needed to work without the dynamic runtime libraries installed before. Typically people just change /MD -> /MT in CMAKE_<LANG>_FLAGS_<CONFIG> in their project and build their binaries that way while simply tolerating that the checks run with /MD.

Ideally we should make runtime library selection a first-class setting just like the generator, platform, and toolset selection. Then CMake would generate the proper /MD or /MT flag as needed. Such design would be better discussed on the developer mailing list though. Meanwhile we can work through some issues here.

> When linking CMake{C,CXX}CompilerId, isn't it supposed to use CMAKE_SHARED_LINKER_FLAGS?

No. The compiler id is a bootstrapping step and the CMAKE_SHARED_LINKER_FLAGS value may not be finalized yet. The compiler id uses a series of guesses and repeated attempts to figure out what compiler is being used.

If you're using a Visual Studio generator then Modules/CMakeDetermineCompilerId.cmake has a special code path to generate a .vcxproj file from Modules/CompilerId/VS-10.vcxproj.in for the compiler id project. That file currently hard-codes MultiThreadedDebugDLL as the RuntimeLibrary. If runtime library selection were a first-class feature then it could switch off that. Instead for now we should teach Modules/CMakeDetermineCompilerId.cmake to repeat the compiler id test with various alternative options for the RuntimeLibrary field.

> I'm trying to determine why the testCCompiler program fails to build (all I see right now in the log is "RC Pass 1 failed to run"),

You can get slightly more verbose information by adding "VERBOSE=1" to the environment (not the cache).

> --debug-{trycompile,output},

Make sure you're doing this from a command line and not the gui. I don't know if they work for the latter. Also, do this in a simple test project that has only

  cmake_minimum_required(VERSION 3.5)
  project(Test C)
(0040860)
Daniel Richard G. (reporter)
2016-04-13 16:33

Handling /MD vs. /MT explicitly in the UI would be a nice-to-have, but that goes beyond what I need. All I want is to be able to arbitrarily override defaults, but at a very basic level, like env vars and -D flags.

(After all, even if such a new first-class setting were to be implemented, it would still address just one specific flag. There could still be other flags/variables you need to modify, and obviously you can't have a dedicated UI widget for every one.)

Re _LINKER_FLAGS: Note that /MD vs. /MT is not applicable to the linker. I need to add something like "/nodefaultlib:foo bar.lib" in order for the link to work. (It's a long story.)

I understand that CMAKE_*_LINKER_FLAGS* may not be finalized at the point that the compiler test is run, but it should at least use LDFLAGS if that is set in the environment. (I see that LDFLAGS is recognized, and the contents added to CMAKE_*_LINKER_FLAGS, but it's not currently used in the compiler test.) Ideally, too, if any _LINKER_FLAGS vars are set in the environment, CMake should just use those from the get-go and not bother to determine them itself.

Re VERBOSE=1: I set that, and created the even more minimal project you described. In CMakeError.log, I now see

    Visual Studio Incremental Link with embedded manifests
    Create CMakeFiles\cmTC_6b8a1.dir/manifest.rc
    Create empty: CMakeFiles\cmTC_6b8a1.dir/embed.manifest
    RC Pass 1:
     /foCMakeFiles\cmTC_6b8a1.dir/manifest.res CMakeFiles\cmTC_6b8a1.dir/manifest.rc
    
    RC Pass 1 failed to run.
    NMAKE : fatal error U1077: 'C:\Users\drg\Desktop\cmake-3.5.20160411-gf5a87-win64-x64\bin\cmake.exe' : return code '0xffffffff'
    Stop.
    NMAKE : fatal error U1077: 'C:\dev\microsoft\vc2013\bin\amd64\nmake.exe' :
    return code '0x2'
    Stop.

Shouldn't the value of CMAKE_RC_COMPILER appear there, before the /fo.../manifest.res? (That's supposed to be the full tool invocation, right?) This variable is set to "rc", but I see that "rc" is actually not in my PATH.

Which would explain why the resource-compile is failing, but shouldn't CMake have returned NOTFOUND for CMAKE_RC_COMPILER, then? And why doesn't the log show the "'rc' is not recognized as an internal or external command..." error message? That would have made very clear what was going on.
(0040866)
Brad King (manager)
2016-04-15 13:10

> All I want is to be able to arbitrarily override defaults, but at a very basic level, like env vars and -D flags.

One can do this on a command line with

  cmake ../src -DCMAKE_C_FLAGS_DEBUG=/MT

That is a -D flag as you request. If you're doing it in the gui then you need to use the gui features (Add Entry) to do that. I'd rather focus further discussion on the other issues.

> I need to add something like "/nodefaultlib:foo bar.lib" in order for the link to work.

To get CMAKE_EXE_LINKER_FLAGS used for the checks, see [policy CMP0056](https://cmake.org/cmake/help/v3.5/policy/CMP0056.html [^]). If your project calls cmake_minimum_required(VERSION 3.2) as the first line of the top-level CMakeLists.txt file this will be automatic. To set it without modifying the project, use CMAKE_POLICY_DEFAULT_CMP0056 in the cache eas explained in the CMP0056 documentation.

Is the compiler id detected as MSVC with some version, or does that step fail?

> This variable is set to "rc", but I see that "rc" is actually not in my PATH.

Currently we assume that rc is always in the PATH when building under the IDE environment. If you're using a Makefile generator then we assume that if "cl" is in the path then "rc" is too. When targeting a Windows platform we require the RC language to be available, and therefore need the tool.
(0042978)
Kitware Robot (administrator)
2016-06-10 14:29

Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.

 Issue History
Date Modified Username Field Change
2016-04-07 16:53 Daniel Richard G. New Issue
2016-04-08 08:29 Brad King Note Added: 0040828
2016-04-08 15:36 Daniel Richard G. Note Added: 0040834
2016-04-11 11:30 Brad King Note Added: 0040836
2016-04-12 10:16 Brad King Note Added: 0040844
2016-04-12 16:30 Daniel Richard G. Note Added: 0040846
2016-04-12 16:44 Brad King Note Added: 0040847
2016-04-12 23:45 Daniel Richard G. Note Added: 0040848
2016-04-13 15:13 Daniel Richard G. Note Added: 0040857
2016-04-13 15:30 Brad King Note Added: 0040859
2016-04-13 16:33 Daniel Richard G. Note Added: 0040860
2016-04-15 13:10 Brad King Note Added: 0040866
2016-06-10 14:29 Kitware Robot Note Added: 0042978
2016-06-10 14:29 Kitware Robot Status new => resolved
2016-06-10 14:29 Kitware Robot Resolution open => moved
2016-06-10 14:29 Kitware Robot Assigned To => Kitware Robot
2016-06-10 14:31 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team