CMake是一个比make更高级的编译配置工具,它可以根据不同平台、不同的编译器,生成相应的Makefile或者vcproj项目。通过编写CMakeLists.txt,可以控制生成的Makefile,从而控制编译过程。CMake自动生成的Makefile不仅可以通过make命令构建项目生成目标文件,还支持安装(make install)、测试安装的程序是否能正确执行(make test,或者ctest)、生成当前平台的安装包(make package)、生成源码包(make package_source)、产生Dashboard显示数据并上传等高级功能,只要在CMakeLists.txt中简单配置,就可以完成很多复杂的功能,包括写测试用例。如果有嵌套目录,子目录下可以有自己的CMakeLists.txt。总之,CMake是一个非常强大的编译自动配置工具,支持各种平台,KDE也是用它编译的,感兴趣的可以试用一下。
当然,类似的make工具也很多,Autocof、JAM、QMake、SCons甚至ANT,目的都是指定一套规则来简化整个构建编译流程。CMake工具链简单、灵活,且跨平台,很多知名项目都在使用CMake构建。适合以C、C++或者java等编译语言的项目。
2.1 CMake的安装
CMake下载地址为:https://cmake.org/download/
2.2 CMake-gui的使用
CMake的安装过程很简单,这里就不再赘述了。其中CMake提供带GUI界面的工具cmake-gui。本文主要是以命令行的形式来讲述CMake的使用,这里就稍微提一下cmake-gui的使用。原理都是差不多的。
简述操作步骤如下:
hello_cmake.c:
#include
int main() {
printf("Hello CMake\n");
return 0;
}
CMakeLists.txt:
make_minimum_required (VERSION 2.8)
project (HelloCMake)
add_executable(HelloCMake hello_cmake.c)
3、运行cmake-gui,会打开如下界面:
为了答谢大家关注和支持,这次给大家准备了限时领取福利:阿里面试题、百度面试题、滴滴面试题、华为面试题、京东面试题、美团面试题、腾讯面试题、头条面试题、中兴面试题。
还等什么小编推荐自己的linuxC/C++语言交流群:【1106675687】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!前100名进群领取,额外赠送一份价值199的C/C++、linux资料包含(视频教程、电子书、实战项目及代码),下面部分展示。
2.3 CMake命令行的使用
这里,依然使用刚才的示例来说明下CMake命令行的方式的使用(清理bin目录下的文件即可),使用步骤如下:
在当前构建的路径,执行cmake,cmake后面参数为CMakeLists.txt所在路径,-G用来指定构建生成目标平台的项目工程。分别对应上面的GUI的操作。
在Cygwin中新版的CMake会报警告(在32位Windows系统上则会报错)。
由此可见,在Unix系列的操作系统上,使用CMake步骤分为:
2.4 CMake命令行说明
CMake命令行的选项可以在命令行终端上,输入cmake --help查看。更详尽的解释可以查看CMake的官方手册。
CMake命令行格式为:
(1) cmake [<options>] (<path-to-source> | <path-to-existing-build>)
(2) cmake [(-D <var>=<value>)...] -P <cmake-script-file>
(3) cmake --build <dir> [<options>...] [-- <build-tool-options>...]
(4) cmake -E <command> [<options>...]
(5) cmake --find-package <options>...
常见的使用方式是第一种。这里也主要介绍这种方式。
(1)[
cmake .
这里option为空,构建的路径为用户所在的当前路径。
其中option常用的有:
-G < generator-name >:
指定构建系统生成器,当前平台所支持的generator-name可以通过帮助手册查看。例如: cmake -G “Visual Studio 11 2012” E:\workplace\cmake,生成VS2012的构建工程。
-D :
添加变量及值到CMakeCache.txt中。例如:cmake -D EXECUTABLE_OUTPUT_PATH=“bin” .,会在CMakeCache.txt中添加一条
//No help, variable specified on the command line.
EXECUTABLE_OUTPUT_PATH:UNINITIALIZED=bin
这样,可以在CMakeLists.txt文件中读取该变量的值。例如:message(${EXECUTABLE_OUTPUT_PATH})
-U
此选项可用于从CMakeCache.txt文件中删除一个或多个变量,支持使用*和?的匹配。与-D对应,使用是须谨慎,可能会导致CMakeCache.txt不工作。
-i:
以向导的方式运行CMake。此选项会弹出一系列的提示,要求用户回答关于工程配置的一些问题。这些结果会被用来设置cmake的缓存值。注意,新版的CMake可能不再支持此选项。
-E:
CMake命令行模式。CMake提供了一系列与平台无关的命令。例如:copy,make_directory,echo等,更多详细参见cmake -E help。
用CMake构建一个项目工程,是通过一个或多个CMakeLists.txt文件来控制的。CMakeLists.txt中包含一系列命令来描述需要执行的构建。
3.1 CMake语法
在CMakeLists.txt中的命令的语法,都是形如下面这种格式:
command (args...)
command:是命令的名字。
args:是参数的列表。多个参数使用空格隔开。
3.1.1 常用的命令
cmake_minimum_required:设置项目要求的CMake最低版本号,如果当前版本的CMake低于所需的值,它将停止处理项目并报告错误。注意在project之前调用该命令,一般在CMakeLists.txt文件开头调用。命令格式为:
cmake_minimum_required(VERSION major.minor[.patch[.tweak]]
[FATAL_ERROR])
使用示例:
cmake_minimum_required(VERSION 2.8.5)
add_custom_command:该命令可以为生成的构建系统添加一条自定义的构建规则。这里又包含两种使用方式,一种是通过自定义命令在构建中生成输出文件,另外一种是向构建目标添加自定义命令。命令格式分别为
(1)生成文件
add_custom_command(OUTPUT output1 [output2 ...]
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[MAIN_DEPENDENCY depend]
[DEPENDS [depends...]]
[BYPRODUCTS [files...]]
[IMPLICIT_DEPENDS <lang1> depend1
[<lang2> depend2] ...]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[DEPFILE depfile]
[VERBATIM] [APPEND] [USES_TERMINAL])
参数介绍:
OUTPUT:指定命令预期产生的输出文件。如果输出文件的名称是相对路径,即相对于当前的构建的源目录路径。输出文件可以指定多个output1,output2(可选)等。
COMMAND:指定要在构建时执行的命令行。如果指定多个COMMAND,它们讲按顺心执行。ARGS参数是为了向后兼容,为可选参数。args1和args2为参数,多个参数用空格隔开。
MAIN_DEPENDENCY:可选命令,指定命令的主要输入源文件。
DEPENDS:指定命令所依赖的文件。
BYPRODUCTS:可选命令,指定命令预期产生的文件,但其修改时间可能会比依赖性更新,也可能不会更新。
IMPLICIT_DEPENDS:可选命令,请求扫描输入文件的隐式依赖关系。给定的语言指定应使用相应的依赖性扫描器的编程语言。目前只支持C和CXX语言扫描器。必须为IMPLICIT_DEPENDS列表中的每个文件指定语言。从扫描中发现的依赖关系在构建时添加到自定义命令的依赖关系。请注意,IMPLICIT_DEPENDS选项目前仅支持Makefile生成器,并且将被其他生成器忽略。
WORKING_DIRECTORY:可选命令,使用给定的当前工作目录执行命令。如果它是相对路径,它将相对于对应于当前源目录的构建树目录。
COMMENT:可选命令,在构建时执行命令之前显示给定消息。
DEPFILE:可选命令,为Ninja生成器指定一个.d depfile。 .d文件保存通常由自定义命令本身发出的依赖关系。对其他生成器使用DEPFILE是一个错误。
使用实例:
add_executable(MakeTable MakeTable.cxx)
add_custom_command (
OUTPUT ${
CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${
CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
COMMENT "This is a test"
)
(2)自定义构建事件
add_custom_command(TARGET <target>
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
参数介绍:
TARGET:定义了与构建指定相关联的新命令。当已经存在是,相应的command将不再执行。
PRE_BUILD:在目标中执行任何其他规则之前运行。这仅在Visual Studio 7或更高版本上受支持。对于所有其他生成器PRE_BUILD将被视为PRE_LINK。
PRE_LINK:在编译源之后运行,但在链接二进制文件或运行静态库的库管理器或存档器工具之前运行。
POST_BUILD:在目标中的所有其他规则都已执行后运行。
使用实例:
add_custom_command(TARGET ${
APP_NAME}
PRE_BUILD
COMMAND ${
CMAKE_COMMAND} -E copy_directory ${
CMAKE_CURRENT_SOURCE_DIR}/Resources
${
CMAKE_CURRENT_BINARY_DIR})
add_custom_target:该命令可以给指定名称的目标执行指定的命令,该目标没有输出文件,并始终被构建。命令的格式为
add_custom_target(Name [ALL] [command1 [args1...]]
[COMMAND command2 [args2...] ...]
[DEPENDS depend depend depend ... ]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM] [USES_TERMINAL]
[SOURCES src1 [src2...]])
参数介绍(上面介绍过含义相同的参数,这里就不再赘述了):
Name:指定目标的名称。
ALL:表明此目标应添加到默认构建目标,以便每次都将运行(该命令名称不能为ALL)
SOURCES:指定要包括在自定义目标中的其他源文件。指定的源文件将被添加到IDE项目文件中,以方便编辑,即使它们没有构建规则。
使用示例:
add_custom_target(APP ALL
DEPENDS ${
APP_NAME} # 依赖add_custom_command输出的jar包
COMMENT "building cassdk_jni.jar"
)
add_definitions:为源文件的编译添加由-D引入的宏定义。命令格式为
add_definitions(-DFOO -DBAR ...)
使用示例:
add_definitions(-DWIN32)
add_dependencies:使顶级目标依赖于其他顶级目标,以确保它们在该目标之前构建。这里的顶级目标是由add_executable,add_library或add_custom_target命令之一创建的目标。
使用示例:
add_custom_target(mylib DEPENDS ${
MYLIB})
add_executable(${
APP_NAME} ${
SRC_LIST})
add_dependencies(${
APP_NAME} mylib)
add_executable:使用指定的源文件给项目添加一个可执行文件。命令格式为
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])
参数介绍:
name:该命令调用列出的源文件来构建的可执行目标。 对应于逻辑目标名称,在项目中必须是全局唯一的。构建的可执行文件的实际文件名是基于本机平台的约定。
WIN32:如果给出WIN32,则在创建的目标上设置属性WIN32_EXECUTABLE。
MACOSX_BUNDLE:如果给定MACOSX_BUNDLE,将在创建的目标上设置相应的属性。
EXCLUDE_FROM_ALL:如果给定EXCLUDE_FROM_ALL,将在创建的目标上设置相应的属性。
source:源码列表。
使用示例:
add_executable(HelloCMake hello_cmake.c)
add_library:使用指定的源文件给项目添加一个库。命令格式为
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])
参数介绍:
name:该命令调用列出的源文件来构建的库目标。对应于逻辑目标名称,在项目中必须是全局唯一的。
STATIC:静态库,在链接其他目标时使用。
SHARED:动态链接库,运行时加载。
MODULE:不会被链接到其它目标中,但是可能会在运行时使用dlopen-系列的函数动态链接。
使用示例:
add_library(HelloCMake hello_cmake.c)
add_subdirectory:向构建中添加子目录。命令格式为
add_subdirectory(source_dir [binary_dir]
[EXCLUDE_FROM_ALL])
使用示例:
add_subdirectory(${
SRC_ROOT})
aux_source_directory:查找目录中的所有源文件。命令格式为
aux_source_directory(<dir> <variable>)
查找指定目录dir中所有源文件的名称,并将列表存储在提供的variable中。
使用示例:
aux_source_directory(. DIR_SRCS)
add_executable(${
APP_NAME} ${
DIR_SRCS})
configure_file:将文件复制到其他位置并修改其内容。命令格式为
configure_file(<input> <output>
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
使用示例:
configure_file (
"${PROJECT_SOURCE_DIR}/Config.h.in"
"${PROJECT_BINARY_DIR}/Config.h"
)
file:文件操作相关的命令。命令格式为
file(WRITE <filename> <content>...)
file(APPEND <filename> <content>...)
file(READ <filename> <variable>
[OFFSET <offset>] [LIMIT <max-in>] [HEX])
file(STRINGS <filename> <variable> [<options>...])
file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> <filename> <variable>)
file(GLOB <variable>
[LIST_DIRECTORIES true|false] [RELATIVE <path>]
[<globbing-expressions>...])
file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
[LIST_DIRECTORIES true|false] [RELATIVE <path>]
[<globbing-expressions>...])
file(RENAME <oldname> <newname>)
file(REMOVE [<files>...])
file(REMOVE_RECURSE [<files>...])
file(MAKE_DIRECTORY [<directories>...])
file(RELATIVE_PATH <variable> <directory> <file>)
file(TO_CMAKE_PATH "" <variable>)
file(TO_NATIVE_PATH "" <variable>)
file(DOWNLOAD <url> <file> [<options>...])
file(UPLOAD <file> <url> [<options>...])
file(TIMESTAMP <filename> <variable> [<format>] [UTC])
file(GENERATE OUTPUT output-file
<INPUT input-file|CONTENT content>
[CONDITION expression])
file(<COPY|INSTALL> <files>... DESTINATION <dir>
[FILE_PERMISSIONS <permissions>...]
[DIRECTORY_PERMISSIONS <permissions>...]
[NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
[FILES_MATCHING]
[[PATTERN <pattern> | REGEX <regex>]
[EXCLUDE] [PERMISSIONS <permissions>...]] [...])
file(LOCK <path> [DIRECTORY] [RELEASE]
[GUARD <FUNCTION|FILE|PROCESS>]
[RESULT_VARIABLE <variable>]
[TIMEOUT <seconds>])
以上都是文件相关的操作,这里就不详细解释。
使用示例为:
# 查找src目录下所有以hello开头的文件并保存到SRC_FILES变量里
file(GLOB SRC_FILES "src/hello*")
# 递归查找
file(GLOB_RECURSE SRC_FILES "src/hello*")
find_file:查找一个文件的完整路径。命令格式为
find_file (<VAR> name1 [path1 path2 ...])
使用示例:
find_file(HELLO_H hello.h)
find_library:查找一个库文件。命令格式为
find_library (<VAR> name1 [path1 path2 ...])
使用示例:
find_library(LUA lua5.1 /usr/lib /lib)
find_package:查找并加载外部项目的设置。命令格式为
find_package(<package> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
使用示例为:
find_package(Protobuf)
find_path:查找包含某个文件的路径。命令格式为
find_path (<VAR> name1 [path1 path2 ...])
使用示例:
find_path(DIR_SRCS hello.h .)
include_directories:将给定的目录添加到编译器用于搜索包含文件的目录。相对路径则相对于当前源目录。命令格式为
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
使用示例:
include_directories(
${
CMAKE_CURRENT_SOURCE_DIR}
${
CMAKE_CURRENT_SOURCE_DIR}/cocos
${
CMAKE_CURRENT_SOURCE_DIR}/cocos/platform
${
CMAKE_CURRENT_SOURCE_DIR}/extensions
${
CMAKE_CURRENT_SOURCE_DIR}/external
)
include:
包含其他目录的CMakeLists.txt文件。命令格式为
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>]
[NO_POLICY_SCOPE])
使用示例:
include(platform/CMakeLists.txt)
link_directories:指定链接器查找库的路径。命令格式为
link_directories(directory1 directory2 ...)
使用示例:
link_directories(${
PROJECT_SOURCE_DIR}/lib)
list:列表相关的操作。命令格式为
list(LENGTH <list> <output variable>)
list(GET <list> <element index> [<element index> ...]
<output variable>)
list(APPEND <list> [<element> ...])
list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
list(FIND <list> <value> <output variable>)
list(INSERT <list> <element_index> <element> [<element> ...])
list(REMOVE_ITEM <list> <value> [<value> ...])
list(REMOVE_AT <list> <index> [<index> ...])
list(REMOVE_DUPLICATES <list>)
list(REVERSE <list>)
list(SORT <list>)
使用示例:
list(APPEND SRC_LIST
${
PROTO_SRC}
)
message:向用户显示消息。命令格式为
message([<mode>] "message to display" ...)
参数说明:
mode:可选的值为none,STATUS,WARNING,AUTHOR_WARNING,SEND_ERROR,FATAL_ERROR,DEPRECATION。
使用示例:
message(STATUS "This is BINARY dir " ${
HELLO_BINARY_DIR})
option:提供用户可以选择的选项。命令格式为
option(<option_variable> "help string describing option"
[initial value])
使用示例:
option (USE_MYMATH "Use tutorial provided math implementation" ON)
project:为整个工程设置一个工程名。命令格式为
project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[LANGUAGES <language-name>...])
使用示例:
project (HelloCMake)
set:将一个CMAKE变量设置为给定值。命令格式为
## set(<variable> <value>... [PARENT_SCOPE])
使用示例:
set(COCOS2D_ROOT ${
CMAKE_SOURCE_DIR}/cocos2d)
set_target_properties:设置目标的一些属性来改变它们构建的方式。命令格式为
set_target_properties(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
使用示例为:
set_target_properties(cocos2d
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
VERSION "${COCOS2D_X_VERSION}"
)
string:字符串相关操作。命令格式为
string(FIND <string> <substring> <output variable> [REVERSE])
string(REPLACE <match_string>
<replace_string> <output variable>
<input> [<input>...])
string(REGEX MATCH <regular_expression>
<output variable> <input> [<input>...])
string(REGEX MATCHALL <regular_expression>
<output variable> <input> [<input>...])
string(REGEX REPLACE <regular_expression>
<replace_expression> <output variable>
<input> [<input>...])
string(APPEND <string variable> [<input>...])
string(CONCAT <output variable> [<input>...])
string(TOLOWER <string1> <output variable>)
string(TOUPPER <string1> <output variable>)
string(LENGTH <string> <output variable>)
string(SUBSTRING <string> <begin> <length> <output variable>)
string(STRIP <string> <output variable>)
string(GENEX_STRIP <input string> <output variable>)
string(COMPARE LESS <string1> <string2> <output variable>)
string(COMPARE GREATER <string1> <string2> <output variable>)
string(COMPARE EQUAL <string1> <string2> <output variable>)
string(COMPARE NOTEQUAL <string1> <string2> <output variable>)
string(COMPARE LESS_EQUAL <string1> <string2> <output variable>)
string(COMPARE GREATER_EQUAL <string1> <string2> <output variable>)
string(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512>
<output variable> <input>)
string(ASCII <number> [<number> ...] <output variable>)
string(CONFIGURE <string1> <output variable>
[@ONLY] [ESCAPE_QUOTES])
string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]
[RANDOM_SEED <seed>] <output variable>)
string(TIMESTAMP <output variable> [<format string>] [UTC])
string(MAKE_C_IDENTIFIER <input string> <output variable>)
string(UUID <output variable> NAMESPACE <namespace> NAME <name>
TYPE <MD5|SHA1> [UPPER])
使用示例:
string(REPLACE "${PROJECT_SOURCE_DIR}/hello.c" "" DIR_SRCS "${DIR_ROOT}")
target_link_libraries:将给定的库链接到一个目标上。命令格式为
target_link_libraries(<target> ... <item>... ...)
使用示例:
target_link_libraries(luacocos2d cocos2d)
3.1.2 常用的变量
使用 进 行 变 量 的 引 用 。 例 如 : m e s s a g e ( {}进行变量的引用。例如:message( 进行变量的引用。例如:message({Hello_VERSION}),Hello为工程名。CMake提供了很多有用的变量。
以下仅列举常用的变量:
3.2 CMakeLists.txt编写
有了上面的基础,再编写CMakeLists.txt自然会事半功倍。下面,以几个小实例来说下通过CMakeLists.txt的来构建项目。
这里cJSON库为例来说明下CMakeLists.txt的写法。当然,这里的代码并严谨,仅用来演示CMakeList的用法。
3.2.1 将cJSON构建为静态库
(1)在本地建立cJSONdemo1的目录工程,并将cJSON库源代码拷贝到目录中,并在该目录新建CMakeLists.txt文件。目录结构如下:
cJSONdemo1
├── cJSON_Utils.h
├── cJSON_Utils.c
├── cJSON.h
├── cJSON.c
└── CMakeLists.txt
CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 2.8.5)
project(cJSON-lib)
set(CJSON_SRC cJSON.c cJSON_Utils.c)
add_library(cjson STATIC ${
CJSON_SRC})
(2)自动搜索目录源码
在上面cJSONdemo1的基础上做一些改进。前面提过set( …),可以预见在cJSON库源码越来越多的情况下,会变成这样:
set(CJSON_SRC cJSON.c cJSON1.c cJSON2.c cJSON3.c cJSON4.c cJSON5.c)
这样,源文件越多,需要添加次数就越多。而且,每增加一个源文件就需要修改CMakeLists.txt文件,“耦合性”太大。这里,可以使用aux_source_directory来自动查找源文件。CMakeLists.txt文件最终如下:
cmake_minimum_required(VERSION 2.8.5)
project(cJSON-lib)
aux_source_directory(. CJSON_SRC)
add_library(cjson STATIC ${
CJSON_SRC})
(3)递归搜索目录源码
若将cJSONdemo改成包含子目录,子目录中又包含源码的形式,有多级目录。如下
cJSONdemo1
│── cJSON_Utils.h
│── cJSON_Utils.c
│── cJSON.h
│── cJSON.c
│── CMakeLists.txt
└── foo
├── cJSON1.h
├── cJSON1.c
├── cJSON2.h
├── cJSON2.c
└── goo
├── cJSON3.h
├── cJSON3.c
├── cJSON4.h
└── cJSON4.c
可以使用file命令,来自动递归查找相应的源文件。CMakeLists.txt文件最终如下:
cmake_minimum_required(VERSION 2.8.5)
project(cJSON-lib)
file(GLOB_RECURSE CJSON_SRC ${
CMAKE_CURRENT_SOURCE_DIR}/*.c)
add_library(cjson STATIC ${CJSON_SRC})
(4)指定构建库的名字,路径和前缀。CMakeLists.txt文件最终如下:
cmake_minimum_required(VERSION 2.8.5)
project(cJSON-lib)
file(GLOB_RECURSE CJSON_SRC ${
CMAKE_CURRENT_SOURCE_DIR}/*.c)
add_library(cjson STATIC ${CJSON_SRC})
set_target_properties(cjson PROPERTIES OUTPUT_NAME "json")
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/static)
set(CMAKE_STATIC_LIBRARY_PREFIX "")
3.2.1 将cJSON外部依赖库链接进可执行文件中
通过上面过程了解了将cJSON库构建文件静态库的过程。下面,再添加测试代码来调用cJSON库,并最终构建为可执行文件。目录如下:
cJSONdemo2
│── test.c
│── CMakeLists.txt
└── lib
├── cJScJSON_UtilsON1.h
├── cJSON_Utils.c
├── cJSON.h
├── cJSON.c
└── CMakeLists.txt
test.c:
#include
#include
#include "lib/cJSON.h"
void parser(char* text) {
char *out;
cJSON *json;
json = cJSON_Parse(text);
if (!json) {
printf("Error before: [%s]\n", cJSON_GetErrorPtr());
}else {
out = cJSON_Print(json);
cJSON_Delete(json);
printf("%s\n", out);
free(out);
}
}
int main(int argc, char * argv[]) {
char text[]="[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]";
parser(text);
return 0;
}
cJSONdemo2/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.5)
project(cjson-example)
aux_source_directory(. CJSON_EXAMPLE_SRC)
add_subdirectory(./lib)
add_executable(cjson-example ${
CJSON_EXAMPLE_SRC})
target_link_libraries(cjson-example cjson)
cJSONdemo2/lib/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.5)
aux_source_directory(. CJSON_SRC)
add_library(cjson STATIC ${
CJSON_SRC})
3.2.2 将cJSON库改为可选
在上面cJSONdemo2的基础上,新建cJSONConfig.h.in并相应修改test.c。目录如下:
cJSONdemo3
│── test.c
│── cJSONConfig.h.in
│── CMakeLists.txt
└── lib
├── cJScJSON_UtilsON1.h
├── cJSON_Utils.c
├── cJSON.h
├── cJSON.c
└── CMakeLists.txt
cJSONConfig.h.in:
#cmakedefine USE_CJSON
test.c:
#include
#include
#ifdef USE_MYMATH
#include "lib/cJSON.h"
void parser(char* text) {
char *out;
cJSON *json;
json = cJSON_Parse(text);
if (!json) {
printf("Error before: [%s]\n", cJSON_GetErrorPtr());
}else {
out = cJSON_Print(json);
cJSON_Delete(json);
printf("%s\n", out);
free(out);
}
}
#endif
int main(int argc, char * argv[]) {
char text[]="[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]";
#ifdef USE_MYMATH
parser(text);
#else
printf("use other json library\n");
#endif
return 0;
}
以上只是通过一些简单的示例来说明了CMake基础及相关应用。更多高级功能需要日常的实践及查询CMake官方文档。