《CMAKE实践》读书笔记


在这里插入图片描述

简单cmake

在开篇的思维导图中已经展示了该实例的文件布局。其中main.cpp/CmakeLists.txt内容如下所示:

main.cpp

#include <iostream>
using namespace std;

int main(){
	std::cout << "hello world" << endl;
	return 0;
}

CmakeLists.txt

PROJECT(HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "THIS is a binary dir" ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is source dir" ${HELLO_SOURCE_DIR})

ADD_EXECUTABLE(hello ${SRC_LIST})

接着我们来看下构建过程,

  1. ./build目录下执行cmake .., ..表示上一级目录;此时build目录下产生如下文件:
[root@instance-avkrpt0w t1]# ls build/
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile

在这些文件中,最重要的当然是Makefile文件啦。

  1. 同样的build目录下执行make命令,此刻产生可执行文件hello

对于上述使用过的指令做一个简单的解释:

  1. PROJECT(projectname [CXX] [C] [Java]),用于指定工程名称,同时指定支持语言。该语句隐形定义两个cmake变量,PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR
  2. SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]) , docstring : 文档字符串,显示定义变量。
  3. MESSAGE([SEND_ERROR] | STATUS | fATAL_ERROR], "message to display...."),向终端输出用户定义的信息。
    1. SEND_ERROR, 产生错误,生成过程跳过。
    2. STATUS,输出信息
    3. ‘FATAL_ERROR’,终止所有cmake过程。
  4. ADD_EXECUTALBE(hello ${SRC_LIST}),生成一个hello的可执行文件。SRC_LIST,源文件列表,一般用过SET定义。

更好一点的cmake

在开篇的思维导图中已经展示了该实例的文件布局。其中文件具体如下:

  • ./src/main.cpp:和上述一样,打印hello , world。
  • COPYRIGHT, README,随意写一些东西
  • runhello.sh脚本,用来调用hello二进制。
  • ./bin,保存二进制文件与中间文件。
  • 主工程./CMakeLists.txt如下:
PROJECT(HELLO)

# 将src源文件产生的中间文件和目标二进制存放在project_binary_dir/bin目录下
ADD_SUBDIRECTORY(src bin)

INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/t2)
INSTALL(PROGRAMS runhello.sh DESTINATION bin)
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/t2)
  • ./src/CMakeLists.txt如下:
# 指定最终的目标二进制的位置。
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
ADD_EXECUTABLE(hello main.cpp)

同样,构建过程如下:

  1. 目录工程下mkdir build && cd build
  2. 执行cmake -D CMAKE_INSTALL_PREFIX=/tmp/t2/usr,可以通过cmake --help看 -D的使用说明。
  3. make
  4. make install ,显示如下
[100%] Built target hello
Install the project...
-- Install configuration: ""
-- Up-to-date: /tmp/t2/usr/share/doc/cmake/t2/COPYRIGHT
-- Up-to-date: /tmp/t2/usr/share/doc/cmake/t2/README
-- Up-to-date: /tmp/t2/usr/bin/runhello.sh
-- Installing: /tmp/t2/usr/share/doc/cmake/t2
-- Up-to-date: /tmp/t2/usr/share/doc/cmake/t2/hello.txt

该文件中使用的cmake指令如下:

  • ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL]),向当前工程添加存放源文件的子目录,并可指定中间二进制和目标二进制存放位置。EXCLUDE_FROM_ALL是将这个目录从编译过程中排除。
  • 安装需要INSTALL指令和CMAKE_INSTALL_PREFIX变量相互配合,详细介绍请看cmake practice。install指令针对于FILES\PROGRAMS\DIRECTORY有不同的可选项。CMAKE_INSTALL_PREFIX就是安装路径前缀,默认为/usr/local
  • 注意:CMakeLists.txt中两种定制二进制文件和中间文件输出方法的区别。

静态库与动态库

在开篇的思维导图中已经展示了该实例的文件布局。其中文件具体如下:

./CMakeLists.txt

PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib)

./lib/CMakeLists.txt

SET(LIBHELLO_SRC hello.cpp)

# 设置lib输出
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 动态库
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相对应
GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME)
# 设置不同版本好和API号
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
MESSAGE(STATUS "this is the hello_static outputname" ${OUTPUT_VALUE})

# 安装共享库和头文件
INSTALL(TARGETS hello hello_static 
	LIBRARY DESTINATION lib
	ARCHIVE DESTINATION lib)

INSTALL(FILES hello.h DESTINATION include/hello)

./lib/hello.h

#ifndef HELLO_H
#define HELLO_H

void HelloFunc();

#endif

./lib/hello.cpp

#include "hello.h"
#include <iostream>

using namespace std;


void HelloFunc(){
	cout << "hello wold \n";
}

接着就是执行cmake -D CMAKE_INSTALL_PREFIX=/usr/local ----> make ----> make install。执行该命令显示如下:

Install the project...
-- Install configuration: ""
-- Up-to-date: /usr/local/lib/libhello.so.1.2
-- Up-to-date: /usr/local/lib/libhello.so.1
-- Up-to-date: /usr/local/lib/libhello.so
-- Up-to-date: /usr/local/lib/libhello.a
-- Installing: /usr/local/include/hello/hello.h

这段CMake代码需要注意以下几点:

  • 如何生成动态库与静态库;

  • 如何安装动态库与其头文件。

  • 如何设置同名静态库与静态库。

    这三个问题,在CMakeList.txt中已经详细介绍了。

使用静态库与动态库

文件结构与上述2一致,具体如下:

  1. ./src/main.cpp
#include "hello.h"

int main(){
	HelloFunc();
	return 0;
}
  1. ./CMakeList.txt
PROJECT(NEWHELLO)
ADD_SUBDIRECTORY(src)
  1. ./src/CMakeLists.txt
# 1头文件
INCLUDE_DIRECTORIES(/usr/include/hello)

ADD_EXECUTABLE(main main.cpp)
# 2动态库
TARGET_LINK_LIBRARIES(main hello)
# 2静态库
# TARGET_LINK_LIBRARIES(main libhello.a)

在第三章中,我们已经安装了hello的静态库、动态库、头文件,所以只需要包含其,头文件路径和hello库的路径即可,三条指令如上1,2,3

当生成可执行文件是,我们可以通过ldd main查看库信息。

**注意:**可以能在执行动态链接产生的可执行文件,会报错。这是因为链接器找不到库文件,可以通过以下ld.so.conf配置文件中插入一行/usr/lib

$ vim /etc/ld.so.conf     
  /usr/lib  

# 更新
$ ldconfig 

关于头文件与库文件搜索路径:

  1. 如果头文件与库文件安装在常规目录(/usr/local/include/usr/local/lib),那么我们在使用头文件与库文件的时候,可以当作是标准库一样使用。

  2. 如果头文件与库文件不是安装在这类路径上,我们就需要自己指定头文件与库文件搜索路径,这里有以下三种方法:

    1. INCLUDE_DIRECTORIES()LINK_DIRECTORIES() 指定头文件和库文件的绝对目录。
    2. 通过FIND_PATHFIND_LIBRARY实现1的功能,这里我们可以根据是否使用环境变量CMAKE_INCLUDE_PATHCMAKE_LIBRARY_PATH分出以下两种实现方式:
    # 方法一,未使用环境变量
    ---------------------CMake_Lists.txt----------------------
    find_path(myHeader hello.h /usr/include/hello)
    IF(myHeader)
            INCLUDE_DIRECTORIES(${myHeader})
    ENDIF(myHeader)
    
    ADD_EXECUTABLE(main main.cpp)
    
    find_library(LIBHELLO_PATH hello /tmp/t2/lib)
    IF(LIBHELLOPATH)
            MESSAGE(FATAL ERROR "libhello not found")
    ENDIF(NOT LIBHELLO_PATH)
    
    TARGET_LINK_LIBRARIES(main ${LIBHELLO_PATH})
    --------------------------------------------
    
    # 方法二,使用环境变量
    export CMAKE_INCLUDE_PATH=/usr/include/hello
    export CMAKE_LIBRARY_PATH=/tmp/t2/lib
    ------------------------CMakeLists.txt--------------
    
    find_path(myHeader hello.h)
    IF(myHeader)
            INCLUDE_DIRECTORIES(${myHeader})
    ENDIF(myHeader)
    
    ADD_EXECUTABLE(main main.cpp)
    
    find_library(LIBHELLO_PATH hello)
    IF(LIBHELLOPATH)
            MESSAGE(FATAL ERROR "libhello not found")
    ENDIF(NOT LIBHELLO_PATH)
    
    TARGET_LINK_LIBRARIES(main ${LIBHELLO_PATH})
    

FIND_PACKAGE命令使用

这里也就是将上述find_pathfind_lbrary在封装在find_package中。对于一些常用的库,cmake已经帮我写好了相应的find<name>.cmake模块,但是对于自定义的库,我们需要自己编写该模块,感兴趣的朋友可看《cmake实践》

参考

  • 《CMake实践》
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值