MantisBT - CMake
View Issue Details
0015754CMakeCMakepublic2015-09-21 10:542016-02-01 09:10
Johannes Asal 
Brad King 
normalmajoralways
closedfixed 
x64Windows7
CMake 3.3 
CMake 3.4CMake 3.4 
0015754: Visual Studio incremental build not working properly when target names start with a capital letter
When using a target name starting with a capital letter (e.g. Mylibrary) in add_library (and probably also add_executable), GCC toolchains build fine but Visual Studio (tested with 2010 specifically) refuses to compile new .cpp files in the first incremental build after adding them to the CMakeLists.txt. However, it correctly detects that the CMakeLists.txt has changed and reconfigures accordingly. The second incremental build compiles the added files, which makes it even more strange. Please note that the bug occurs only when building via the CMake command line interface (cmake.exe --build). Building from within Visual Studio works always which is why I think it must be a problem with CMake.
Install Visual Studio 2010. Unzip the attached ZIP file. Open a command line in the /build subfolder and call

cmake -G"Visual Studio 10" ..

Then do a

cmake --build .

Watch how test1.cpp is compiled properly. Then open CMakeLists.txt and uncomment the line with test2.cpp. Do an incremental build by calling

cmake --build .

The change of CMakeLists.txt is detected but test2.cpp is NOT COMPILED! Do a second incremental build

cmake --build .

Now test2.cpp is compiled.

Delete the bugreport folder and extract it again from the ZIP file to return to the initial state. Open the CMakeLists.txt and rename the 'Notworking' target name in add_library to 'working'. Repeat all steps above and you will see that test2.cpp is compiled in the first incremental build already, as one would expect.

I tested a lot of combinations and it seems that the capital letter in front seems to be the source of the problem.
No tags attached.
zip bugreport.zip (922) 2015-09-21 10:54
https://public.kitware.com/Bug/file/5531/bugreport.zip
Issue History
2015-09-21 10:54Johannes AsalNew Issue
2015-09-21 10:54Johannes AsalFile Added: bugreport.zip
2015-09-21 15:09Brad KingNote Added: 0039463
2015-09-21 15:14Brad KingNote Added: 0039464
2015-09-22 03:48Johannes AsalNote Added: 0039466
2015-09-22 04:07Johannes AsalNote Edited: 0039466bug_revision_view_page.php?bugnote_id=39466#r1911
2015-09-22 04:07Johannes AsalNote Edited: 0039466bug_revision_view_page.php?bugnote_id=39466#r1912
2015-09-22 09:27Brad KingNote Added: 0039467
2015-09-22 09:29Brad KingNote Added: 0039468
2015-09-22 09:41Johannes AsalNote Added: 0039469
2015-09-22 13:05Brad KingNote Added: 0039470
2015-09-22 13:05Brad KingAssigned To => Brad King
2015-09-22 13:05Brad KingStatusnew => resolved
2015-09-22 13:05Brad KingResolutionopen => fixed
2015-09-22 13:05Brad KingFixed in Version => CMake 3.4
2015-09-22 13:05Brad KingTarget Version => CMake 3.4
2015-09-23 03:19Johannes AsalNote Added: 0039472
2016-02-01 09:10Robert MaynardNote Added: 0040417
2016-02-01 09:10Robert MaynardStatusresolved => closed

Notes
(0039463)
Brad King   
2015-09-21 15:09   
Strange. I can reproduce this with VS 2010. I can also reproduce it with VS 2015. I also changed the CMakeLists.txt file with this patch:

 -project(NOTWORKING)
 +project(Unrelated)

to make sure the .sln file name looks nothing like any of the .vcxproj file names and it made no difference.

Running "cmake --build ." internally runs:

  msbuild ALL_BUILD.vcxproj /t:Build /p:Configuration=Debug

I can also reproduce the issue by using the msbuild invocation directly.
(0039464)
Brad King   
2015-09-21 15:14   
The difference between the two behaviors appears to be the order in which ProjectReference elements appear in "ALL_BUILD.vcxproj". It works if ZERO_CHECK comes first because that is for regenerating when CMakeLists.txt files have changed.

If I rename the "Notworking" target to "ZZZ" it still starts in a capital but also works because "ZZZ" sorts after "ZERO_CHECK" while "Notworking" sorts before it.

We'll have to look at hacking the sort function to place ZERO_CHECK first among all ProjectReference elements.
(0039466)
Johannes Asal   
2015-09-22 03:48   
(edited on: 2015-09-22 04:07)
Now I'm even more confused. There are ProjectDependencies in the solution file which ensure that the projects are built in the correct order. The command line build should take into account those dependencies but I guess triggering ALL_BUILD.vcxproj directly circumvents this somehow. That explains why the build works fine when running it from the solution in VisualStudio. My suggestion would be to make "cmake --build" use the solution instead:

msbuild NOTWORKING.sln /t:Build /p:Configuration=Debug

This will make it figure out the dependencies by itself. I already tested it and it seems to work fine.

You might still need an alternative for building individual targets though since the solution builds the complete CMake project including all subtargets.

(0039467)
Brad King   
2015-09-22 09:27   
There are reasons we do not use the .sln file to drive the build. One of them is that msbuild refuses to build a target that is not selected for default build as part of the current configuration. For example:

 add_custom_target(CustomTarget COMMAND ...) # without the ALL option

After generating the project, msbuild cannot build the target through the solution:

 > MSBuild Unrelated.sln /t:CustomTarget
 c:\...\Unrelated.sln.metaproj : error MSB4057: The target "CustomTarget" does not exist in the project. [c:\...\Unrelated.sln]

but can when naming the .vcxproj directly:

 > MSBuild CustomTarget.vcxproj
 (builds)

In the latter case MSBuild ignores the .sln altogether so ProjectReference elements are needed.
(0039468)
Brad King   
2015-09-22 09:29   
Re 0015754:0039467: Additionally, the ALL_BUILD target corresponds to "make all" and so is needed as the target used for the default build. The ALL_BUILD target is created just like the example CustomTarget shown and so needs the .vcxproj file to be named directly to get it to build.
(0039469)
Johannes Asal   
2015-09-22 09:41   
That's true. But when building with "--build ." you want all targets to be built. So maybe you could use the solution in that special case? Probably I'm missing some other pitfalls in that assumption though... Anyway, I'll be fine with any solution as long as it fixes my problem ;)
(0039470)
Brad King   
2015-09-22 13:05   
I've refactored the existing target ordering logic:

 VS: Refactor target ordering logic
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=03bfe71a [^]

to make the fix to this issue easy:

 VS: Fix rebuild with regeneration after input CMake code change
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=40c7b461 [^]
(0039472)
Johannes Asal   
2015-09-23 03:19   
Great! Thanks a lot.
(0040417)
Robert Maynard   
2016-02-01 09:10   
Closing resolved issues that have not been updated in more than 4 months.