CMake Tutorial – Chapter 2: IDE Integration

Introduction

Now that we are familiar with CMake I will make good on CMake’s promise of flexibility. I said before that CMake could create projects for various IDE’s and in this chapter we will do so. This is one of CMake’s greatest strengths as it allows for very diverse development environments while working on the same project. It also makes it possible for you to take advantage of all available tools. If, for example, you prefer to work in Emacs or Vim and build with Make you could still create an IDE project and take advantage of its refactoring tools.

By now some of you have looked at the scroll bar and noticed that this chapter is rather long. Don’t worry I don’t expect you to read all of it and there are a lot of pictures. I present several IDEs but assume that you will only read the ones that are useful to you.

Please remember that CMake has more generators than those presented here. To list all of the available generators for your install use the command cmake --help. Most available generators are listed in the CMake documentation .

We will use the same code as we had at the end of the first chapter. It can be downloaded again here: [zip file] Source

Visual Studio

Visual Studio 2010 Express Version 10.0.30319.1 RTMTel was used.
Visual Studio 2010 Professional Version 10.0.30319.1 RTMRel was used for MSBuild

Generating a Visual Studio solution is simple, we just have to use a Visual Studio generator when we invoke CMake.

 > mkdir visualStudio
 > cd visualStudio
 > cmake -G "Visual Studio 10" ..
-- Check for working C compiler using: Visual Studio 10
-- Check for working C compiler using: Visual Studio 10 -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler using: Visual Studio 10
-- Check for working CXX compiler using: Visual Studio 10 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio

It is important to note that there are different generators for different versions of Visual Studio, so you will have to make sure that you chose the generator most appropriate for your Visual Studio install. CMake’s output is actually a lot shorter than when we first ran it. You will notice that CMake uses Visual Studio to compile rather than interacting directly with the compiler.

Of course we still did an out-of-source build so the Visual Studio project files will not clutter your source tree. This is what CMake created:

[generated files]

As you can see CMake created several Visual Studio files. The one we really care about is To Do List.sln, as you can see this is named after our CMake project. If file names containing spaces cause problems for you, or are inconvenient, then you will want to make sure your project names do not contain spaces. Let’s see what kind of solution CMake created.

Note: When you open the solution Visual Studio may display a Security Warning because it doesn’t trust the projects. This seems to be caused by CMake creating them not Visual Studio. You can just click “OK”.

[Visual Studio project window]

The generated solution is a bit more complicated than what you would have created by hand. There are 3 more projects than you would have expected since we are only building one executable and nothing else. Each project does, however, have a purpose:

ALL_BUILD
This project builds all of the targets that are defined in the CMakeLists.txt. Since we only have one in ours it is a bit redundant.
RUN_TESTS
Building this project runs CTest in much the same way that make test did. It creates the same output files, too. CTest’s output is also displayed in the Output Window. Just as before this does not depend on any of your targets, so if your tests depend on any targets be sure to build them first.
toDo
This is the little command line tool we are building. It corresponds to the add_executable command we have in our CMakeLists.txt.
ZERO_CHECK
This is a rather oddly named project. It’s purpose is to make sure that the Visual Studio solution and its projects are all up to date. If you modify the CMakeLists.txt this project will update your Visual Studio solution. All other projects depend on this one so you don’t have to build it manually. Unfortunately when the solution and projects are updated by this Visual Studio will, for each one updated, ask you if you want to reload it, which can get a bit annoying.

If you look at the “toDo” project you will notice that it only contains the .cc files. This is because those are the only files listed in the CMakeLists.txt for the toDo target. If you were to add ToDo.h to the toDo target it would appear in the “toDo” project in Visual Studio.

Let’s try and build and see what happens.

[Visual Studio build]

I used the “Start Debugging” button on the toolbar which tried to debug the “ALL_BUILD” project. So while it successfully built toDo.exe it was not run since “ALL_BUILD” does not produce any outputs, much less an executable. So if you want to actually debug “toDo” you will have to explicitly pick that project. If we explicitly debug the “toDo” project we get what we were expecting.

Note: If you set the project you want to debug as the “StartUp” project Visual Studio will debug it when you click the “Start Debugging” button. You can recognize the “StartUp” project as its name will be bold. To do this right click on the project and pick “Set as StartUp Project”.

[Visual Studio build, second try]

Unfortunately our program is run in a command window that closes as soon as our program completes, so we don’t get to see its output. However the Output Window in Visual Studio shows that toDo exited with a code of 0 which means our test still passes. So everything works fine in Visual Studio.

If you need to be able to build from the command line either because you prefer to or for an automated build process you can use the MSBuild command.

Note: MSBuild does not appear to be included with Visual Studio Express, but only Visual Studio Professional.

 > cd visualStudio
 > MSBuild ALL_BUILD.vcxproj
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.269]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 7/22/2012 1:18:41 AM.
Project "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ALL_BUILD.vcxproj" on node 1 (default targets).
Project "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ALL_BUILD.vcxproj" (1) is building "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ZERO_CHECK.vcxproj" (2) on node 1 (default targets).
PrepareForBuild:
  Creating directory "Win32\Debug\ZERO_CHECK\".
  Creating directory "Debug\".
InitializeBuildStatus:
  Creating "Win32\Debug\ZERO_CHECK\ZERO_CHECK.unsuccessfulbuild" because "AlwaysCreate" was specified.
CustomBuild:
  Checking Build System
  CMake does not need to re-run because M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio/CMakeFiles/generate.stamp is up-to-date.
FinalizeBuildStatus:
  Deleting file "Win32\Debug\ZERO_CHECK\ZERO_CHECK.unsuccessfulbuild".
  Touching "Win32\Debug\ZERO_CHECK\ZERO_CHECK.lastbuildstate".
Done Building Project "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ZERO_CHECK.vcxproj" (default targets).
Project "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ALL_BUILD.vcxproj" (1) is building "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj" (3) on node 1 (default targets).
PrepareForBuild:
  Creating directory "toDo.dir\Debug\".
InitializeBuildStatus:
  Creating "toDo.dir\Debug\toDo.unsuccessfulbuild" because "AlwaysCreate" was specified.
CustomBuild:
  Building Custom Rule M:/Programming/C++/CMake Tutorial/flavors/part1_step2/CMakeLists.txt
  CMake does not need to re-run because M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\CMakeFiles\generate.stamp is up-to-date.
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /Zi /nologo /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"toDo.dir\Debug\\" /Fd"M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio/Debug/toDo.pdb" /Gd /TP /analyze- /errorReport:queue "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\main.cc" "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\ToDo.cc"  /Zm1000 /GX /GZ
cl : Command line warning D9035: option 'GX' has been deprecated and will be removed in a future release [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
cl : Command line warning D9036: use 'EHsc' instead of 'GX' [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
cl : Command line warning D9035: option 'GZ' has been deprecated and will be removed in a future release [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
cl : Command line warning D9036: use 'RTC1' instead of 'GZ' [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
  main.cc
  ToDo.cc
  Generating Code...
ManifestResourceCompile:
  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\rc.exe /nologo /fo"toDo.dir\Debug\toDo.exe.embed.manifest.res" toDo.dir\Debug\toDo_manifest.rc
Link:
  C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:QUEUE /OUT:"M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\Debug\toDo.exe" /INCREMENTAL /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"toDo.dir\Debug\toDo.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio/Debug/toDo.pdb" /SUBSYSTEM:CONSOLE /STACK:"10000000" /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio/Debug/toDo.lib" /MACHINE:X86 toDo.dir\Debug\toDo.exe.embed.manifest.res
  toDo.dir\Debug\main.obj
  toDo.dir\Debug\ToDo.obj  /machine:X86 /debug
Manifest:
  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /out:"toDo.dir\Debug\toDo.exe.embed.manifest" /manifest toDo.dir\Debug\toDo.exe.intermediate.manifest
  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\rc.exe /nologo /fo"toDo.dir\Debug\toDo.exe.embed.manifest.res" toDo.dir\Debug\toDo_manifest.rc
LinkEmbedManifest:
  C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:QUEUE /OUT:"M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\Debug\toDo.exe" /INCREMENTAL /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"toDo.dir\Debug\toDo.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio/Debug/toDo.pdb" /SUBSYSTEM:CONSOLE /STACK:"10000000" /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"M:/Programming/C++/CMake Tutorial/flavors/part1_step2/visualStudio/Debug/toDo.lib" /MACHINE:X86 toDo.dir\Debug\toDo.exe.embed.manifest.res
  toDo.dir\Debug\main.obj
  toDo.dir\Debug\ToDo.obj  /machine:X86 /debug
  toDo.vcxproj -> M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\Debug\toDo.exe
FinalizeBuildStatus:
  Deleting file "toDo.dir\Debug\toDo.unsuccessfulbuild".
  Touching "toDo.dir\Debug\toDo.lastbuildstate".
Done Building Project "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj" (default targets).
PrepareForBuild:
  Creating directory "Win32\Debug\ALL_BUILD\".
InitializeBuildStatus:
  Creating "Win32\Debug\ALL_BUILD\ALL_BUILD.unsuccessfulbuild" because "AlwaysCreate" was specified.
CustomBuild:
  Building Custom Rule M:/Programming/C++/CMake Tutorial/flavors/part1_step2/CMakeLists.txt
  CMake does not need to re-run because M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\CMakeFiles\generate.stamp is up-to-date.
  Build all projects
FinalizeBuildStatus:
  Deleting file "Win32\Debug\ALL_BUILD\ALL_BUILD.unsuccessfulbuild".
  Touching "Win32\Debug\ALL_BUILD\ALL_BUILD.lastbuildstate".
Done Building Project "M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ALL_BUILD.vcxproj" (default targets).
Build succeeded.
"M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\ALL_BUILD.vcxproj" (default target) (1) ->
"M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj" (default target) (3) ->
(ClCompile target) ->
  cl : Command line warning D9035: option 'GX' has been deprecated and will be removed in a future release [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
  cl : Command line warning D9036: use 'EHsc' instead of 'GX' [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
  cl : Command line warning D9035: option 'GZ' has been deprecated and will be removed in a future release [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
  cl : Command line warning D9036: use 'RTC1' instead of 'GZ' [M:\Programming\C++\CMake Tutorial\flavors\part1_step2\visualStudio\toDo.vcxproj]
    4 Warning(s)
    0 Error(s)
Time Elapsed 00:00:05.49
MSBuild ALL_BUILD.vcxproj
The MSBuild tool requires the project to build as a command line argument. In this case I built everything. As you can see its output is rather verbose. (Also it seems the projects created by CMake could use some updating.)
reference, command line reference

Xcode

Mac OS X

Xcode Version 4.1 Build 4B110 was used.

Generating an Xcode project is very similar to generating any other project:

 > mkdir xcode
 > cd xcode
 > cmake -G "Xcode" ..
-- The C compiler identification is GNU 4.2.1
-- The CXX compiler identification is GNU 4.2.1
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler using: Xcode
-- Check for working C compiler using: Xcode -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler using: Xcode
-- Check for working CXX compiler using: Xcode -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode

If you look closely you will notice that most of CMake’s output looks the same as it did when we first ran it. In fact the only major difference is that CMake doesn’t directly interact with the compiler, it uses Xcode instead. We are still doing an out-of-source build so even the Xcode project won’t clutter your source tree. CMake created the following files:

[generated files]

Most of these files will look familiar if you had looked at what files CMake generated before. The most important file is To Do List.xcodeproj. Note that the project file is named after the project command in CMakeLists.txt. If spaces in file names cause trouble in your environment then you will want to ensure your project names have no spaces. Now let’s take a look at the project CMake created for us.

[Xcode project window]

The project is not as neat as one you would have made by hand. Most conspicuously ToDo.h is missing. This is because CMake doesn’t actually know about it. However because it is in the same directory as ToDo.cc the compiler will still find it. If you were to include ToDo.h in the add_executable() command then it would be included in the Xcode project. Both Xcode and CMake know not to compile header files so there would be no actual effect on the build.

You will notice the extra folders “ALL_BUILD” and “ZERO_CHECK”, these actually correspond to particular Xcode targets created by CMake. These are the targets created by CMake:

[Xcode targets]
ZERO_CHECK
This oddly named target checks your CMakeLists.txt and updates your project as needed. Just as with the generated Makefile.
toDo
This is our executable as specified by the add_executable() command. This will build our little command line tool.
RUN_TESTS
This runs CTest just as make test did before. It produces the same output files as before, too. CTest’s output, however, is not displayed, but it can be found using the Log Navigator. Also as before it does not depend on any other targets, e.g. “toDo,” even if a test does.
ALL_BUILD
This builds all targets except “RUN_TESTS” just as make did before. Since we only specified one target, “toDo,” this target is redundant, but if we had specified other targets, say another executable, this would build them all.

Let’s build toDo and see what output Xcode produces.

[Xcode build]

The “Run” button in Xcode builds and then runs the target. The build succeeded and the test still passes; so far everything works fine in Xcode. You will notice, though, that we now have a warning. If you were to look in Xcode you will find that -Wmost, -Wno-four-char-constants, and -Wno-unknown-pragmas are passed to gcc by Xcode. Our CMakeLists.txt doesn’t pass any additional options to the compiler so when we were using the Makefile generator we were using gcc’s default settings. For now don’t worry about the warning, we will get to that in chapter 3.

Now if you prefer to work from the command line but must use Xcode you can use the xcodebuild tool provided by Apple.

 > cd xcode
 > xcodebuild -list
Information about project "To Do List":
    Targets:
        ALL_BUILD
        RUN_TESTS
        ZERO_CHECK
        toDo
    Build Configurations:
        Debug
        Release
        MinSizeRel
        RelWithDebInfo
    If no build configuration is specified "Debug" is used.
 > xcodebuild
=== BUILD AGGREGATE TARGET ZERO_CHECK OF PROJECT To Do List WITH THE DEFAULT CONFIGURATION (Debug) ===
Check dependencies
PhaseScriptExecution "CMake Rules" "xcode/To Do List.build/Debug/ZERO_CHECK.build/Script-1D0B6873874D4ED8AF14DE31.sh"
    cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2"
    /bin/sh -c "\"/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/ZERO_CHECK.build/Script-1D0B6873874D4ED8AF14DE31.sh\""
echo ""
make -f /Volumes/Documents/Programming/C++/CMake\ Tutorial/flavors/part1_step2/xcode/CMakeScripts/ReRunCMake.make
make[1]: `CMakeFiles/cmake.check_cache' is up to date.
=== BUILD NATIVE TARGET toDo OF PROJECT To Do List WITH THE DEFAULT CONFIGURATION (Debug) ===
Check dependencies
CompileC "xcode/To Do List.build/Debug/toDo.build/Objects-normal/x86_64/ToDo.o" ToDo.cc normal x86_64 c++ com.apple.compilers.llvmgcc42
    cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2"
    setenv LANG en_US.US-ASCII
    /Developer/usr/bin/llvm-gcc-4.2 -x c++ -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -O0 "-DCMAKE_INTDIR=\"Debug\"" -isysroot /Developer/SDKs/MacOSX10.7.sdk -fasm-blocks -mmacosx-version-min=10.7 -gdwarf-2 "-I/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug/include" "-I/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/DerivedSources/x86_64" "-I/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/DerivedSources" -Wmost -Wno-four-char-constants -Wno-unknown-pragmas "-F/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug" -c "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/ToDo.cc" -o "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/Objects-normal/x86_64/ToDo.o"
CompileC "xcode/To Do List.build/Debug/toDo.build/Objects-normal/x86_64/main.o" main.cc normal x86_64 c++ com.apple.compilers.llvmgcc42
    cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2"
    setenv LANG en_US.US-ASCII
    /Developer/usr/bin/llvm-gcc-4.2 -x c++ -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -O0 "-DCMAKE_INTDIR=\"Debug\"" -isysroot /Developer/SDKs/MacOSX10.7.sdk -fasm-blocks -mmacosx-version-min=10.7 -gdwarf-2 "-I/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug/include" "-I/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/DerivedSources/x86_64" "-I/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/DerivedSources" -Wmost -Wno-four-char-constants -Wno-unknown-pragmas "-F/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug" -c "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/main.cc" -o "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/Objects-normal/x86_64/main.o"
/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/main.cc: In function 'int equalityTest(T1, T2, const char*, const char*, const char*, int) [with T1 = long unsigned int, T2 = int]':
/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/main.cc:34:   instantiated from here
/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/main.cc:58: warning: comparison between signed and unsigned integer expressions
Ld xcode/Debug/toDo normal x86_64
    cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2"
    setenv MACOSX_DEPLOYMENT_TARGET 10.7
    /Developer/usr/bin/llvm-g++-4.2 -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.7.sdk "-L/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug" "-F/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug" -filelist "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/Objects-normal/x86_64/toDo.LinkFileList" -mmacosx-version-min=10.7 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -o "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/Debug/toDo"
PhaseScriptExecution "CMake PostBuild Rules" "xcode/To Do List.build/Debug/toDo.build/Script-01429AA71A364B6AAE9CB89B.sh"
    cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2"
    /bin/sh -c "\"/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/toDo.build/Script-01429AA71A364B6AAE9CB89B.sh\""
echo "Depend check for xcode"
Depend check for xcode
cd /Volumes/Documents/Programming/C++/CMake\ Tutorial/flavors/part1_step2/xcode && make -C /Volumes/Documents/Programming/C++/CMake\ Tutorial/flavors/part1_step2/xcode -f /Volumes/Documents/Programming/C++/CMake\ Tutorial/flavors/part1_step2/xcode/CMakeScripts/XCODE_DEPEND_HELPER.make PostBuild.toDo.Debug
make[1]: Nothing to be done for `PostBuild.toDo.Debug'.
=== BUILD AGGREGATE TARGET ALL_BUILD OF PROJECT To Do List WITH THE DEFAULT CONFIGURATION (Debug) ===
Check dependencies
PhaseScriptExecution "CMake Rules" "xcode/To Do List.build/Debug/ALL_BUILD.build/Script-48A6EF12B1004D59A240CCC6.sh"
    cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2"
    /bin/sh -c "\"/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/xcode/To Do List.build/Debug/ALL_BUILD.build/Script-48A6EF12B1004D59A240CCC6.sh\""
echo ""
echo Build\ all\ projects
Build all projects
** BUILD SUCCEEDED **
xcodebuild -list
This lists all the targets and all the build configurations set up in the Xcode project. Xcode, by default, uses the xcodeproj file in the current directory if there is only one, which is the case when using CMake. (man page )
xcodebuild
xcodebuild assumes the first target if none is provided on the command line, much like make. Conveniently CMake made ALL_BUILD the first target. As you can see this builds everything and is a lot more verbose than the makefile created by CMake.

iOS

While cross-compiling will not be covered until later you can build for iOS using CMake and the Xcode generator. There is a Google Code Project specifically for this: ios-cmake .

Eclipse CDT4

Eclipse Indigo Version 3.7.2 Build I20110613-1736 was used.

If you want to use Eclipse you simply need to tell CMake so when you generate your project files.

 > mkdir eclipse
 > cd eclipse
 > cmake -G "Eclipse CDT4 - Unix Makefiles" ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Could not determine Eclipse version, assuming at least 3.6 (Helios). Adjust CMAKE_ECLIPSE_VERSION if this is wrong.
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
CMake Warning in CMakeLists.txt:
  The build directory is a subdirectory of the source directory.
  This is not supported well by Eclipse.  It is strongly recommended to use a
  build directory which is a sibling of the source directory.
-- Generating done
-- Build files have been written to: /home/john/Desktop/part1_step2/eclipse
 > ls -A
CMakeCache.txt  cmake_install.cmake  CTestTestfile.cmake  .project
CMakeFiles      .cproject            Makefile

Well perhaps it isn’t actually that simple. CMake warns us that Eclipse doesn’t like the build directory being a subdirectory of the source directory. As you can see it created the .project and .cproject files required by Eclipse CDT.

[Eclipse project window]

The project looks okay, however it isn’t. Certain aspects of the project will not function properly. So we will learn from our mistake and follow CMake’s advice.

 > cd ..
 > mkdir eclipse
 > cd eclipse
 > cmake -G "Eclipse CDT4 - Unix Makefiles" ../part1_step2/
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Could not determine Eclipse version, assuming at least 3.6 (Helios). Adjust CMAKE_ECLIPSE_VERSION if this is wrong.
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/john/Desktop/eclipse
 > ls -a
.   CMakeCache.txt  cmake_install.cmake  CTestTestfile.cmake  .project
..  CMakeFiles      .cproject            Makefile

CMake’s output looks the same, save for the lack of a warning, and it also created the same files as before. The project should work fine this time. Let’s have a look.

[Eclipse project window, take 2]

The project looks a lot better this time. If you are familiar with Eclipse you may know that it only supports one target per project whereas CMake supports many. In fact managing builds of complex source trees is one of CMake’s strengths. These seem to be at odds with each other. If you looked closely before you would have noticed that CMake created a Makefile and created a Makefile project for Eclipse. This allows CMake to support multiple targets and work with Eclipse. The “[Subprojects]” folder lists every CMake project included, in our case there’s just one. Similarly the “[Targets]” folder lists all of the targets defined in your CmakeLists.txt. If you looked at any of the other IDE projects generated by CMake you may be surprised to see ToDo.h included. That is because the Eclipse project includes some virtual folders which display whatever files happened to be in the corresponding directory.

Let’s try building our project and see if it still works.

[Eclipse build]

It still builds fine and as you can see Eclipse uses make to do the building. Conveniently the binary executable “toDo” is added to the project so it can easily be run or debugged from within Eclipse.

Eclipse supports Makefiles rather well so you can get it to build any of the available targets. Eclipse provides a convenient list.

[Eclipse Makefile targets]

The default is, of course, to build all targets. “[exe] toDo” is, of course our tiny example program. However there is also “[exe] toDo/fast” which has an intriguing name. The difference between the two is that the “fast” version doesn’t check if the CmakeLists.txt has changed or recalculate toDo’s dependencies. It also doesn’t calculate completion percentages. If you are sure that none of those have changed using a “fast” target can speed up your build a bit. However, the most interesting target here is “: test” which will run CTest just as make test did before. CTest’s output is displayed in the Build Console and the Testing directory is added to the project.

[Eclipse make test]

As you can see the test still passes so everything works in Eclipse.

If you desire to still build your project from the command line it is actually quite easy because CMake created Makefiles. So you can build just as you did before.

 > cd ../eclipse
 > make
[ 50%] Building CXX object CMakeFiles/toDo.dir/main.cc.o
[100%] Building CXX object CMakeFiles/toDo.dir/ToDo.cc.o
Linking CXX executable toDo
[100%] Built target toDo

KDevelop

For KDevelop 3 CMake will generate a project for you to use. KDevelop 4, however, has native CMake support making that step unnecessary.

Generated (KDevelop3)

KDevelop Version 3.3.4 was used.

If you want CMake to create a KDevelop project for you specify the “KDevelop3” generator. There is also a “KDevelop3 – Unix Makefiles” which generates the same exact files, so save yourself the typing.

 > mkdir kdevelop
 > cd kdevelop
 > cmake -G "KDevelop3" ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/john/Desktop/part1_step2/kdevelop

The output looks similar to the first time we ran it. It produces a few extra files for KDevelop, though.

[KDevelop 3 files]

The KDevelop 3 project file, To Do List.kdevelop is the most important of the new files. You will notice that CMake still created a Makefile. KDevelop’s Makefile support, however, is quite good. Let’s see the project.

[KDevelop 3 project]

Oddly the “File List” only displays ToDo.cc even though we would expect it to also include main.cc. The “File Selector” shows all of the files in your source directory. Let’s see if we can still build.

[KDevelop 3 build]

Of course it still builds. We are using the same Makefile as we originally did. The only difference this time is that KDevelop is running make for us. Thanks to KDevelop’s Makefile support we can actually build any target we want.

[KDevelop 3 targets]

By default KDevelop builds the target “all” which does exactly what you’d expect, it builds everything. There are a few targets that end with “/fast”. These “fast” targets skip some steps to save time, so be careful when using them. Dependency calculation and checking the CMakeLists.txt file for changes are skipped; also completion percentages aren’t printed. While these will build faster than the regular targets if there are any changes that require dependencies to be recalculated or any CMakeLists.txt have been changed you results will not be what you expected.

Currently the most interesting target is “test”. Building this target is, of course, the same as running make test.

[KDevelop 3 test]

Our test still passes. Don’t lie, I know you had doubts. CTest’s output is displayed in the Messages panel. Just as before CTest creates the same files, too.

If you wanted to build from the command line it’s quite simple since we have a Makefile just as before.

 > cd kdevelop
 > make
[ 50%] Building CXX object CMakeFiles/toDo.dir/main.cc.o
[100%] Building CXX object CMakeFiles/toDo.dir/ToDo.cc.o
Linking CXX executable toDo
[100%] Built target toDo

CMake Support (KDevelop4)

KDevelop Version 4.3.1 was used.

KDevelop 4 has built-in support for CMake projects. So rather than use a generator to make a new project file as was done in the previous examples we instead simply open the CMake project with KDevelop.

After launching KDevelop 4 choose “Open / Import Project…” from the “Project Menu” and follow the steps of the import process. First you will have to find you CmakeLists.txt file. KDevelop will treat it as your project file. Next it will ask for a project name and build system. It will infer both and likely be correct. Lastly it will configure your build directory and CMake binary. Again the defaults are probably sufficient. After that you will get to see your project.

[KDevelop 4 project]

The file list shows all files that are actually in the project directory. Conveniently this include ToDo.h. However you may also notice a kdev4 project file. While KDevelop4 supports CMake, including out of source builds, it does put a project file in your source directory. Although since it is only one file it is easy to clean up (or have git ignore).

Building is, of course, as simple as clicking the “Build Selection” button.

[KDevelop 4 build]

You will notice that KDevelop still uses make to build the project. The main difference here is that KDevelop also runs CMake for you. These are the files it created:

[KDevelop 4 files]

Exactly the files you should have expected.

Now if I wanted to run our little program the “Execute” button doesn’t seem to work, it merely displays an error. However if I right-click on the “toDo” entry under the project and pick “Execute As…” > “Native Application” it runs fine.

[KDevelop 4 run]

Unfortunately I cannot find a way to run the tests from within KDevelop. As it does create a Makefile project the tests can be manually run from the command line. That seems like an ugly work-around, though.

 > cd kdevelop
 > make test
Running tests...
Test project /Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/kdevelop
    Start 1: toDoTest
1/1 Test #1: toDoTest .........................   Passed    0.01 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) =   0.05 sec

Since this is a Makefile project you can easily build from the command line using make.

 > cd kdevelop
 > make
[ 50%] Building CXX object CMakeFiles/toDo.dir/main.cc.o
[100%] Building CXX object CMakeFiles/toDo.dir/ToDo.cc.o
Linking CXX executable toDo
[100%] Built target toDo

10 thoughts on “CMake Tutorial – Chapter 2: IDE Integration

  1. 1-How do I run the RUN_TESTS from Visual Studio? In other example(not a VS example) you have shown running “make test” in a console will run all the specified test and create a Testing folder with the test run results.
    2-How do I get the INSTALL part of the CMakeLists.txt to run for Visual Studio if I want to install it in to a destination?

    • For both RUN_TESTS and INSTALL (which has not been discussed yet) simply build them as you would any other target. This is unusual behavior in an IDE but if I had to guess I would say that CMake was designed with make in mind over IDE support, again I’m just guessing.

  2. Hi and thanks for your nice tutorial. I just wanted to tell you that I get an “403 Forbidden” for all of your images/screenshots. Nevertheless, I can follow the tutorial but it seems to me that this is not what you intended.

  3. In my opinion, the open source IDE Qt Creator (not specifc for Qt project development) has the best “CMake” integration so far. It doesn’t require a specific “CMake” generator. You can read more about it in the article Setting Up a CMake Project.

    The “CMake” integration in the commercial IDE CLion also looks promising, though I do not have tested it yet.

    • I agree with your opinion of Qt Creator. When I had started writing this I had only used the initial release of Qt Creator, let’s just say that the current version is significantly better. I should probably update this chapter to include at least Qt Creator. I have heard good things about JetBrains’ other refactoring tools and IDEs so CLion is probably worth a look.

      Fun fact: Qt Creator actually uses the “CodeBlocks – Unix Makefiles” or “CodeBlocks – Ninja” generators. Of course it does that for you so your statement is still valid.

      • I concur that Qt Creator is a excellent IDE for CMake projects. I use Qt Creator with its CMakeProjectManager plugin which are both installed by the Qt 5.7 windows installer from http://www.qt.io. So far, I have been able to do with Qt Creator everything that John’s tutorial covers. As with KDevelop4, it has native CMake support.

        To create a new CMake project, use its New Project wizard, select Non-Qt Project Plain C++ application, then when asked choose cmake instead of the default qmake for its Build System. The default CMakeLists.txt it creates uses the following to add any source files in CMakeLists.txt’s directory to the project

        aux_source_directory(. SRC_LIST)
        add_executable(${PROJECT_NAME} ${SRC_LIST})

        For existing CMake projects, use the Open Project wizard to open an existing CMakeLists.txt. This is how you would develop source downloaded from Lamp’s tutorial after unzipping it.

        To run tests configured in your CMakeLists.txt, click on the Projects icon on the left, click the Build and Run tab, then click the kit’s Build tab. From that screen, in the Build Steps section, click the Add Build Steps button, then add a new Build Step (i.e., ‘Build: cmake.exe –build . –target test’). Make sure the default Build Step is first in the list of Build Steps.

  4. What about handling multiple build types with CMake and Eclipse? The best I could come up with is to generate separate Debug and Release projects, which is cumbersome when Eclipse already supports multiple build configurations within one project. I end up with Eclipse indexing my code twice (3 times actually, as I also have CMake create a top-level project for Git integration) unless I close and open various projects. What a mess!

    • So CMake’s design, as I understand, works with one build folder and you would use cmake, ccmake, or cmake-gui to change the build type as desired. Of course that way you end up periodically rebuilding everything when you change build types. With some IDEs and simple configurations multiple build types can be supported at the same time, but that often becomes brittle as the CMake lists become more complicated. In fact for generators such as Visual Studio it is possible to limit the build configurations available in the IDE so that in cases when multiple build types can’t be supported at the same time.

Leave a Reply

Your email address will not be published. Required fields are marked *