C++开发者必备技能CMake
先简单介绍一下,CMake是一个跨平台的编译工具,它可以根据不用的平台,不同的编译环境,生成不同的MakeFile,从而控制编译的过程。
使用CMake的步骤:
1、ccmake directory //配置编译选项,这个命令不太常用,所以没有深入了解
2、cmake directory //这个目录是CMkaeLists.txt所在的目录,用于生成MakeFile文件,实际使用首先要执行这个命令生成MakeFile,才能进行下一步编译工作,这一步cmake会查询当前的编译环境,生成适合当前环境的编译文件
3、make //最后一步,简单的make,不需要参数,自动完成编译,执行这个命令需要在MakeFile目录下
使用cmake的命令就是这么简单,但是最复杂的在于CMakeLists.txt的编写,它包含一系列编译的命令,包括定义工程信息,包含头文件,链接库文件等等,使用cmake最关键的就是学会CMkaeLists.txt的命令。(CMakeLists.txt对命令大小写不敏感)
如果工程下面有子目录,子目录下需要定义一些库的话,可以把所有的文件在工程的根目录的CMakeLists.txt中全部指定,但是这样做在工程庞大的情况下根目录的CMakeLists.txt会显得非常臃肿且难以管理,所以我们可以在每个子目录中都使用一个CMakeLists.txt,然后对每一个子目录中的库进行单独的编译。因此常用的做法是专门写一个编译的脚本,按照库引用的先后顺序去编译每一个子目录下面的库
project(test) project定义一个工程,名字为test
add_library(lib_sock sock.cpp sock.h) add_library命令,添加一个库,这个库要编译的文件列表,第一个lib_sock是给这个库定义一个名称,sock.cpp sock.h是这个库要编译的文件,例如添加一个sock类,类声明放在sock.h中,函数实现放在sock.cpp中,那么如果后面编译库文件或者编译可执行文件要用到这个类的话,必须以这样的形式把这两个文件包含进来。
link_libraries(lib_sock) 链接库命令,上面add_library定义了一个库,名字为lib_sock,link_libraries命令就是把这个库编译好后链接进来,这个步骤是必须的
add_executable(pop3_client client.cpp) 编译一个可执行文件,如果client.cpp中用到了上面的sock.h中的类,那么在执行这个命令之前必须执行add_library和link_libraries命令先把库链接进来才能编译出这个可执行文件
FIND_LIBRARY(SUM_LIB lib_sum ./sum NO_DEFAULT_PATH) FIND_LIBRARY命令,用于在不确定库的位置的时候模糊查找的命令,在例子中./sum是要查找的目录的路径,可以是相对路径,lib_sum是要查找的库的名称,SUM_LIB将会得到查找的结果,所以这条命令往往要配合link_libraries命令使用,也就是在查找到库之后如果下一步的编译需要用到,那么就把这个库链接进来。因此这里也可以看出link_libraries命令的参数其实就是一个库的路径,例如我们也可以这样去调用这个命令: link_libraries(/home/xiaxiaosheng/test/sum/liblib_sum.a),liblib_sum.a是一个已经编译好的静态库
下面这个例子是我练习的时候的CMakeLists.txt:
project(pop3_client) add_library(
lib_sock
sock.cpp
sock.h
)
link_libraries(lib_sock) link_libraries(${PROJECT_SOURCE_DIR}/sum/liblib_sum.a)
#FIND_LIBRARY(SUM_LIB lib_sum ./sum NO_DEFAULT_PATH) #message("sum_lib:::======================" ${SUM_LIB}) #打印一条信息 #link_libraries(${SUM_LIB}) #把找到的库链接 add_executable(pop3_client client.cpp) #编译出一个可执行文件
其中这个PROJECT_SOURCE_DIR是工程的根目录,用的时候像shell脚本的语法类似${PROJECT_SOURCE_DIR},要注意的地方就是link_libraries的参数是一个库的路径,但是,这个路径只能是绝对路径,不能是相对目录,所以我们这个时候就可以用${PROJECT_SOURCE_DIR}工程的根目录,从根目录出发,在后面加上相对于根目录的路径就可以得到目标的绝对路径,例如${PROJECT_SOURCE_DIR}/sum/liblib_sum.a,这个liblib_sum.a就是根目录下的一个子目录sum下有一个liblib_sum.a库
持续更新...