分享

CMake and Visual Studio | Cognitive Waves

 凤凰苑凶真 2016-09-22

CMake produces Visual Studio solutions seamlessly. This post will map CMake commands to the Visual Studio IDE with an example which makes learning much easier. It is primarily intended for a C++ developer using Visual Studio. Most references here is based on Visual Studio 2010 but will apply equally well to other versions. Continuing from the preface CMake for Visual Studio Developers.

Introduction
Visual Studio to CMake Mapping
Example
    Source Structure
    Execute CMake
    Visual Studio Solution Explorer View
    Build and Run
    Test
    CMakeLists.txt Details
CMake pre-defined projects
Debug and Release Configurations
Conclusion

Introduction

A short background on the CMake philosophy. Typically source should be considered as any files that are explicitly modified by the developer. Anything that is or can be consistently generated from the source files should be considered as output of the build process. A build will always generate a lot of temporary/intermediate files and to avoid polluting the actual source, it is recommended to have out of source builds.

Other than the typical intermediate files like .obj, Visual Studio produces many more transient files including .sln, .sbr, .suo, .vcxproj.user, .vcxproj.filters. These need not (and should not) be checked into the source repository as sometimes they are large and user specific.

A Visual Studio developer might consider the project file (.vcproj) as a “source” since it involves adding, removing source files and modifying dependencies etc. However, with CMake you can consider this to be an intermediate file too, as CMake will generate it and is recommended for it to be outside the source directory.

In a CMake build system, the build “rules” or “project settings” are defined in text files called CMakeLists.txt.

Visual Studio to CMake Mapping

Some common Visual Studio project operations and settings and its mapping to CMake is listed below as an overview.

Visual Studio CMake Command
Solution file (.sln) project
Project file (.vcproj) target name in the command add_executable or add_library
executable (.exe) add_executable
static library (.lib) add_library
dynamic library (.dll) add_library(SHARED)
Source Folders source_group
Project Folders set_property(TARGET <target> PROPERTY FOLDER <name>)
Properties->C/C++->Preprocessor->Preprocessor Definitions add_definitions
Properties->C/C++->General->Additional Include Directories include_directories
Properties->Linker->General->Additional Library Directories link_directories
Properties->Linker->Input->Additional Dependencies target_link_libraries

Example

The CMake tutorial from http://www./cmake/help/cmake_tutorial.html is a very simple example. Please refer to it if you are not familiar with the basics. Here it has been enhanced to show specific aspects commonly used on Windows.
 
The example code can be accessed via GitHub at https://github.com/cognitivewaves/CMake-VisualStudio-Example. For those not familiar with GitHub, the same example code is in a 7z file. Right mouse click on tutorial-7z.jpg, Save Link As on to disk, rename it as Tutorial.7z and extract the zip file for the sources.

Source Structure

CMake-VisualStudio-Example
   |-- app
   |   |-- CMakeLists.txt
   |   |-- main.cxx
   |-- math
   |   |-- advanced
   |   |   |-- AdvancedFunctions.cxx
   |   |   |-- AdvancedFunctions.h
   |   |-- simple
   |   |   |-- SimpleFunctions.cxx
   |   |   |-- SimpleFunctions.h
   |   |-- CMakeLists.txt
   |   |-- MathExports.h
   |-- CMakeLists.txt
   |-- TutorialConfig.h.in

Execute CMake

As recommended earlier, for an out of source build, create a directory where CMake will produce the required Visual Studio Project files and a lot of CMake specific files.

D:\tmp\CMake-VisualStudio-Example> mkdir _build

Make the build directory the current working directory.

D:\tmp\CMake-VisualStudio-Example> cd _build

Run the CMake command and specify where to find the first(root) CMakeLists.txt. In this case ".." is used to indicate one directory up from the current working directory. The -G option specifies it to generate a Visual Studio 2010 Win64 project files. Note that there are other generators that can be specified.

D:\tmp\CMake-VisualStudio-Example\_build> cmake .. -G "Visual Studio 10 Win64"

The Visual Studio solution file will be created in the _build directory.

Visual Studio Solution Explorer View

Open the solution file in Visual Studio.
cmake_vs_solution

Build and Run

Build the solution in Visual Studio. The output binary files (app.exe, math.dll) from the build are created under their own sub-directories in the _build directory. So you will not be able to run the executable in this state because it will not be able to find math.dll

This is where install comes into play. Build INSTALL.vcproj as it does not get built as part of the solution. This project copies the binaries to _build\bin\ directory.

The executable can now be run in a command window.

D:\tmp\CMake-VisualStudio-Example\_build\bin> app.exe 200
The sum of 200 and 200 is 400
The square root of 200 is 14.1421
? Note that project ALL_BUILD is the default “Startup Project”. This is never the case for debugging. So right click on the executable project (app in this case) and select as “Startup Project”.

? To run/debug it from Visual Studio, the properties on the executable project (app in this case), must be changed.
Set Properties->Debugging->Command to ..\bin\app.exe.
Set Properties->Debugging->Command Arguments to 200

Test

Invoking CTest from the build directory will run the tests. Alternatively, the tests can be run within the Visual Studio environment by right click “Build” on the RUN_TESTS project and the test run report will be displayed in the output window.

D:\tmp\CMake-VisualStudio-Example\_build>ctest
Test project D:/tmp/CMake-VisualStudio-Example/_build
    Start 1: AppTest1
1/3 Test #1: AppTest1 .........................   Passed    0.00 sec
    Start 2: AppTest2
2/3 Test #2: AppTest2 .........................   Passed    0.00 sec
    Start 3: AppTest3
3/3 Test #3: AppTest3 .........................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 3

Total Test time (real) =   0.03 sec

CMakeLists.txt Details

The comments in each line provides more details about each CMake command.

File: CMake-VisualStudio-Example/CMakelist.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
cmake_minimum_required (VERSION 2.6)
# Maps to Visual Studio solution file (Tutorial.sln)
# The solution will have all targets (exe, lib, dll)
# as Visual Studio projects (.vcproj)
project (Tutorial)
# Turn on the ability to create folders to organize projects (.vcproj)
# It creates "CMakePredefinedTargets" folder by default and adds CMake
# defined projects like INSTALL.vcproj and ZERO_CHECK.vcproj
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Set compiler flags and options.
# Here it is setting the Visual Studio warning level to 4
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
# Command to output information to the console
# Useful for displaying errors, warnings, and debugging
message ("cxx Flags: " ${CMAKE_CXX_FLAGS})
# Sub-directories where more CMakeLists.txt exist
add_subdirectory(app)
add_subdirectory (math)
# Turn on CMake testing capabilities
enable_testing()
# Add test cases
add_test(AppTest1 ${PROJECT_BINARY_DIR}/bin/app.exe 100)
add_test(AppTest2 ${PROJECT_BINARY_DIR}/bin/app.exe 200)
add_test(AppTest3 ${PROJECT_BINARY_DIR}/bin/app.exe 300)

File: CMake-VisualStudio-Example/math/CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# Collect sources into the variable MATH_SOURCES without
# having to explicitly list each header and source file.
#
# CMake documentation states "We do not recommend using GLOB to collect a
# list of source files from your source tree. If no CMakeLists.txt file
# changes when a source is added or removed then the generated build system
# cannot know when to ask CMake to regenerate".
file (GLOB MATH_SOURCES
      "*.h")
# Collect sources into the variable SIMPLE_FUNCTION_SOURCES
file (GLOB SIMPLE_FUNCTION_SOURCES
      "simple/*.h",
      "simple/*.cxx")
# The recommended way to collect sources in variable
# ADVANCED_FUNCTION_SOURCES by explicitly specifying the source files
set  (ADVANCED_FUNCTION_SOURCES
      "advanced/AdvancedFunctions.h"
      "advanced/AdvancedFunctions.cxx")
# Create named folders for the sources within the .vcproj
# Empty name lists them directly under the .vcproj
source_group("" FILES ${MATH_SOURCES})
source_group("simple" FILES ${SIMPLE_FUNCTION_SOURCES})
source_group("advanced" FILES ${ADVANCED_FUNCTION_SOURCES})
# Properties->C/C++->General->Additional Include Directories
include_directories (.)
# Set Properties->General->Configuration Type to Dynamic Library(.dll)
# Creates math.dll with the listed sources collected in the variables
# Also adds sources to the Solution Explorer
add_library(math SHARED ${MATH_SOURCES}
                        ${SIMPLE_FUNCTION_SOURCES}
                        ${ADVANCED_FUNCTION_SOURCES})
# Creates folder "libraries" and adds target project (math.vcproj)
set_property(TARGET math PROPERTY FOLDER "libraries")
# Adds logic to INSTALL.vcproj to copy math.dll to destination directory
install (TARGETS math
         RUNTIME DESTINATION ${PROJECT_BINARY_DIR}/bin)

File: CMake-VisualStudio-Example/app/CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Properties->C/C++->General->Additional Include Directories
include_directories ("${PROJECT_SOURCE_DIR}/Math")
# Set Properties->General->Configuration Type to Application(.exe)
# Creates app.exe with the listed sources (main.cxx)
# Adds sources to the Solution Explorer
add_executable (app main.cxx)
# Properties->Linker->Input->Additional Dependencies
target_link_libraries (app math)
# Creates a folder "executables" and adds target
# project (app.vcproj) under it
set_property(TARGET app PROPERTY FOLDER "executables")
# Adds logic to INSTALL.vcproj to copy app.exe to destination directory
install (TARGETS app
         RUNTIME DESTINATION ${PROJECT_BINARY_DIR}/bin)

CMake pre-defined projects

To add some CMake functionality to the Visual Studio environment, it creates a few project files which can be ignored for the most part. In any case, a brief description is given below.

INSTALL CMake install specification. It is simulating the Linux make install so it has to be manually built after the full build.
RUN_TESTS CMake test specification. This project will enable running tests in Visual Studio and the test run report will be shown in the output window
ZERO_CHECK Used to make sure that the project files are up-to-date with respect to the CMakeLists.txt files
ALL_BUILD Builds all projects with its dependency order

Debug and Release Configurations

Visual Studio supports multiple configurations in a single project file and creates a per-configuration directory. CMake generates four configurations by default: Debug, Release, MinSizeRel and RelWithDebInfo.

See the link for changing the default.
CMake Wiki: How can I specify my own configurations (for generators that allow it) ?

Conclusion

CMake is a better build system than Visual Studio projects and solutions. It is compact and much more easier to maintain even for a Windows only projects.

Hope the the document is useful. Feel free to comment if you need any clarifications or further information.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多