在Windows上使⽤CMake
CMake简介
你或许听过好⼏种 Make ⼯具,例如 GNU Make ,QT 的 qmake ,微软的 MS nmake,BSD Make(pmake),Makepp,等等。这些 Make ⼯具遵循着不同的规范和标准,所执⾏的 Makefile 格式也千差万别。这样就带来了⼀个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。⽽如果使⽤上⾯的 Make ⼯具,就得为每⼀种标准写⼀次 Makefile ,这将是⼀件让⼈抓狂的⼯作。
CMake就是针对上⾯问题所设计的⼯具:它⾸先允许开发者编写⼀种平台⽆关的 ⽂件来定制整个编译流程,然后再根据⽬标⽤户的平台进⼀步⽣成所需的本地化 Makefile 和⼯程⽂件,如 Unix 的 Makefile 或 Windows 的 Visual Studio ⼯程。从⽽做
到“Write once, run everywhere”。
Windows上使⽤CMake
Windows上使⽤CMake也很⽅便,除了传统的命令⾏⽅式使⽤CMake,还有⼀个简单的GUI程序来使⽤CMake。
安装CMake
为了⽅便起见,可以把CMake加到系统PATH中。
CMake的GUI⽤法
安装好CMake,会创建⼀个快捷⽅式,点击运⾏就会运⾏,这个是CMake的GUI程序,以下图所⽰: use-cmake-on-windows
source code编辑框就是输⼊代码的所在的路径,这个路径能够到⼀个⽂件。
build the binaries编辑框就是编译输出的中间⽂件和最终的⼆进制⽂件的⽬录。
因为CMake最终通过⽂件⽣成Windows上对应的vs⼯程⽂件,不同的vs版本也会影响到最终⽣成vs⼯程⽂件,所以configure对话框就是选择代码编译⼯具的,如图所⽰: use-cmake-on-windows
下⾯以google test⼯程的代码为例来使⽤CMake-gui,输⼊google test对应的路径,点击Generate按钮就会在
E:/googletest/googletest/build⽬录⽣成vs编译⼯程⽂件: use-cmake-on-windows为什么现在都用cmake
use-cmake-on-windows
⽤vs打开gtest.sln⽂件,就可以编译google test代码了。
CMake的命令⾏⽤法
CMake的命令⾏⽤法⽐GUI的⽤法复杂,但是功能更加强⼤,值得⼀学。以下是CMake命令⾏调⽤的⽅法:
cmake [] ( | )
cmake [(-D=)…] -P
cmake --build
[] [-- …]
cmake -E […]
cmake --find-package …
⽣成编译⼯程⽂件
cmake 就是⽣成可以编译⼯程⽂件。当时运⾏的⽬录在哪⾥,⽣成的可编译⼯程⽂件就在哪个⽬录。⽐如⽂件在f:cmake ⽬录,⽽当时在f:cmakebuild⽬录运⾏cmake …,则⽣成的编译⼯程⽂件在f:cmakebuild⽬录。
也可以再⽣成编译⼯程⽂件的时候通过-D来添加变量值,⽐如内容如下:
cmake_minimum_required (VERSION 2.6)
project (a)
message(${EXECUTABLE_OUTPUT_PATH})
add_executable(b b.cpp)
我们可以通过-D选择来设置EXECUTABLE_OUTPUT_PATH的值,也是编译的⽂件的输出⽬录:
cmake -D EXECUTABLE_OUTPUT_PATH=“another_output” …
这样,我们就给编译脚本传递了新的EXECUTABLE_OUTPUT_PATH值。
编译⼯程
CMake除了⽣成编译⼯程⽂件,它也可以调⽤系统的编译⼯程来编译⼯程,如:
cmake --build .
默认是编译debug模式,也可以传递在–后⾯传递MSBUILD参数来控制:
cmake --build . -- /p:Configuration=Release
命令⾏⼯具模式
CMake有⼀个-E的命令⾏⼯具模式,提供了⼀些常⽤的功能,⽐复制⽂件、创建⽬录、读写注册表、读写环境变量、计算md5值等等。脚本可以调⽤这些功能。
编写
创建可以执⾏程序⼯程
⾸先从创建⼀个最简单的可执⾏程序开始,内容如下:
cmake_minimum_required (VERSION 2.6)
project (LearnCMake)
message(${LearnCMake_SOURCE_DIR})
message(${LearnCMake_BINARY_DIR})
add_executable(FirstExecutable hello_world.cpp)
第1⾏是cmake需要的最低版本,⽬前这个是VERSION 2.6,⼀般不⽤修改。
第2~4⾏表⽰我们创建了⼀个名为LearnCMake⼯程,对应⽣成⼀个LearnCMake.sln。project函数表⽰创建⼀个⼯程。同时,也⽣成了4个变量:
PROJECT_SOURCE_DIR, _SOURCE_DIR。⼯程的源代码⽬录。
PROJECT_BINARY_DIR, _BINARY_DIR。⼯程的⼆进制⽂件⽬录。
第5⾏表⽰添加⼀个名为FirstExecutable的可执⾏程序项⽬,它的源代码为hello_world.cpp。下⾯是add_executable的完整⽤法:
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])
默认的是创建控制台⼯程,加上WIN32表⽰创建的是win32⼯程,如下:
add_executable(FirstExecutable WIN32 hello_world.cpp)
后⾯是项⽬的代码,可以添加多个代码⽂件,⽤空格分开。
创建库⼯程
创建库⼯程跟创建可执⾏程序⼯程类似,创建库⼯程使⽤add_library函数,如下例⼦:
cmake_minimum_required (VERSION 3.0)
project (LearnCMake)
add_library(FirstLibrary first_library.cpp)
add_library(SecondLibrary second_library.cpp)
add_executable(FirstExecutable hello_world.cpp)
target_link_libraries(FirstExecutable FirstLibrary)
add_library的⽤法如下:
add_library( [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 …])
默认的是静态库,也可以显式的设置库是否为静态库、动态库或者是模块。另外BUILD_SHARED_LIBS也可控制编译成哪种库。
target_link_libraries⽤来链接库,⽤法如下:
target_link_libraries( [item1 [item2 […]]]
[[debug|optimized|general] ] …)
set 设置变量
add_library、add_executable都可以添加多个源⽂件,如下:
cmake_minimum_required (VERSION 3.0)
project (LearnCMake)
add_executable(FirstExecutable main.cpp app_util.h app_util.cpp)
add_library(FirstLibrary app_util.h app_util.cpp)
我们可以通过定义⼀个AppUtilSrc 变量来代替app_util.h app_util.cpp ,如下:
cmake_minimum_required (VERSION 3.0)
project (LearnCMake)
set(AppUtilSrcs app_util.h app_util.cpp)
add_executable(FirstExecutable main.cpp ${AppUtilSrcs})
add_library(FirstLibrary ${AppUtilSrcs})
效果是跟上⾯等价的。还可以累积值:
set(AppUtilSrcs app_util.h app_util.cpp)
set(AppUtilSrcs ${AppUtilSrcs} b.cpp)
这样AppUtilSrcs就代表着3个⽂件了。
设置编译模式
设置mt编译模式:
set(CMAKE_CXX_FLAGS_RELEASE “{CMAKE_CXX_FLAGS_DEBUG} /MTd”)
设置md编译模式:
CMAKE XX LAGS ELEASE /MT ")set (CMAKE XX LAGS EBUG "C F R C F D
set(CMAKE_CXX_FLAGS_RELEASE “{CMAKE_CXX_FLAGS_DEBUG} /MDd”)
默认是多字节模式,设置成unicode模式:
add_definitions(-D_UNICODE)
另外add_definitions还可以设置其他的选项。
添加其他
⼀个⾥⾯的target如果要链接其他中的target,可以使⽤add_subdirectory,我们以使⽤googletest库为例:
add_subdirectory("…/thirdparty/googletest/googletest/" gtest)
file(GLOB_RECURSE gtest_lib_head_files “…/thirdparty/googletest/googletest/.h")
source_group(“gtest” FILES ${gtest_lib_head_files})
include_directories("…/thirdparty/googletest/googletest/include")
aux_source_directory("./pbase_unittest/src" pbase_unittest_src_files)
file(GLOB_RECURSE pbase_unittest_include_files "./pbase_unittest/include/.h”)
add_executable(pbase_unittest ${pbase_unittest_src_files} ${pbase_unittest_include_files} ${gtest_lib_head_files})
target_link_libraries(pbase_unittest gtest)
代码控制
如果想把./pbase/src⽬录下的所有源⽂件加⼊到⼯程,可以⽤aux_source_directory把某个⽬录下的源⽂件加⼊到某个变量中,稍后就可以使⽤这个变量代表的代码了,如:
aux_source_directory("./pbase/src" pbase_lib_src_files)
add_library(pbase ${pbase_lib_src_files})
添加头⽂件包含⽬录是:
include_directories("…/thirdparty/googletest/googletest/include")
但是include_directories中的⽂件不会体现先visual studio⼯程中,⽽aux_source_directory只会添加源⽂件,会忽略头⽂件,如果想⽣存的visual studio⼯程⾥⾯也包含头⽂件,可以这样:
add head files
file(GLOB_RECURSE pbase_lib_head_files “./pbase/include/*.h”)
add_library(pbase ${pbase_lib_head_files})
如果想⽣存visual studio中的filter,可以使⽤source_group:
file(GLOB_RECURSE gtest_lib_head_files “…/thirdparty/googletest/googletest/*.h”)
source_group(“gtest” FILES ${gtest_lib_head_files})
最终添加头⽂件到⼯程⾥标准模板是:
file(GLOB_RECURSE gtest_lib_head_files “…/thirdparty/googletest/googletest/*.h”)
source_group(“gtest” FILES ${gtest_lib_head_files})
include_directories("…/thirdparty/googletest/googletest/include")
add_executable(pbase_unittest ${gtest_lib_head_files})CMAKE XX LAGS ELEASE /MD ")set (CMAKE XX LAGS EBUG "C F R C F D
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论