CMake配置

PROJECT(工程名字)


    这条指令会自动创建两个变量:

<project name>_BINARY_DIR(二进制文件保存路径)    <project name>_SOURCE_DIR(源代码路径)

Cmake 系统也帮助我们预定义了 PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR其值与上述对应相等
 
SET(变量名 变量值)

    SET(VAR [VALUE] [CACHE TYPEDOCSTRING [FORCE]])
    SET(SRC_LIST main.c t1.c t2.c):即SPC_LIST代表main.c t1.c t2.c
    SET(SRC_LIST main.c):同上
 
MESSAGE(消息类型 消息内容)
    MESSAGE([SEND_ERROR | STATUS| FATAL_ERROR] "message to display")


ADD_EXECUTABLE(可执行文件名 生成该可执行文件的源文件)
    ADD_EXECUTABLE(hello${SRC_LIST}):通过${SRC_LIST}生成hello的可执行文件
 
ADD_SUBDIRECTORY(子目录名字)
    ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL]):告诉cmake通过子目录名字去找寻所需资源src/lib等等

 
SET(EXECUTABLE_OUTPUT_PATH${PROJECT_BINARY_DIR}/bin)更改生成的可执行文件路径,让文件在bin里面生成
SET(LIBRARY_OUTPUT_PATH${PROJECT_BINARY_DIR}/lib)更改生成的库文件路径,让文件在lib里面生成

ADD_LIBRARY(hello SHARED${LIBHELLO_SRC})生成动态静态库

    ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL]

    source1source2 ... sourceN)通过source生成不同的类型的libname库文件


SET_TARGET_PROPERTIES

为一个目标设置属性。该命令的语法是列出所有你想要变更的文件,然后提供你想要设置的值。你能够使用任何你想要的属性/值对,并且在随后的代码中调用GET_TARGET_PROPERTY命令取出属性的值。即OUTPUT_NAME的值就是hello

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

同时生成动态静态库
    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})动态库
    ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})静态库

    SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
    SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
    SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)


控制版本
        SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2  SOVERSION 1)
        VERSION指代动态库版本,SOVERSION指代API版本。


        INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
        INSTALL(FILES hello.h DESTINATION include/hello)

注意,静态库要使用ARCHIVE关键字


cmake -DCMAKE_INSTALL_PREFIX=/usr ..[路径]
 
INCLUDE_DIRECTORIES(追加标志 头文件路径)
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM]dir1 dir2 ...)
 
LINK_DIRECTORIES(库文件路径)
LINK_DIRECTORIES(directory1 directory2 ...)

    TARGET_LINK_LIBRARIES 设置要连接库文件的名称
    TARGET_LINK_LIBRARIES(targetlibrary1 <debug | optimized> library2 ..)
    TARGET_LINK_LIBRARIES(main hello),连接libhello.so库
    TARGET_LINK_LIBRARIES(main lib hello.a)
    TARGET_LINK_LIBRARIES(main lib hello.so) 


使用$ENV{NAME}指令就可以调用系统的环境变量

系统信息

1,CMAKE_MAJOR_VERSION,CMAKE主版本号,比如2.4.6中的2
2,CMAKE_MINOR_VERSION,CMAKE次版本号,比如2.4.6中的4
3,CMAKE_PATCH_VERSION,CMAKE补丁等级,比如2.4.6 中的6
4,CMAKE_SYSTEM,系统名称,比如Linux-2.6.22
5,CMAKE_SYSTEM_NAME,不包含版本的系统名,比如Linux
6,CMAKE_SYSTEM_VERSION,系统版本,比如2.6.22
7,CMAKE_SYSTEM_PROCESSOR,处理器名称,比如i686.
8,UNIX,在所有的类UNIX平台为TRUE,包括OS X和cygwin
9,WIN32,在所有的win32平台为TRUE,包括cygwin

主要的开关选项:
1,CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS,用来控制IF ELSE语句的书写方式,在
下一节语法部分会讲到。
2,BUILD_SHARED_LIBS
这个开关用来控制默认的库编译方式,如果不进行设置,使用ADD_LIBRARY并没有指定库类型的情况下,默认编译生成的库都是静态库。
如果SET(BUILD_SHARED_LIBS ON)后,默认生成的为动态库。
3,CMAKE_C_FLAGS
设置C编译选项,也可以通过指令ADD_DEFINITIONS()添加。
4,CMAKE_CXX_FLAGS
设置C++编译选项,也可以通过指令ADD_DEFINITIONS()添加。
ADD_DEFINITIONS(-DENABLE_DEBUG-DABC),定义宏


ADD_DEPENDENCIES
定义target依赖的其他target,确保在编译本target之前,其他的target已经被构建。
ADD_DEPENDENCIES(target-name depend-target1depend-target2 ...)
 
ADD_TEST与ENABLE_TESTING指令
ADD_TEST(testname Exenamearg1 arg2 ...)
如果没有在同一个CMakeLists.txt中打开ENABLE_TESTING()指令,任何ADD_TEST都是无效的。
ADD_TEST(mytest${PROJECT_BINARY_DIR}/bin/main)
ENABLE_TESTING()


生成Makefile后,就可以运行make test来执行测试了。


 AUX_SOURCE_DIRECTORY
 AUX_SOURCE_DIRECTORY(dir VARIABLE)
 作用是发现一个目录下所有的源代码文件并将列表存储在一个变量中
 AUX_SOURCE_DIRECTORY(. SRC_LIST)
 ADD_EXECUTABLE(main ${SRC_LIST})

CMAKE_MINIMUM_REQUIRED(VERSION2.5 FATAL_ERROR)最低版本CMAKE要求
EXEC_PROGRAM(Executable[directory in which to run]
[ARGS <arguments to executable>]
[OUTPUT_VARIABLE <var>]
[RETURN_VALUE <var>])


用于在指定的目录运行某个程序,通过ARGS添加参数,如果要获取输出和返回值,可通过OUTPUT_VARIABLE和RETURN_VALUE分别定义两个变量.
    举个简单的例子,我们要在src目录执行ls命令,并把结果和返回值存下来。
可以直接在src/CMakeLists.txt中添加:


EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE)
IF(not LS_RVALUE)
MESSAGE(STATUS "ls result: "${LS_OUTPUT})
ENDIF(not LS_RVALUE)
 
FILE指令
文件操作指令,基本语法为:
FILE(WRITE filename "message towrite"... )

FILE(APPEND filename "message towrite"... )

FILE(READ filename variable)

FILE(GLOB variable [RELATIVE path][globbing expressions]...)
FILE(GLOB_RECURSE variable [RELATIVE path] [globbingexpressions]...)
FILE(REMOVE [directory]...)
FILE(REMOVE_RECURSE [directory]...)
FILE(MAKE_DIRECTORY [directory]...)
FILE(RELATIVE_PATH variable directory file)
FILE(TO_CMAKE_PATH path result)
FILE(TO_NATIVE_PATH path result)
 

INCLUDE指令,用来载入CMakeLists.txt文件,也用于载入预定义的cmake模块.
INCLUDE(file1 [OPTIONAL])
INCLUDE(module [OPTIONAL])

OPTIONAL参数的作用是文件不存在也不会产生错误。
你可以指定载入一个文件,如果定义的是一个模块,那么将在CMAKE_MODULE_PATH中搜索这个模块并载入。
 

FIND_系列指令主要包含一下指令:
FIND_FILE(<VAR> name1 path1 path2 ...)
VAR变量代表找到的文件全路径,包含文件名
FIND_LIBRARY(<VAR> name1 path1 path2 ...)
VAR变量表示找到的库全路径,包含库文件名
FIND_PATH(<VAR> name1 path1 path2 ...)
VAR变量代表包含这个文件的路径。
FIND_PROGRAM(<VAR> name1 path1 path2 ...)
VAR变量代表包含这个程序的全路径。


FIND_PACKAGE(<name> [major.minor] [QUIET][NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])
用来调用预定义在CMAKE_MODULE_PATH下的Find<name>.cmake模块,你也可以自己

定义Find<name>模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录


中供工程使用
FIND_LIBRARY示例:
FIND_LIBRARY(libX X11 /usr/lib)
IF(NOT libX)
MESSAGE(FATAL_ERROR “libX not found”)
ENDIF(NOT libX)

原本的条件语句
IF(WIN32)
MESSAGE(STATUS “This is windows.”)
#作一些Windows相关的操作
ELSE(WIN32)
MESSAGE(STATUS “This is not windows”)
#作一些非Windows相关的操作
ENDIF(WIN32)
通过设置SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
上述代码可写为
IF(WIN32)
ELSE()
ENDIF()
还可以
IF(WIN32)
#do something related to WIN32
ELSEIF(UNIX)
#do something related to UNIX
ELSEIF(APPLE)
#do something related to APPLE
ENDIF(WIN32)

WHILE指令的语法是:
WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)

FOREACH指令的使用方法有三种形式:

列表
FOREACH(loop_var arg1 arg2...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)

像我们前面使用的AUX_SOURCE_DIRECTORY的例子
AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F ${SRC_LIST})
MESSAGE(${F})
ENDFOREACH(F)

范围

FOREACH(loop_var RANGE total)

ENDFOREACH(loop_var)


从0到total以1为步进举例如下:


FOREACH(VAR RANGE 10)
MESSAGE(${VAR})
ENDFOREACH(VAR)

最终得到的输出是:0-10

范围和步进
FOREACH(loop_var RANGE start stop [step])
ENDFOREACH(loop_var)

从start开始到stop结束,以step为步进,举例如下

FOREACH(A RANGE 5 15 3)
MESSAGE(${A})
ENDFOREACH(A)

最终得到的结果是:

5
8
11
14


这个指令需要注意的是,直到遇到ENDFOREACH指令,整个语句块才会得到真正的执行。


FIND_PACKAGE(CURL)
IF(CURL_FOUND)
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(curltest${CURL_LIBRARY})
ELSE(CURL_FOUND)
MESSAGE(FATAL_ERROR ”CURL library not found”)
ENDIF(CURL_FOUND)

可以自己定义一些FIND_PACKAGE包,比如
定义cmake/FindHELLO.cmake模块

FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello)
FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/lib /usr/local/lib)

IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
SET(HELLO_FOUND TRUE)
ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
IF (HELLO_FOUND)
IF (NOT HELLO_FIND_QUIETLY)
MESSAGE(STATUS "FoundHello: ${HELLO_LIBRARY}")
ENDIF (NOT HELLO_FIND_QUIETLY)
ELSE (HELLO_FOUND)
IF (HELLO_FIND_REQUIRED)
MESSAGE(FATAL_ERROR"Could not find hello library")
ENDIF (HELLO_FIND_REQUIRED)
ENDIF (HELLO_FOUND)


那么可以使用
FIND_PACKAGE(HELLO)
IF(HELLO_FOUND)
ADD_EXECUTABLE(hello main.c)
INCLUDE_DIRECTORIES(${HELLO_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(hello${HELLO_LIBRARY})
ENDIF(HELLO_FOUND)


来操作,不过操作之前需要设置cmake搜索路径


SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)  

猜你喜欢

转载自blog.csdn.net/lnplnp_/article/details/79634541
今日推荐