MantisBT - CMake
View Issue Details
0013623CMakeCMakepublic2012-10-31 04:312013-10-07 10:04
Michael Broutin 
Brad King 
normalminoralways
closedfixed 
MSVC 2012 expressWindows 7Windows 7 x64
CMake 2.8.9 
 
0013623: MSBuild.exe doesn't "see" a project in solution (MSVC 2012 express)
Hi,
I'm no sure whether it's a CMake or MSVC issue, but here is the case :
I use a nightly build of CMake which has MSVC 2012 express support (2.8.9 doesn't support it, AFAIK)
In the generated solution, I have a custom target to build doxygen doc (Cmake script is here : http://code.google.com/p/ogre-procedural/source/browse/docs/CMakeLists.txt [^])

I can build successfully this target from within the IDE.

But, when I try to run it from a batch, either using "CMake --build" or MSBuild.exe things get a bit messy : when I specify the target "doc", MSBuild or CMake just say that this target doesn't exist in the solution.
Other targets with code in it, or building with no target specified seem to work properly, it's just this target which fails...
Build the Ogre SDK from source for MSVC11 express
Get this project : http://code.google.com/p/ogre-procedural/source/checkout [^]
Generate it with CMake, then call "CMake --build" with target doc.
In the past, I used MSVC 2010 and it properly built the "doc" target.
But I used devenv.exe (or VCExpress.exe for the express version), didn't try with MSBuild.
No tags attached.
zip cmake_bug.zip (868) 2012-11-03 10:24
https://public.kitware.com/Bug/file/4551/cmake_bug.zip
zip msbuild_targets_in_subdirs-patch1.zip (15,109) 2013-03-25 11:51
https://public.kitware.com/Bug/file/4693/msbuild_targets_in_subdirs-patch1.zip
zip msbuild_targets_in_subdirs-patch2.zip (18,023) 2013-03-27 06:53
https://public.kitware.com/Bug/file/4697/msbuild_targets_in_subdirs-patch2.zip
zip msbuild_targets_in_subdirs-patch3.zip (20,797) 2013-03-28 10:23
https://public.kitware.com/Bug/file/4700/msbuild_targets_in_subdirs-patch3.zip
zip msbuild_targets_in_subdirs-patch4.zip (1,594) 2013-04-06 15:51
https://public.kitware.com/Bug/file/4716/msbuild_targets_in_subdirs-patch4.zip
Issue History
2012-10-31 04:31Michael BroutinNew Issue
2012-10-31 07:44Brad KingNote Added: 0031357
2012-10-31 11:44d3x0rNote Added: 0031358
2012-11-01 06:26Michael BroutinNote Added: 0031366
2012-11-03 10:24Michael BroutinFile Added: cmake_bug.zip
2012-11-03 10:26Michael BroutinNote Added: 0031397
2012-11-05 13:34Brad KingNote Added: 0031436
2012-11-05 13:38Brad KingNote Added: 0031437
2012-11-05 13:38Brad KingStatusnew => backlog
2013-03-25 11:51Petr KmochFile Added: msbuild_targets_in_subdirs-patch1.zip
2013-03-25 11:56Petr KmochNote Added: 0032694
2013-03-25 13:24Brad KingNote Added: 0032695
2013-03-27 06:53Petr KmochFile Added: msbuild_targets_in_subdirs-patch2.zip
2013-03-27 06:56Petr KmochNote Added: 0032705
2013-03-27 06:56Petr KmochNote Edited: 0032705bug_revision_view_page.php?bugnote_id=32705#r1087
2013-03-27 06:57Petr KmochNote Edited: 0032705bug_revision_view_page.php?bugnote_id=32705#r1088
2013-03-27 08:53Brad KingNote Added: 0032706
2013-03-28 10:23Brad KingFile Added: msbuild_targets_in_subdirs-patch3.zip
2013-03-28 10:28Brad KingNote Added: 0032719
2013-04-06 15:51Petr KmochFile Added: msbuild_targets_in_subdirs-patch4.zip
2013-04-06 15:55Petr KmochNote Added: 0032772
2013-04-12 11:50Brad KingNote Added: 0032817
2013-04-12 11:51Brad KingAssigned To => Brad King
2013-04-12 11:51Brad KingStatusbacklog => resolved
2013-04-12 11:51Brad KingResolutionopen => fixed
2013-10-07 10:04Robert MaynardNote Added: 0034028
2013-10-07 10:04Robert MaynardStatusresolved => closed

Notes
(0031357)
Brad King   
2012-10-31 07:44   
Please try to strip the test case down to a minimal example.
(0031358)
d3x0r   
2012-10-31 11:44   
This can probably be worked around by adding .vcxproj...
cmake --build . --target doc.vcxproj

I don't know why, seems sometimes I have to specify the .vcxproj, sometimes the target would just build, but in my case it was 'install'.
(0031366)
Michael Broutin   
2012-11-01 06:26   
@d3x0r :
I finally found a workaround, but it was not by adding .vcxproj...
I had to specify the directory in which the subproject(the target) is located.
In this example, "cmake --build . --target docs\doc" worked.
The same trick doesn't work with MSBuild, so I'll use cmake --build from now.

@Brad King :
Finally, it's not a bug for "cmake --build", but the fact to have to specify subdir is a bit misleading... let's call that a usability "bug" (it should at least be in the documentation, IMO)
As soon as I get the time, I'll provide a stripped down example.
(0031397)
Michael Broutin   
2012-11-03 10:26   
@Brad King :
I just attached a minimal test case, run testBug.bat to test it.
(Visual Studio 11 or 11 express must be installed and the cmake directory in the PATH)

As I said, it may not be a bug, just something missing from the documentation..
(0031436)
Brad King   
2012-11-05 13:34   
Re 0013623:0031397: Thanks. From that example I constructed this:

$ cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(cmakebug C)
add_subdirectory(subdir)
$ cat subdir/CMakeLists.txt
add_custom_target(test #ALL
  COMMAND  "dir" VERBATIM)


One may experiment with invocations of MSBuild directly, for example passing the .sln file itself. MSBuild will internally convert the .sln into a project file. We can ask it to write the project out to disk using an environment variable:

 set msbuildemitsolution=1
 MSBuild /p:Configuration=Debug cmakebug.sln

From the resulting "cmakebug.sln.metaproj" one can see that there is no <Target> element for the "test" project. However, uncommenting the above "ALL" option makes the <Target> element for "test" appear. Then one can do

 MSBuild /p:Configuration=Debug cmakebug.sln /t:test

This won't work for non-ALL projects though so we cannot use it as a way for CMake to invoke MSBuild to drive targets through solutions.

One may also invoke MSBuild directly on the target file:

 MSBuild /p:VisualStudioVersion=11.0 /p:Configuration=Debug subdir\test.vcxproj

but it requires knowing the location of the file. Currently CMake generates a similar command line but leaves off the "subdir\" part unless it is given to the "--target" option of "cmake --build". This is the issue reported here.

We cannot simply document that one must put "subdir\" on manually because doing so does not work when CMake chooses devenv to drive command-line builds. A single "cmake --build . --target test" should work no matter how it builds underneath.

CMake's "--build" command may have to actually parse the .sln file to pass the proper path to MSBuild. For compatibility with people's existing work-arounds we should skip this approach when the "--target" value already has a slash.
(0031437)
Brad King   
2012-11-05 13:38   
The MSBuild command line generation is here in the source:

 http://cmake.org/gitweb?p=cmake.git;a=blob;f=Source/cmGlobalVisualStudio10Generator.cxx;hb=v2.8.10#l150 [^]

The approach described in 0013623:0031436 could be implemented here.

Moving to backlog until someone has time to dedicate to this.
(0032694)
Petr Kmoch   
2013-03-25 11:56   
I've added a tentative patch for this (msbuild_targets_in_subdirs-patch1.zip). However, I have few questions I'd need answered in order to polish it up:

1) My code currently parses the .sln file inside cmGlobalVisualStudio10Generator::GenerateBuildCommand(). How should I report errors if they occur? Currently, they're just silently ignored.

2) Is it safe to assume that inside GenerateBuildCommand(), the current directory will always be the one containing the .sln being built? I saw GenerateBuildCommand() is also used by CPack and CTest; I don't know what changes would be necessary there.

3) cmSystemTools::TrimWhitespace() only trims spaces from the string, no other whitespace. Is that intentional?
(0032695)
Brad King   
2013-03-25 13:24   
Re 0013623:0032694: Thanks for working on this.

1) GenerateBuildCommand is called through many different code paths and we don't have good internal error handling. I think ignoring parse errors for now is fine.

2) GenerateBuildCommand can be called when the .sln does not even exist let alone in the current working directory. You could add an optional argument for the top of the build tree and provide it from code paths where it is available. That way it will work for "cmake --build" at least.

3) TrimWhitespace was added by a contributor here:

  http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2cd36550 [^]

You'll have to check existing call sites to see if removing other whitespace (\t\r\n) is appropriate for them. If so I'm fine with adding it.

In your patch you add this line:

 + if(NOT MSVC60 AND NOT MSVC70 AND NOT MSVC80 AND NOT MSVC90)

Those variables are about the toolchain in use, not the generator. Since support for PlatformToolset in VS >= 10 was added there is a difference. Use something like

 if(CMAKE_GENERATOR MATCHES "Visual Studio (6|7|8|9) ")

instead.
(0032705)
Petr Kmoch   
2013-03-27 06:56   
(edited on: 2013-03-27 06:57)
I've incorporated the changes and uploaded a new patch (msbuild_targets_in_subdirs-patch2.zip). This one should be complete.

I've only found 3 calls to TrimWhitespace(). I believe trimmig all whitespace is appicable to all of them, so I've modified the function.

(0032706)
Brad King   
2013-03-27 08:53   
Thanks. I took the TrimWhitespace fix since it is trivial:

 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=674f918a [^]

I'll look at the rest of the changes in more detail.

Thanks for including unit tests for cmVisualStudioSlnParser.
(0032719)
Brad King   
2013-03-28 10:28   
Re 0013623:0032705: Peter, please take a look at msbuild_targets_in_subdirs-patch3.zip. I re-worked your patches a bit and added more. Net differences from yours:

* Simplified the search for MSBUILD_EXECUTABLE when adding the VSProjectInSubdir test
* Add testVisualStudioSlnParser only on windows where the needed code builds
* Portability fixes to old windows compilers (Borland 5.5, VS 6)
* Add .gitattributes to keep CRLF newlines in .sln-file samples
* Some {}-style fixes
* Drop build_command's attempt to pass projectDir because the .sln may not be available consistently when it is invoked
* Split the addition of the projectDir parameter to GenerateBuildCommand into its own commit, followed by the commit to use it in the VS 10 generator

The two new commits enable support for the new parameter in ctest_build. Can you please look at adding a test for that?
(0032772)
Petr Kmoch   
2013-04-06 15:55   
I've added a test case for ctest_build() (squashed into your last commit). Uploaded just that commit as msbuild_targets_in_subdirs-patch4.zip. Please let me know if you need anything more.

Sorry about messing up the {}-style. I'm currently switching between 3 projects, each of which uses a different style for this, so it's hard not to mix them up occasionally.
(0032817)
Brad King   
2013-04-12 11:50   
Re 0013623:0032772: Thanks Petr. I've gotten the topic through our nightly testing cleanly after some minor updates. Here it is:

 Add projectDir parameter to GenerateBuildCommand
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=de8be9ef [^]

 VS: Create parser for Visual Studio .sln files
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=df035e48 [^]

 VS: Use .sln parser to build targets in subdirs with msbuild (0013623)
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3cd40006 [^]

 VS: Add test for building MSBuild project in subdir
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1ca93182 [^]

 CTest: Simplify ctest_* command source/build dir lookup
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a6c0299c [^]

 ctest_build: Pass projectDir to GenerateBuildCommand
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ac9a5f4d [^]
(0034028)
Robert Maynard   
2013-10-07 10:04   
Closing resolved issues that have not been updated in more than 4 months.