cmake使用

【语法】

 ­

注释 ­ # : ­ ­ ­
 ­ ­ ­ ­#我是注释

 ­

命令语法 COMMAND:
 ­ ­ ­ COMMAND(参数1 参数2 ...)

 ­

字符串列

 ­ ­ ­ A;B;C ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ //分号分割或空格分隔的值

 ­

变量
 ­ ­ ­ set(Foo a b c) ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ // 设置变量 Foo
 ­ ­ ­ command(${Foo}) ­ ­ ­ ­ //等价于 command(a b c)
 ­ ­ ­ command("${Foo}") ­ // 等价于 command("a b c")
 ­ ­ ­ command("/${Foo}") // 转义,和 a b c无关联


流控制结构
 ­ ­ ­ IF()...ELSE() ­ /ELSEIF()...ENDIF()
 ­ ­ ­ WHILE()...ENDWHILE()
 ­ ­ ­ FOREACH()...ENDFOREACH()

 ­

【常用命令】

(按A~Z排列)

 ­

ADD_EXECUTABLE
add_exectuable ­ : 工程生成一个可执行文件。
add_executable(hello ${SRC_LIST}) ­ //生成一个名为hello.exe的可执行文件

 ­

ADD_LIBRARY
add_library : ­ 生成一个库文件。
add_library(libhello ${LIB_SRC}) ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ //生成libhello.lib文件
add_library(libhello SHARED ${LIB_SRC}) ­ //生成动态库文件

 ­

ADD_CUSTOM_COMMAND(
TARGET name
PRE_BUILD|PRE_LINK|POST_BUILD
COMMAND cmd1 [COMMAND cmd2 …] ):
为目标工程name添加一个或多个新的自定义的编译规则cmd1,cmd2等,执行时机可以选择编译前,链接前或者编译后。它的作用相当于Visual Studio工程的“Custom Build Step”属性。
add_custom_command 为生成的构建系统添加一条自定义的构建规则。
  add_custom_command命令有两种主要的功能;第一种是为了生成输出文件,添加一条自定义命令。

  add_custom_command(OUTPUT output1 [output2 ...]
                     COMMAND command1 [ARGS] [args1...]
                     [COMMAND command2 [ARGS] [args2...] ...]
                     [MAIN_DEPENDENCY depend]
                     [DEPENDS [depends...]]
                     [IMPLICIT_DEPENDS <lang1> depend1 ...]
                     [WORKING_DIRECTORY dir]
                     [COMMENT comment] [VERBATIM] [APPEND])

  这种命令格式定义了一条生成指定的文件(文件组)的生成命令。在相同路径下创建的目标(CMakeLists.txt文件)——任何自定义命令的输出都作为它的源文件——被设置了一条规则:在构建的时候,使用指定的命令来生成这些文件。如果一个输出文件名是相对路径,它将被解释成相对于构建树路径的相对路径,并且与当前源码路径是对应的。注意,MAIN_DEPENDENCY完全是可选的,它用来向visual studio建议在何处停止自定义命令。对于各种类型的makefile而言,这条命令创建了一个格式如下的新目标:

  OUTPUT: MAIN_DEPENDENCY DEPENDS
    COMMAND

  如果指定了多于一条的命令,它们会按顺序执行。ARGS参数是可选的,它的存在是为了保持向后兼容,以后会被忽略掉。

  第二种格式为一个目标——比如一个库文件或者可执行文件——添加一条自定义命令。这种格式可以用于目标构建前或构建后的一些操作。这条命令会成为目标的一部分,并且只有目标被构建时才会执行。如果目标已经构建了,该目标将不会执行。

  add_custom_command(TARGET target
                     PRE_BUILD | PRE_LINK | POST_BUILD
                     COMMAND command1 [ARGS] [args1...]
                     [COMMAND command2 [ARGS] [args2...] ...]
                     [WORKING_DIRECTORY dir]
                     [COMMENT comment] [VERBATIM])

  这条命令定义了一个与指定目标的构建过程相关的新命令。新命令在何时执行,由下述的选项决定:

  PRE_BUILD  - 在所有其它的依赖之前执行;
  PRE_LINK   - 在所有其它的依赖之后执行;
  POST_BUILD - 在目标被构建之后执行;

  注意,只有Visual Studio 7或更高的版本才支持PRE_BUILD。对于其他的生成器,PRE_BUILD会被当做PRE_LINK来对待。

  如果指定了WORKING_DIRECTORY选项,这条命令会在给定的路径下执行。如果设置了COMMENT选项,后跟的参数会在构建时、以构建信息的形式、在命令执行之前显示出来。如果指定了APPEND选项,COMMAND以及DEPENDS选项的值会附加到第一个输出文件的自定义命令上。在此之前,必须有一次以相同的输出文件作为参数的对该命令的调用。在当前版本下,如果指定了APPEND选项,COMMENT, WORKING_DIRECTORY和MAIN_DEPENDENCY选项会被忽略掉,不过未来有可能会用到。

  如果指定了VERBATIM选项,所有该命令的参数将会合适地被转义,以便构建工具能够以原汁原味的参数去调用那些构建命令。注意,在add_custom_command能看到这些参数之前,CMake语言处理器会对这些参数做一层转义处理。推荐使用VERBATIM参数,因为它能够保证正确的行为。当VERBATIM未指定时,CMake的行为依赖于平台,因为CMake没有针对某一种工具的特殊字符采取保护措施。

  如果自定义命令的输出并不是实际的磁盘文件,应该使用SET_SOURCE_FILES_PROPERTIES命令将该输出的属性标记为SYMBOLIC。

  IMPLICIT_DEPENDS选项请求扫描一个输入文件的隐含依赖关系。给定的语言参数(文中的lang1—译注)指定了应该使用哪种编程语言的依赖扫描器。目前为止,仅支持C和CXX语言扫描器。扫描中发现的依赖文件将会在编译时添加到自定义命令中。注意,IMPLICIT_DEPENDS选项目前仅仅直至Makefile生成器,其它的生成器会忽略之。

  如果COMMAND选项指定了一个可执行目标(由ADD_EXECUTABLE命令创建的目标),在构建时,它会自动被可执行文件的位置所替换。而且,一个目标级的依赖性将会被添加进去,这样这个可执行目标将会在所有依赖于该自定义命令的结果的目标之前被构建。不过,任何时候重编译这个可执行文件,这种特性并不会引入一个会引起自定义命令重新运行的文件级依赖。

  DEPENDS选项指定了该命令依赖的文件。如果依赖的对象是同一目录(CMakeLists.txt文件)下另外一个自定义命令的输出,CMake会自动将其它自定义命令带到这个命令中来。如果DEPENDS指定了任何类型的目标(由ADD_*命令创建),一个目标级的依赖性将会被创建,以保证该目标在任何其它目标使用这个自定义命令的输出之前,该目标已经被创建了。而且,如果该目标是可执行文件或库文件,一个文件级依赖将会被创建,用来引发自定义命令在目标被重编译时的重新运行。

在Unix Makefile中,这条命令相当于增加了一个依赖关系和一条显式生成命令。


ADD_CUSTOM_TARGET( name COMMAND cmd1 [COMMAND cmd2 …] ):
自定义目标,生成一个自定义文件类型

添加一个名为name的编译目标,并指定一个或多个自定义的命令cmd1,cmd2等。注意ADD_CUSTOM_COMMAND与这个命令的区别:前者是针对一个已有的子工程进行自定义编译规则的设置;后者则是建立一个新的自定义的目标工程,例如一个专用于将已生成文件拷贝到指定文件夹的INSTALL工程;以及与之作用截然相反的UNINSTALL工程。

 ­add_subdirectory :增加子文件夹,2个参数的话就是源→目标 文件夹生成对应 ­
add_subdirectory(src) ­:建立src子文件夹
add_subdirectory(src bin) ­ ­:在cmake目标文件夹中与源文件夹对应 src→bin文件夹

 ­

ADD_DEPENDENCIES( target1 t2 t3 )
目标target1依赖于t2 t3

 ­

ADD_DEFINITIONS( "-Wall -ansi")
本意是供设置 -D... /D... 等编译预处理需要的宏定义参数,对比 REMOVE_DEFINITIONS()

 ­

AUX_SOURCE_DIRECTORY ( “sourcedir” variable)
收集目录中的文件名并赋值给变量

 ­

EXEC_PROGRAM ( bin [work_dir] ARGS <..> [OUTPUT_VARIABLE var] [RETURN_VALUE var] )
 ­执行外部程序

 ­

FILE ( WRITE|READ|APPEND|GLOB| GLOB_RECURSE|REMOVE|MAKE_DIRECTORY ...)
文件操作

 ­

FIND_FILE
FIND_PATH
FIND_LIBRARY
FIND_PACKAGE ­ ­ ­ 上述4个注意 CMAKE_LIBRARY_PATH

 ­

FIND_PROGRAM

 ­

INCLUDE_DIRECTORIES ( "dir1" "dir2" ... )
include_directories ­ : 包含指定目录下的指定文件夹
include_directories(${PROJECT_SOURCE_DIR}/libhello) ­ //包含当前目录下的libhello文件夹

 ­

INSTALL ( FILES “f1” “f2”DESTINATION . )
DESTINATION (目标文件夹)相对于 ${CMAKE_INSTALL_PREFIX}
 ­
LINK_DIRECTORIES ("dir1" "dir2")
 ­库文件路径。注意:由于历史原因,相对路径会原样传递给链接器。尽量使用FIND_LIBRARY而避免使用这个。
 ­
LINK_LIBRARIES ( lib1 lib2 ...)
设置所有目标需要链接的库

 ­

LIST ( APPEND|INSERT|LENGTH|GET| REMOVE_ITEM|REMOVE_AT|SORT ...)
列表操作

 ­

MESSAGE (...) ­ 输出信息,方便检查调试

message(${PROJECT_SOURCE_DIR})

 ­

project

建立一个工程
project ­ ­ 不是强制性的,但最好始终都加上。这一行会引入两个变量
•HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR
同时,cmake自动定义了两个等价的变量
•PROJECT_BINARY_DIR ­ ­ 和 ­ PROJECT_SOURCE_DIR
如果是out-of-source方式构建(源代码和生成的中间产物分离),所以要时刻区分这两个变量对应的目录

 ­

SET
set (SRC_LIST hello.cpp) ­ //源文件列表 hello.cpp
set (APP_SRC main.c) ­ ­ ­ ­ ­ ­ //语义基本同上,具体不太了解
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) ­ //指定生成hello.exe到目标文件夹

 ­

SET_TARGET_PROPERTIES ( ... ):设置目标的属性 OUTPUT_NAME, VERSION, ....
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello") ­ //使libhello.lib输出文件名为hello.exe

 ­

SEPARATE_ARGUMENTS ( VAR )
转换空格分隔的字符串到列表

 ­

STRING ( TOUPPER|TOLOWER|LENGTH| SUBSTRING|REPLACE|REGEX ...)
字符串操作

 ­

TARGET_LINK_LIBRARIES ( target-name lib1 lib2 ...)
target_link_libraries ­ : ­ 将指定库文件链接到某个执行文件
target_link_libraries(hello libhello) ­ ­ //将libhello.lib文件链接到hello.exe

 ­

 ­

【常见变量】


----工程路径------


•CMAKE_SOURCE_DIR
•PROJECT_SOURCE_DIR
•<projectname>_SOURCE_DIR
这三个变量指代的内容是一致的,是工程顶层目录

 ­

•CMAKE_BINARY_DIR
•PROJECT_BINARY_DIR
•<projectname>_BINARY_DIR
这三个变量指代的内容是一致的,如果是in source编译,指得就是工程顶层目录,如果 ­ 是out-of-source编译,指的是工程编译发生的目录

 ­

•CMAKE_CURRENT_SOURCE_DIR
指的是当前处理的CMakeLists.txt所在的路径。

 ­

•CMAKE_CURRRENT_BINARY_DIR
如果是in-source编译,它跟CMAKE_CURRENT_SOURCE_DIR一致,如果是out-ofsource ­ 编译,他指的是target编

译目录。

•CMAKE_CURRENT_LIST_FILE
输出调用这个变量的CMakeLists.txt的完整路径

 ­

----CMAKE_BUILD_TYPE-----

 ­

控制 Debug 和 Release 模式的构建

•CMakeList.txt文件
SET(CMAKE_BUILD_TYPE Debug)•命令行参数
cmake DCMAKE_BUILD_TYPE=Relea

 ­

-----编译器参数-----


•CMAKE_C_FLAGS
•CMAKE_CXX_FLAGS
也可以通过指令ADD_DEFINITIONS()添加

 ­

CMAKE_INCLUDE_PATH
配合 FIND_FILE() 以及 FIND_PATH() 使用。如果头文件没有存放在常规路径/usr/include, /usr/local/include等),
则可以通过这些变量就行弥补。如果不使用 FIND_FILE 和 FIND_PATH的话,CMAKE_INCLUDE_PATH,没有任何作

用。

 ­

•CMAKE_LIBRARY_PATH

配合 FIND_LIBRARY() 使用。否则没有任何作用

 ­

•CMAKE_MODULE_PATH

cmake 为上百个软件包提供了查找器(finder):FindXXXX.cmake

当使用非cmake自带的finder时,需要指定finder的路径,这就是CMAKE_MODULE_PATH,配合 FIND_PACKAGE

()使用

 ­

CMAKE_INSTALL_PREFIX
控制make install是文件会安装到什么地方。默认定义是/usr/local 或 %PROGRAMFILES%

 ­

BUILD_SHARED_LIBS
如果不进行设置,使用ADD_LIBRARY且没有指定库类型,默认编译生成的库是静态库。

 ­

UNIX 与 WIN32
•UNIX,在所有的类UNIX平台为TRUE,包括OS X和cygwin
•WIN32,在所有的win32平台为TRUE,包括cygwin

 

注意:要使用模块时,必须先用include指定把模块引用进CMakeList.txt

例如:include(FindPkgConfig)

模块的位置:/usr/share/cmake-2.8/Modules


模块(module)
FindPkgConfig    CMake 的pkg-config模块

    <PREFIX> 自定义的前缀

    pkg_check_modules(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)
    检测所有给出的modules    

    设置'REQUIRED'参数后 如果MODULE没有找到会发生错误
   
    该命令会设置以下几个变量
        PKG_CONFIG_FOUND    如果pkg-config可以运行在系统中 为TRUE
        PKG_CONFIG_EXECUTABLE    pkg-config程序的路径
        <PREFIX>_FOUND        如果module存在 设置为1   

    下列生成的变量有两组值 一种使用<PREFIX>作为前缀 另一种使用<PREFIX>_STATIC作为前缀 (在调用pkgconfig时使用--static选项)

    <XPREFIX> = <PREFIX>        普通情况下
    <XPREFIX> = <PREFIX>_STATIC    为static链接的情况下

    <XPREFIX>_LIBRARIES        库
    <XPREFIX>_LIBRARY_DIRS        库的路径
    <XPREFIX>_LDFLAGS        所有需要的链接选项
    <XPREFIX>_LDFLAGS_OTHERS    所有其他的链接选项
    <XPREFIX>_INCLUDE_DIRS        '-I' 预处理选项
    <XPREFIX>_CFLAGS        所有需要的cflags(C编译器的选项)
    <XPREFIX>_CFLAGS_OTHERS        其他的编译选项

模块
包括(CheckIncludeFiles)
用法
CHECK_INCLUDE_FILES(标头变量)
范例
CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H)
正如刚才冗长的讨论,这可以用来检查一个头的存在。

模块
包括(CheckFunctionExists)
用法
CHECK_FUNCTION_EXISTS(函数变量)
范例
CHECK_FUNCTION_EXISTS(madvise HAVE_MADVISE)
检查是否存在给定的函数。这是通过将一个小程序,它可能不会导致未定义的引用。

模块
包括(CheckSymbolExists)
用法
CHECK_SYMBOL_EXISTS(符号标题变量)
范例
CHECK_SYMBOL_EXISTS((LC_MESSAGES“locale.h中”HAVE_LC_MESSAGES)
检查是否存在给定的符号,如果指定的标头也包括在内。

模块
包括(CheckLibraryExists)
用法
CHECK_LIBRARY_EXISTS(库函数的位置变量)
范例
CHECK_LIBRARY_EXISTS(volmgt volmgt_running“”HAVE_VOLMGT)
检查是否存在给定的库和包含给定的函数。这是通过将一个小程序,它使用功能和图书馆的链接。在一个额外的链接位置参数目录(- Ldir)如果需要的话可以考虑。

模块
包括(CheckTypeSize)
用法
套装(CMAKE_EXTRA_INCLUDE_FILES头)
CHECK_TYPE_SIZE(类型变量)
套装(CMAKE_EXTRA_INCLUDE_FILES)
范例
设定(CMAKE_EXTRA_INCLUDE_FILES sys / socket.h中)
CHECK_TYPE_SIZE(“结构ucred”STRUCT_UCRED)
套装(CMAKE_EXTRA_INCLUDE_FILES)
检查是否存在指定的类型和返回类型的大小。在变量的类型的大小将被退回,另外一个变量HAVE_STRUCT_UCRED将被设置为true,如果存在的类型。请不要认为你必须设置CMAKE_EXTRA_INCLUDE_FILES为这种类型所需的头文件,你应该调用CHECK_TYPE_SIZE后重置它。如果你是不是真的有兴趣在该类型的大小,但只有它是否存在与否,你也可以使用STRUCT_UCRED直接,如果类型不存在,这将是空的,所以也计算为假(如将HAVE_STRUCT_UCRED )。

模块
包括(CheckPrototypeExists)
用法
CHECK_PROTOTYPE_EXISTS(函数头变量)
范例
CHECK_PROTOTYPE_EXISTS(mkstemps“stdlib.h中; unistd.h”HAVE_MKSTEMPS_PROTO)
头检查是否为给定函数的声明,即不检查是否使用功能将导致未定义的引用。

模块
包括(CheckCXXSourceCompiles)
包括(CheckCSourceCompiles)
用法
CHECK_CXX_SOURCE_COMPILES(源变量)
CHECK_C_SOURCE_COMPILES(源变量)
检查是否在给定的源代码将编译和链接。您可以设置CMAKE_REQUIRED_LIBRARIES,CMAKE_REQUIRED_FLAGS和CMAKE_REQUIRED_INCLUDES因此,如果额外的库或编译器标志是必需的。

 


Project的指令的语法是:

PROJECT(projectname [CXX] [C] [JAVA])

这个执行是用来定义工程的名称的和定义工程支持的语言。这个指令也隐式的定义了两个cmake变量:<projectname>_BINARY_DIR以及<projectname>_BINARY_DIR,这里就是HELLO_BINARY_DIR和HELLO_SOURCE_DIR,两个变量指的都是当前工程的路径。

SET指令的语法:

SET(VAR[VALUE] [CACHE TYPE DOCSTRING [FORCE]])

Set指令是用来显式的定义变量的,我们之前用到的是SET(SRC_LIST main.cpp)如果有多个源文件,也可以定义成SET(SRC_LIST main.cpp t1.cpp t2.cpp)。

 

MESSAGE指令的语法是:

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)

这个指令用于向终端输出用户信息,包含三种类型:

SEND_ERROR,产生错误,生成过程被跳过。

SATUS,输出前缀为-的信息。

FATAL_ERROR,立即终止所有cmake过程。

我们在这里使用的是STATUS信息输出,显示了由PROJECT指令顶一顶两个饮食变量HELLO_BINARY_DIR和HELLO_SOURCE_DIR。

 

ADD_EXECUTABLE(hello ${SRC_LIST})

定义了这个工程会生成一个文件名为hello的可执行文件,相关的源文件是SRC_LIST中定义的源文件列表,本例中你可以直接写成ADD_EXECUTABLE(hello main.c)。

 

将本例改写成一个最简化的CMakeLists.txt:

PROJECT(HELLO)

ADD_EXECUTABLE(hello main.c)

http://blog.csdn.net/qp120291570/article/details/7283727

本节的任务:
1,建立一个静态库和动态库,提供 HelloFunc 函数供其他程序编程使用,HelloFunc
向终端输出 Hello World 字符串。
2,安装头文件与共享库。
一,准备工作:
在/backup/cmake 目录建立 t3 目录,用于存放本节涉及到的工程
二,建立共享库
cd /backup/cmake/t3
mkdir lib
在 t3 目录下建立 CMakeLists.txt,内容如下:
PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib)
在 lib 目录下建立两个源文件 hello.c 与 hello.h
hello.c 内容如下:
#include “hello.h”
void HelloFunc()
{
printf(“Hello World\n”);
}
hello.h 内容如下:
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
void HelloFunc();
#endif
在 lib 目录下建立 CMakeLists.txt,内容如下:
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
三,编译共享库:
仍然采用 out-of-source 编译的方式,按照习惯,我们建立一个 build 目录,在 build
目录中
cmake ..
make
这时,你就可以在 lib 目录得到一个 libhello.so,这就是我们期望的共享库。
如果你要指定 libhello.so 生成的位置,可以通过在主工程文件 CMakeLists.txt 中修
改 ADD_SUBDIRECTORY(lib)指令来指定一个编译输出位置或者
在 lib/CMakeLists.txt 中添加
SET(LIBRARY_OUTPUT_PATH <路径>)来指定一个新的位置。
这两者的区别我们上一节已经提到了,所以,这里不再赘述,下面,我们解释一下一个新的
指令 ADD_LIBRARY
ADD_LIBRARY(libname
[SHARED|STATIC|MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
你不需要写全 libhello.so,只需要填写 hello 即可,cmake 系统会自动为你生成
libhello.X
类型有三种:
SHARED,动态库
STATIC,静态库
MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手
工构建。
四,添加静态库:
同样使用上面的指令,我们在支持动态库的基础上再为工程添加一个静态库,按照一般的习
惯,静态库名字跟动态库名字应该是一致的,只不过后缀是.a 罢了。
下面我们用这个指令再来添加静态库:
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
然后再在 build 目录进行外部编译,我们会发现,静态库根本没有被构建,仍然只生成了
一个动态库。因为 hello 作为一个 target 是不能重名的,所以,静态库构建指令无效。
如果我们把上面的 hello 修改为 hello_static:
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
就可以构建一个 libhello_static.a 的静态库了。
这种结果显示不是我们想要的,我们需要的是名字相同的静态库和动态库,因为 target 名
称是唯一的,所以,我们肯定不能通过 ADD_LIBRARY 指令来实现了。这时候我们需要用到
另外一个指令:
SET_TARGET_PROPERTIES,其基本语法是:
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本。
在本例中,我们需要作的是向 lib/CMakeLists.txt 中添加一条:
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
这样,我们就可以同时得到 libhello.so/libhello.a 两个库了。
与他对应的指令是:
GET_TARGET_PROPERTY(VAR target property)
具体用法如下例,我们向 lib/CMakeListst.txt 中添加:
GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME)
MESSAGE(STATUS “This is the hello_static
OUTPUT_NAME:”${OUTPUT_VALUE})
如果没有这个属性定义,则返回 NOTFOUND.
让我们来检查一下最终的构建结果,我们发现,libhello.a 已经构建完成,位于
build/lib 目录中,但是 libhello.so 去消失了。这个问题的原因是:cmake 在构建一
个新的 target 时,会尝试清理掉其他使用这个名字的库,因为,在构建 libhello.a 时,
就会清理掉 libhello.so.
为了回避这个问题,比如再次使用 SET_TARGET_PROPERTIES 定义
CLEAN_DIRECT_OUTPUT 属性。
向 lib/CMakeLists.txt 中添加:
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT
1)
这时候,我们再次进行构建,会发现 build/lib 目录中同时生成了 libhello.so 和
libhello.a
五,动态库版本号
按照规则,动态库是应该包含一个版本号的,我们可以看一下系统的动态库,一般情况是
libhello.so.1.2
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.2
为了实现动态库版本号,我们仍然需要使用 SET_TARGET_PROPERTIES 指令。
具体使用方法如下:
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION 指代动态库版本,SOVERSION 指代 API 版本。
将上述指令加入 lib/CMakeLists.txt 中,重新构建看看结果。
在 build/lib 目录会生成:
libhello.so.1.2
libhello.so.1->libhello.so.1.2
libhello.so ->libhello.so.1
六,安装共享库和头文件
以上面的例子,我们需要将 libhello.a, libhello.so.x 以及 hello.h 安装到系统目
录,才能真正让其他人开发使用,在本例中我们将 hello 的共享库安装到<prefix>/lib
目录,将 hello.h 安装到<prefix>/include/hello 目录。
利用上一节了解到的 INSTALL 指令,我们向 lib/CMakeLists.txt 中添加如下指令:
INSTALL(TARGETS hello hello_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include/hello)
注意,静态库要使用 ARCHIVE 关键字
通过:
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
make install
我们就可以将头文件和共享库安装到系统目录/usr/lib 和/usr/include/hello 中了。
七,小结:
本小节,我们谈到了:
如何通过 ADD_LIBRARY 指令构建动态库和静态库。
如何通过 SET_TARGET_PROPERTIES 同时构建同名的动态库和静态库。
如何通过 SET_TARGET_PROPERTIES 控制动态库版本
最终使用上一节谈到的 INSTALL 指令来安装头文件和动态、静态库。

 

参考:
http://17875038.blog.hexun.com/80317937_d.html


http://blog.chinaunix.net/uid-14007440-id-3189851.html

 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值