cmake学习

CMake意为cross-platform make,可用于管理c/c++工程。CMake解析配置文件CMakeLists.txt生成Makefile,相比直接用Makefile管理工程,CMake更灵活和简单。

一.cmake的安装及基本语法

(1)安装cmake。

下载地址:http://www.cmake.org/cmake/resources/software.html

有linux和windows版本的.

(2)一个实例 CMake Hello World

首先编写一个简单的程序(hello.cpp):

#include <stdio.h>

int main()

{

printf("Hello World");

return 0;

}

编写CMakeLists.txt,并与hello.cpp放在同一个目录。添加如下内容:

project(hello)

cmake_minimum_required(VERSION 2.8)

aux_source_directory(. DIR_SRCS)

add_executable(hello ${DIR_SRCS})

在 CMakeLists.txt 所在的目录下创建一个build目录,进入该目录执行 CMake 命令生成构建文件:

mkdir build

cd build

cmake ..

make

./hello

此时,即可在build下生成可执行文件.

(3)CMake基本语法

编写的CMakeLists.txt需要符合一定的语法规则,它主要由CMake命令组成。

1)注释的语法:在CMake中注释使用"#"字符开始到此行结束。

2)CMake命令:命令不区分大小写(参数会区分大小写),命令由命令、参数列表组成,参数之间使用空格进行分隔。

使用一对双引号包括的字符串认为是一个参数。命令可以是一个内置命令(例如:project,add_executable等),也可以是一个用户定义的宏(macro)或者函数(function)。

3)数据类型:CMake的基本数据类型是字符串,一组字符串在一起称为列表(list),例如:

# 通过 set 命令构建一个list变量 VAR

set(VAR a b c)

#使用语法 ${VariableName} 来访问名字为 VariableName 的变量的值(变量名区分大小写)。需要注意的是,即使在字符串中也可以使用 ${VariableName} 来访问变量的值:

# 输出 VAR = a;b;c

message("VAR = ${VAR}")

#使用语法 $ENV{VariableName} 来访问环境变量的值(ENV{VariableName} 则表示环境变量本身),输出环境变量 PATH 的值

message($ENV{PATH})

set(ENV{PATH} /usr/bin)

4)条件控制和循环结构

if(expression)

#...

elseif(expression2)

#...

else()

#...

endif()

对于 if(string) 来说:

如果 string 为(不区分大小写)1、ON、YES、TRUE、Y、非 0 的数则表示真

如果 string 为(不区分大小写)0、OFF、NO、FALSE、N、IGNORE、空字符串、以 -NOTFOUND 结尾的字符串则表示假

如果 string 不符合上面两种情况,则 string 被认为是一个变量的名字。变量的值为第二条所述的各值则表示假,否则表示真。

# 此策略(Policy)在 CMake2.8.0 才被引入

# 因此这里需要指定最低 CMake 版本为 2.8

cmake_minimum_required(VERSION 2.8)

set(YES 0)

# 输出 True

if(YES)

message(True)

else()

message(False)

endif()

# 输出 False

if(${YES})

message(True)

else()

message(False)

endif()

表达式中可以包含操作符,操作符包括:

一元操作符,例如:EXISTS、COMMAND、DEFINED 等

二元操作符,例如:EQUAL、LESS、GREATER、STRLESS、STRGREATER 等

NOT(非操作符)

AND(与操作符)、OR(或操作符)

操作符优先级:一元操作符 > 二元操作符 > NOT > AND、OR

常用操作符介绍:

if(NOT expression)

为真的前提是 expression 为假

if(expr1 AND expr2)

为真的前提是 expr1 和 expr2 都为真

if(expr1 OR expr2)

为真的前提是 expr1 或者 expr2 为真

if(COMMAND command-name)

为真的前提是存在 command-name 命令、宏或函数且能够被调用

if(EXISTS name)

为真的前提是存在 name 的文件或者目录(应该使用绝对路径)

if(file1 IS_NEWER_THAN file2)

为真的前提是 file1 比 file2 新或者 file1、file2 中有一个文件不存在(应该使用绝对路径)

if(IS_DIRECTORY directory-name)

为真的前提是 directory-name 表示的是一个目录(应该使用绝对路径)

if(variable|string MATCHES regex)

为真的前提是变量值或者字符串匹配 regex 正则表达式

if(variable|string LESS variable|string)

if(variable|string GREATER variable|string)

if(variable|string EQUAL variable|string)

为真的前提是变量值或者字符串为有效的数字且满足小于(大于、等于)的条件

if(variable|string STRLESS variable|string)

if(variable|string STRGREATERvariable|string)

if(variable|string STREQUALvariable|string)

为真的前提是变量值或者字符串以字典序满足小于(大于、等于)的条件

if(DEFINED variable)

为真的前提是variable表示的变量被set定义了。

foreach 循环范例:

set(VAR a b c)

foreach(f ${VAR})

message(${f})

endforeach()

while 循环范例:

set(VAR 5)

while(${VAR} GREATER 0)

message(${VAR})

math(EXPR VAR "${VAR} - 1")

endwhile()

5)函数和宏定义

函数会为变量创建一个局部作用域,而宏则使用全局作用域。范例:

# 定义一个宏 hello

macro(hello MESSAGE)

message(${MESSAGE})

endmacro()

# 调用宏 hello

hello("hello world")

# 定义一个函数 hello

function(hello MESSAGE)

message(${MESSAGE})

endfunction()

函数和宏可以通过命令 return() 返回,但是函数和宏的返回值必须通过参数传递出去。例如:

cmake_minimum_required(VERSION 2.8)

function(get_func RESULT)

#RESULT 的值为实参的值,因此需要使用 ${RESULT}

#这里使用 PARENT_SCOPE 是因为函数会构建一个局部作用域

set(${RESULT} "Hello Function" PARENT_SCOPE)

endfunction()

macro(get_macro RESULT)

set(${RESULT} "Hello Macro")

endmacro()

# 输出 Hello Function,函数返回值

get_func(V1)

message(${V1})

# 输出 Hello Macro,宏返回值

get_macro(V2)

message(${V2})

7)字符串的一些问题

字符串可跨行且支持转移字符,例如:

set(VAR "hello

world")

message("\${VAR} = ${VAR}")

# 输出结果为:

# ${VAR} = hello

# world

二.cmake的常用命令

CMake 2.8 的命令可以在此查询:http://www.cmake.org/cmake/help/v2.8.8/cmake.html#section_Commands

1)project 命令

命令语法:project(<projectname> [languageName1 languageName2 … ] )

命令简述:用于指定项目的名称

使用范例:project(Main)

2)cmake_minimum_required命令

命令语法:cmake_minimum_required(VERSION major[.minor[.patch[.tweak]]][FATAL_ERROR])

命令简述:用于指定需要的 CMake 的最低版本

使用范例:cmake_minimum_required(VERSION 2.8)

3)aux_source_directory命令

命令语法:aux_source_directory(<dir> <variable>)

命令简述:用于将 dir 目录下的所有源文件的名字保存在变量 variable 中

使用范例:aux_source_directory(. DIR_SRCS)

4)add_executable 命令

命令语法:add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 source2 … sourceN)

命令简述:用于指定从一组源文件 source1 source2 … sourceN 编译出一个可执行文件且命名为 name

使用范例:add_executable(Main ${DIR_SRCS})

5)add_library 命令

命令语法:add_library([STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1source2 … sourceN)

命令简述:用于指定从一组源文件 source1 source2 … sourceN 编译出一个库文件且命名为 name

使用范例:add_library(Lib ${DIR_SRCS})

6)add_dependencies 命令

命令语法:add_dependencies(target-name depend-target1 depend-target2 …)

命令简述:用于指定某个目标(可执行文件或者库文件)依赖于其他的目标。这里的目标必须是 add_executable、add_library、add_custom_target 命令创建的目标

7)add_subdirectory 命令

命令语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

命令简述:用于添加一个需要进行构建的子目录

使用范例:add_subdirectory(Lib)

8)target_link_libraries命令

命令语法:target_link_libraries(<target> [item1 [item2 […]]][[debug|optimized|general] ] …)

命令简述:用于指定 target 需要链接 item1 item2 …。这里 target 必须已经被创建,链接的 item 可以是已经存在的 target(依赖关系会自动添加)

使用范例:target_link_libraries(Main Lib)

9)set 命令

命令语法:set(<variable> <value> [[CACHE <type><docstring> [FORCE]] | PARENT_SCOPE])

命令简述:用于设定变量 variable 的值为 value。如果指定了 CACHE 变量将被放入 Cache(缓存)中。

使用范例:set(ProjectName Main)

10)unset 命令

命令语法:unset(<variable> [CACHE])

命令简述:用于移除变量 variable。如果指定了 CACHE 变量将被从 Cache 中移除。

使用范例:unset(VAR CACHE)

11)message 命令

命令语法:message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] “message todisplay”…)

命令简述:用于输出信息

使用范例:message(“Hello World”)

12)include_directories 命令

命令语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)

命令简述:用于设定目录,这些设定的目录将被编译器用来查找 include 文件

使用范例:include_directories(${PROJECT_SOURCE_DIR}/lib)

13)find_path 命令

命令语法:find_path(<VAR> name1 [path1 path2 …])

命令简述:用于查找包含文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。默认的情况下,VAR 会被保存在 Cache 中,这时候我们需要清除 VAR 才可以进行下一次查询(使用 unset 命令)。

使用范例:

find_path(LUA_INCLUDE_PATH lua.h ${LUA_INCLUDE_FIND_PATH})

if(NOT LUA_INCLUDE_PATH)

message(SEND_ERROR "Header file lua.h not found")

endif()

14)find_library 命令

命令语法:find_library(<VAR> name1 [path1 path2 …])

命令简述:用于查找库文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。一个类似的命令 link_directories 已经不太建议使用了

15)add_definitions 命令

命令语法:add_definitions(-DFOO -DBAR …)

命令简述:用于添加编译器命令行标志(选项),通常的情况下我们使用其来添加预处理器定义

使用范例:add_definitions(-D_UNICODE -DUNICODE)

16)execute_process 命令

命令语法:

execute_process(COMMAND <cmd1>[args1...]]

[COMMAND <cmd2>[args2...] [...]]

[WORKING_DIRECTORY<directory>]

[TIMEOUT <seconds>]

[RESULT_VARIABLE<variable>]

[OUTPUT_VARIABLE<variable>]

[ERROR_VARIABLE<variable>]

[INPUT_FILE <file>]

[OUTPUT_FILE <file>]

[ERROR_FILE <file>]

[OUTPUT_QUIET]

[ERROR_QUIET]

[OUTPUT_STRIP_TRAILING_WHITESPACE]

[ERROR_STRIP_TRAILING_WHITESPACE])

命令简述:用于执行一个或者多个外部命令。每一个命令的标准输出通过管道转为下一个命令的标准输入。WORKING_DIRECTORY 用于指定外部命令的工作目录,RESULT_VARIABLE 用于指定一个变量保存外部命令执行的结果,这个结果可能是最后一个执行的外部命令的退出码或者是一个描述错误条件的字符串,OUTPUT_VARIABLE 或者 ERROR_VARIABLE 用于指定一个变量保存标准输出或者标准错误,OUTPUT_QUIET 或者 ERROR_QUIET 用于忽略标准输出和标准错误。

使用范例:execute_process(COMMAND ls)

18)file 命令

命令简述:此命令提供了丰富的文件和目录的相关操作(这里仅说一下比较常用的)

使用范例:

# 目录的遍历

# GLOB 用于产生一个文件(目录)路径列表并保存在variable 中

# 文件路径列表中的每个文件的文件名都能匹配globbing expressions(非正则表达式,但是类似)

# 如果指定了 RELATIVE 路径,那么返回的文件路径列表中的路径为相对于 RELATIVE 的路径

# file(GLOB variable [RELATIVE path][globbing expressions]...)

# 获取当前目录下的所有的文件(目录)的路径并保存到 ALL_FILE_PATH 变量中

file(GLOB ALL_FILE_PATH ./*)

# 获取当前目录下的 .h 文件的文件名并保存到ALL_H_FILE 变量中

# 这里的变量CMAKE_CURRENT_LIST_DIR 表示正在处理的 CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)

file(GLOB ALL_H_FILE RELATIVE${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/*.h)

三.CMake常用变量

1.${UNIX} 如果为真,表示为 UNIX-like 的系统,包括 AppleOS X 和 CygWin

2.${WIN32} 如果为真,表示为 Windows 系统,包括 CygWin

3.${APPLE} 如果为真,表示为 Apple 系统

4.${CMAKE_SIZEOF_VOID_P} 表示 void* 的大小(例如为 4 或者 8),可以使用其来判断当前构建为 32 位还是 64 位

5.${CMAKE_CURRENT_LIST_DIR} 表示正在处理的CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)

6.${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} 用于设置 ARCHIVE 目标的输出路径

7.${CMAKE_LIBRARY_OUTPUT_DIRECTORY} 用于设置 LIBRARY 目标的输出路径

8.${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 用于设置 RUNTIME 目标的输出路径

9.${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}  ${<projectname>_SOURCE_DIR}  这三个变量指代的内容是一致的,不论采用何种编译方式,都是工程顶层目录。也就是在 in source 编译时,他跟 CMAKE_BINARY_DIR 等变量一致。PROJECT_SOURCE_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。

10.${PROJECT_NAME}返回通过 PROJECT 指令定义的项目名称。

11.${CMAKE_BINARY_DIR}  ${PROJECT_BINARY_DIR}  ${<projectname>_BINARY_DIR}  这三个变量指代的内容是一致的,如果是 in source 编译,指得就是工程顶层目录;如果是 out-of-source 编译,指的是工程编译发生的目录。PROJECT_BINARY_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。

12.${CMAKE_CURRENT_SOURCE_DIR} 指的是当前处理的 CMakeLists.txt 所在的路径,比如上面我们提到的 src 子目录。

13.${CMAKE_CURRRENT_BINARY_DIR}如果是 in-source 编译,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 out-of-source 编译,他指的是 target 编译目录。使用我们上面提到的 ADD_SUBDIRECTORY(src bin)可以更改这个变量的值。使用 SET(EXECUTABLE_OUTPUT_PATH <新路径>)并不会对这个变量造成影响,它仅仅修改了最终目标文件存放的路径。

14.${CMAKE_CURRENT_LIST_FILE}输出调用这个变量的 CMakeLists.txt 的完整路径

15.${CMAKE_CURRENT_LIST_LINE}输出这个变量所在的行

16.${CMAKE_MODULE_PATH}这个变量用来定义自己的 cmake 模块所在的路径。如果你的工程比较复杂,有可能会自己编写一些 cmake 模块,这些 cmake 模块是随你的工程发布的,为了让 cmake 在处理CMakeLists.txt 时找到这些模块,你需要通过 SET 指令,将自己的 cmake 模块路径设置一下。比如SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)这时候你就可以通过 INCLUDE 指令来调用自己的模块了。

17.${EXECUTABLE_OUTPUT_PATH} 和 ${LIBRARY_OUTPUT_PATH}分别用来重新定义最终结果的存放目录,前面我们已经提到了这两个变量。

四.构建类型

CMake 为我们提供了四种构建类型:

Debug

Release

MinSizeRel

RelWithDebInfo

如果使用 CMake 为 Windows MSVC 生成 projects/workspaces 那么我们将得到上述的 4 种解决方案配置。

如果使用 CMake 生成 Makefile 时,我们需要做一些不同的工作。CMake 中存在一个变量 CMAKE_BUILD_TYPE 用于指定构建类型,此变量只用于基于 make 的生成器。我们可以这样指定构建类型:

$ CMake -DCMAKE_BUILD_TYPE=Debug .

这里的 CMAKE_BUILD_TYPE 的值为上述的 4 种构建类型中的一种。

生成Debug和Release版本

在 Visual Studio 中我们可以生成 debug 版和 release 版的程序,使用 CMake 我们也可以达到上述效果。debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化,而 release 版的不需要调试信息但需要优化。这些特性在 gcc/g++ 中是通过编译时的参数来决定的,如果将优化程度调到最高需要设置参数-O3,最低是 -O0 即不做优化;添加调试信息的参数是 -g -ggdb ,如果不添加这个参数,调试信息就不会被包含在生成的二进制文件中。

CMake 中有一个变量CMAKE_BUILD_TYPE ,可以的取值是 Debug、Release、RelWithDebInfo 和 MinSizeRel。当这个变量值为 Debug 的时候,CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG中的字符串作为编译选项生成Makefile ,当这个变量值为 Release 的时候,工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和CMAKE_C_FLAGS_RELEASE 选项生成 Makefile。

示例:

PROJECT(main)

CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

SET(CMAKE_SOURCE_DIR .)

SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")

SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

AUX_SOURCE_DIRECTORY(. DIR_SRCS)

ADD_EXECUTABLE(main ${DIR_SRCS})

第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和CMAKE_CXX_FLAGS_RELEASE, 这两个变量是分别用于 debug 和 release 的编译选项。

五.编译和链接标志

C 编译标志相关变量:

CMAKE_C_FLAGS

CMAKE_C_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

C++ 编译标志相关变量:

CMAKE_CXX_FLAGS

CMAKE_CXX_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

CMAKE_C_FLAGS 或CMAKE_CXX_FLAGS 可以指定编译标志

CMAKE_C_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]或 CMAKE_CXX_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO] 则指定特定构建类型的编译标志,这些编译标志将被加入到 CMAKE_C_FLAGS 或 CMAKE_CXX_FLAGS 中去,例如,如果构建类型为 DEBUG,那么 CMAKE_CXX_FLAGS_DEBUG 将被加入到 CMAKE_CXX_FLAGS中去.

链接标志相关变量:

CMAKE_EXE_LINKER_FLAGS

CMAKE_EXE_LINKER_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

CMAKE_MODULE_LINKER_FLAGS

CMAKE_MODULE_LINKER_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

CMAKE_SHARED_LINKER_FLAGS

CMAKE_SHARED_LINKER_FLAGS_[DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO]

它们类似于编译标志相关变量

六.编译32位和64位程序

对于 Windows MSVC,我们可以设定 CMake Generator 来确定生成 Win32 还是 Win64 工程文件,例如:

# 用于生成 Visual Studio 10Win64 工程文件

CMake -G "Visual Studio 10 Win64"

# 用于生成 Visual Studio 10Win32 工程文件

CMake -G "Visual Studio 10"

我们可以通过 CMake --help 来查看当前平台可用的 Generator。

CMake .. -DUSE_32BITS=1

if(USE_32BITS)

message(STATUS "Using 32bits")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}-m32")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}-m32")

else()

endif(USE_32BITS)

对于 UNIX 和类 UNIX 平台,我们可以通过编译器标志(选项)来控制进行 32 位还是 64 位构建。

GCC命令行参数

32位版:加上 -m32 参数,生成32位的代码。

64位版:加上 -m64 参数,生成64位的代码。

debug版:加上 -g 参数,生成调试信息。

release版:加上 -static 参数,进行静态链接,使程序不再依赖动态库。加上 -O3 参数,进行最快速度优化。加上-DNDEBUG参数,定义NDEBUG宏,屏蔽断言。

当没有-m32或-m64参数时,一般情况下会生成跟操作系统位数一致的代码,但某些编译器存在例外,例如——

32位Linux下的GCC,默认是编译为32位代码。

64位Linux下的GCC,默认是编译为64位代码。

Window系统下的MinGW,总是编译为32位代码。因为MinGW只支持32位代码。

Window系统下的MinGW-w64(例如安装了TDM-GCC,选择MinGW-w64),默认是编译为64位代码,包括在32位的Windows系统下。

Makefile文件中的示例:

# [args] 生成模式. 0代表debug模式, 1代表release模式. makeRELEASE=1.

ifeq ($(RELEASE),0)

CFLAGS += -g

else

#release

CFLAGS += -static -O3 -DNDEBUG

LFLAGS += -static

endif

# [args] 程序位数. 32代表32位程序, 64代表64位程序, 其他默认. makeBITS=32.

ifeq ($(BITS),32)

CFLAGS += -m32

LFLAGS += -m32

else

ifeq($(BITS),64)

CFLAGS += -m64

LFLAGS += -m64

else

endif

endif

七.多源文件目录的处理方式

例子1:其他源目录文件当作库文件

我们在每一个源码目录中都会放置一个 CMakeLists.txt 文件。我们现在假定有这么一个工程:

HelloWorld

|

+------- Main.cpp

|

+------- CMakeLists.txt

|

+------- Lib

|

+------- Lib.cpp

|

+------- Lib.h

|

+------- CMakeLists.txt

这里 Lib 目录下的文件将被编译为一个库。首先,我们看一下 Lib 目录下的 CMakeLists.txt 文件:

aux_source_directory(. DIR_SRCS)

add_library(Lib STATIC ${DIR_SRCS})

然后,看一下 HelloWorld 目录下的 CMakeLists.txt 文件:

project(Main)

cmake_minimum_required(VERSION 2.8)

add_subdirectory(Lib)  #表示需要执行lib下的CMakeLists.txt

INCLUDE_DIRECTORIES(Lib) #.h文件的搜索路径

aux_source_directory(. DIR_SRCS)

add_executable(Main ${DIR_SRCS})

target_link_libraries(Main Lib)

这里使用了 add_subdirectory 指定了需要进行构建的子目录,并且使用了 target_link_libraries 命令,表示 Main 可执行文件需要链接 Lib库。我们执行 CMake . 命令,首先会执行 HelloWorld 目录下的 CMakeLists.txt 中的命令,当执行到 add_subdirectory(Lib) 命令的时候会进入 Lib 子目录并执行其中的CMakeLists.txt 文件。

例子2:多目录下的源文件使用一个 CMakeLists.txt编译

一个完整的Demo可参考这里。假设当前目录的结构为

Demo

|

+------- a.cpp

|

+------- b.cpp

|

+------- include

|

+------- common.h

|

+------- defines.h

+------- other

|

+------- c.cpp

|

+------- d.cpp

|

+------- CMakeLists.txt

|

+------- Lib

|

+------- libB.a

|

+------- libBd.a

|

+------- libA.so

|

+------- libAd.so

|

+------- libB.so

|

+------- libBd.so

|

+------- libC.so

|

+------- libCd.so

使用下面的CMakeLists.txt文件,目标是编译当前目录和./other目录下的所有源文件,并链接./lib目录下的相应库文件到最终的可执行文件./bin/hello(或./bin/hellod)。

cmake_minimum_required(VERSION 2.8)

project(helloworld)

set(CMAKE_VERBOSE_MAKEFILE on)

set(CMAKE_CXX_COMPILER "g++")

set(CMAKE_CXX_FLAGS "-Wall")

set(CMAKE_CXX_FLAGS_DEBUG "-g3")

set(CMAKE_CXX_FLAGS_RELEASE "-O2")

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

set(SRC_LIST "")

aux_source_directory(.  tmpdir)

set(DIR_SRCS ${SRC_LIST} ${tmpdir})

aux_source_directory(./other  tmpdir)

set(DIR_SRCS ${SRC_LIST} ${tmpdir})

#...  ... 这里可以用一个foreach来做

include_directories(${PROJECT_SOURCE_DIR}/include)

link_directories(${PROJECT_SOURCE_DIR}/lib)

if(${CMAKE_BUILD_TYPE} MATCHES "debug")

add_executable(hellod ${SRC_LIST})

target_link_libraries(hellod Ad Bd.a Cd.so)

else()

add_executable(hello ${SRC_LIST})

target_link_libraries(hello A B.a C.so)

endif()

执行命令cmake -DCMAKE_BUILD_TYPE=debug . 生成Makefile,make之后生成./bin/hellod(调试版本),或执行cmake .最后生成./bin/hello。

例子3 CMakeLists.txt文件的一般写法(一个简单的模板,用于生成库或可执行文件)

#(1)指明cmke需要的版本及工程名

cmake_minimum_required(VERSION 2.8)

project(helloworld)

#(2)指明工程的CMakeLists.txt树节点.(通常用于库工程的编译或多工程的编译,指明其他工程的CMakeLists.txt的路径),目的是形成CMakeLists.txt树,但各个CMakeLists.txt之间是隔离的.

add_subdirectory(lib)      #lib工程,可能要生成静态或动态库

add_subdirectory(sample1)  #sample1工程,可能需要生成一个.exe

...

#(3)添加本工程的宏定义

add_definitions(-D_UNICODE -DUNICODE)

#(4)添加本工程的头文件搜索路径及已有库的搜索路径

include_directories(Lib)  #多路径时,用空格分隔

link_directories(/usr/lib /usr/local/lib)

#(5)添加本工程所有源文件所在路径

set(SRC_LIST "") #使用这种方式添加其实挺方便

aux_source_directory(.  tmpdir)

set(DIR_SRCS ${SRC_LIST} ${tmpdir})

aux_source_directory(./other  tmpdir)

set(DIR_SRCS ${SRC_LIST} ${tmpdir})

...

#(6)添加本工程生成的目标,可执行目标或库目标

add_executable(main ${DIR_SRCS}) 或者 add_library(hello STATIC ${DIR_SRCS})

#(7)添加本工程目标所依赖的库目标及其他已有库

target_link_libraries(main hello pthread ) #链接库用空格分隔

时间: 06-29

cmake学习的相关文章

cmake 学习-cmakelists.txt

#设置库的路径,电脑里有qt4以及qt5,使用qt5时 设置qt5的环境变量(路径). 1 set(CMAKE_PREFIX_PATH $ENV{QTDIR}) 2 #设定工程名称 3 Project(proname) 4 #设置CMake最低版本要求 5 cmake_minimum_required(VERSION 3.6.0) 6 7 #设置需要用到的Qt模块 8 9 FIND_PACKAGE(Qt5Core) #包含qt5core的头文件 10 include_directories(${

ubuntu16.04下CMake学习

http://www.cnblogs.com/xsfmg/p/5902549.htmlhttp://www.cnblogs.com/xsfmg/p/5908064.html

CMake入门以及学习笔记

使用cef3替代chromium内核开发产品过程中,第一次接触到系统构建,使用了最常见的CMake.CMake虽然在构建系统中用的比较多,但是使用到的程序员还是很少的.现在在国内能找到的相关资料和博客比较多,本人在学习中也看了很多人的博客,比如 CMake学习(一)  , CMake语法之流程控制 等.再次感谢这些作者的分享.下边提供一些系统学习的资料. CMake的官网地址:http://www.cmake.org/ CMake主要的文档<learning_cmake> <CMake

【转载】cmake编写

Cmake的输入是在源码目录下的CMakeLists.txt文件.这个文件可以用include或者 add_subdirectory 命令增加入其它的输入文件. 语法 CMakeList.txt文件是由注释.命令和空白字符组成. 注释是由 # 开始,到行结尾. 命令是由:命令名.(.空格分隔的参数.)组成. 例如:command (args….) 上面的command可以是一个命令名:或者是一个宏:也可以是一个函数名. args是以空格分隔的参数例表(如果参数中包含空格,则要加双引号) 除了用于

【OSG学习笔记之一:】OSG+VS2010+win7 64位环境搭建

虽然出生的时候,没有说过“Hello World!”,但是自从走上了编程之路,每一次输出“Hello World!”的时候,都觉得好比中了彩票大奖似的: 仔细算算,从2012年暑假到现在,经历了3年半的光阴,这段时间,不仅是知识.阅历.成长获得最大的一段,也是人生的一大转折点.在这期间,得以继续深造学习自己的专业,虽然踏入这行的时候,也是调剂来的,但是我用这3年的时间,恶补自己7年的不足:2015年,发生了三件大事,我毕业了,我工作了,我有女票了(三件事的重要程度递增):吃得苦中苦,方位人上人,

推荐系统学习07-Waffles

介绍 Waffles 英文原意是蜂蜜甜饼,在这里却指代一个很强大的机器学习的开源工具包. Waffles里包括的算法特别多.涉及机器学习的方方面面,推荐系统位于当中的Waffles_recommend  tool,大概仅仅占整个Waffles的1/10的内容,其他还有分类.聚类.採样.降维.数据可视化.音频处理等许很多多工具包,预计能与之媲美的也就数Weka了. 你能够在waffles看到关于这个工具的具体内容. 你还能够訪问waffles的github网站. waffles与其它的机器学习工具

cmake 之一个小例子

cmake,比手写makefile更好的选择 安装cmake,此部分略过 一.新建一个工程 这里我是在windows下使用eclipse新建了一个c工程(PS:我一般新建一个Makefile类型的工程,这样比较干净) 二.建立必要的文件夹 我的工程目录: D:\code\cpp\cmakestudy\test>tree /f 卷 软件 的文件夹 PATH 列表 卷序列号为 0006-17B7 D:. │ .cproject │ .project │ CMakeLists.txt │ ├─bin

OpenCV2学习笔记(二十一):GPU模块小记

接触一下OpenCV里一个之前没有接触的模块:GPU.这里只是根据教程和大家简单交流一下,欢迎大家批评指正. 注:在使用GPU模块之前,需要确认在使用CMake编译OpenCV时,勾选了选项WITH_CUDA和WITH_TBB使其生效生效. 若以上配置已经完成,在使用GPU模块的函数之前,还做一下检查:调用函数gpu::getCudaEnabledDeviceCount,如果你在使用的OpenCV模块编译时不支持GPU,这个函数返回值为0:否则返回值为已安装的CUDA设备的数量. OpenCV的

Jenkins学习

学习目标 搭建一个完整的CI服务器,该CI服务器具有以下特性: 自动从SVN下代码 自动执行编译打包脚本,并能够获取到编译好的版本,到windows服务器 输出静态检查的结果,显示编译的结果 触发构建 支持单元测试输出结果 先这么多吧,一步一步的来.顺带熟悉一下,HTTP 服务器以及Cmake等工具. 2014-11-30 今天完成插件的安装