当前位置: 首页 > news >正文

CMake详细教程

文章目录

  • 前言
  • 一、CMake是什么
  • 二、CMake安装
  • 三、CMake一个HelloWorld
  • 四、CMake一个HelloWorld语法介绍
    • 1、PROJECT关键字
    • 2、SET关键字
    • 3、MESSAGE关键字
    • 4、ADD_EXECUTABLE关键字
  • 五、CMake语法的基本原则与注意事项
    • 1、基本原则
    • 2、注意事项
  • 六、内部构建与外部构建
    • 1、外部构建方式举例
  • 七、让Hello World看起来更像一个工程
  • 八、安装
    • 1、安装的两种方式
    • 2、安装HelloWorld
      • 2.1、安装文件COPYRIGHT和README
    • 2.2、安装脚本runhello.sh
    • 2.3、安装doc中hello.txt
    • 2.4、安装步骤
  • 九、静态库和动态库的构建
    • 1、同时构建静态和动态库
    • 2、动态库的版本号
    • 3、安装共享库和头文件
  • 九、使用外部共享库和头文件
    • 1、解决make后头文件找不到
    • 2、解决引用的函数问题
  • references

前言

本文用于记录CMake学习

一、CMake是什么

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。
简单来说就是当多个人用不同的语言或者编译器开发同一个项目,最终需要输出一个可执行文件或者共享库(dll,so等),这个时候就可以利用CMake了(如果你不使用CMake,你可能就需要利用gcc/g++去逐个编译),所有的操作都是通过变异CMakeLists.txt来完成的。

二、CMake安装

  1. 绝大多数的linux系统已经安装了CMake

    yum -y install cmake
    
  2. Windows或某些没有安装过的linux系统,去http://www.cmake.org/HTML/Download.htm下载安装

三、CMake一个HelloWorld

使用平台为centos 7

  1. 写一个HelloWorld

    #include <iostream>
    
    int main(){
    std::cout <<  "hello word" << std::endl;
    }
    
  2. 写CMakeLists.txt(注意大小写)

    PROJECT (HELLO)
    
    SET(SRC_LIST main.cpp)
    
    MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
    
    MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
    
    ADD_EXECUTABLE(hello ${SRC_LIST})
    
  3. 使用cmake,生成makefile文件

    [root@localhost cmake_learning]# cmake . // .表示当前目录
    

    输出

    CMake Warning (dev) in CMakeLists.txt:
      Syntax Warning in cmake code at
    
        /learning/cmake_learning/CMakeLists.txt:7:37
    
      Argument not separated from preceding token by whitespace.
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    -- The C compiler identification is GNU 4.8.5
    -- The CXX compiler identification is GNU 4.8.5
    -- Check for working C compiler: /usr/bin/cc
    -- Check for working C compiler: /usr/bin/cc -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- This is BINARY dir /learning/cmake_learning
    -- This is SOURCE dir /learning/cmake_learning
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /learning/cmake_learning
    

    目录下就生成了这些文件-CMakeFiles, CMakeCache.txt, cmake_install.cmake 等文件,并且生成了Makefile.现在不需要理会这些文件的作用,以后你也可以不去理会。最关键的是,它自动生成了Makefile.

  4. 使用make命令编译

    [root@localhost cmake_learning]# make
    

    输出

    Scanning dependencies of target hello
    [100%] Building CXX object CMakeFiles/hello.dir/main.cpp.o
    Linking CXX executable hello
    [100%] Built target hello
    
  5. 生成可执行文件hello并执行

    [root@localhost cmake_learning]# ls
    CMakeCache.txt  cmake_install.cmake  hello     Makefile
    CMakeFiles      CMakeLists.txt       main.cpp
    [root@localhost cmake_learning]# ./hello 
    hello world
    

四、CMake一个HelloWorld语法介绍

1、PROJECT关键字

project关键字可以用来指定工程的名字和支持的语言,默认支持所有语言

PROJECT (HELLO)   指定了工程的名字,并且支持所有语言—建议
PROJECT (HELLO CXX)      指定了工程的名字,并且支持语言是C++
PROJECT (HELLO C CXX)      指定了工程的名字,并且支持语言是C和C++
PROJECT (HELLO C CXX JAVA)      指定了工程的名字,并且支持语言是C、C++和JAVA
语言名要大写

该指令隐式定义了两个CMAKE的变量

<projectname>_BINARY_DIR,本例中是 HELLO_BINARY_DIR

<projectname>_SOURCE_DIR,本例中是 HELLO_SOURCE_DIR
这个两个变量都指向当前的工作目录

MESSAGE关键字就可以直接使用这两个变量,都指向当前的工作目录,后面会讲外部编译

问题:如果改了工程名,这两个变量名也会改变(请回头看一眼CMakeLists.txt文件)

解决:CMake预定义两个变量PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,这两个变量和HELLO_BINARY_DIR,HELLO_SOURCE_DIR是一致的。所以改了工程名也没有关系
即可以将上述CMakeLists.txt文件中的

MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})

替换为

MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${PROJECT_SOURCE_DIR})

2、SET关键字

SET关键字用来显示指定的变量

SET(SRC_LIST main.cpp)    SRC_LIST变量就包含了main.cpp
// 假设还存在t1.cpp t2.cpp
 SET(SRC_LIST main.cpp t1.cpp t2.cpp)

3、MESSAGE关键字

MESSAGE关键字主要用于向终端输出用户自定义的信息,主要包含三种信息

  • SEND_ERROR,产生错误,生成过程被跳过
  • STATUS,输出前缀为–的信息
  • FATAL_ERROR,立即终止所有cmake过程

4、ADD_EXECUTABLE关键字

ADD_EXECUTABLE关键字用于生成可执行文件

ADD_EXECUTABLE(hello ${SRC_LIST}) 生成的可执行文件名是hello,源文件读取变量SRC_LIST中的内容,也可以直接写 ADD_EXECUTABLE(hello main.cpp)

上述例子可以简化的写成

PROJECT(HELLO)
ADD_EXECUTABLE(hello main.cpp)

注意:工程名的 HELLO 和生成的可执行文件 hello 是没有任何关系的

五、CMake语法的基本原则与注意事项

1、基本原则

  • 变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名

  • 指令(参数 1 参数 2…) 参数使用括弧括起,参数之间使用空格或分号分开。 以上面的 ADD_EXECUTABLE 指令为例,如果存在另外一个 func.cpp 源文件就要写成:ADD_EXECUTABLE(hello main.cpp func.cpp)或者ADD_EXECUTABLE(hello main.cpp;func.cpp)

  • 指令是大小写无关的,参数和变量是大小写相关的。但推荐你全部使用大写指令

2、注意事项

  • SET(SRC_LIST main.cpp) 可以写成 SET(SRC_LIST “main.cpp”),如果源文件名中含有空格m ain.cpp,就必须要加双引号
  • ADD_EXECUTABLE(hello main) 后缀可以不行,他会自动去找.c和.cpp,最好不要这样写,可能会有这两个文件main.cpp和main

六、内部构建与外部构建

  • 上述例子就是内部构建,生产的临时文件特别多,不方便清理
  • 外部构建,就会把生成的临时文件放在build目录下,不会对源文件有任何影响强烈使用外部构建方式

1、外部构建方式举例

还是上述那个例子

[root@localhost cmake_learning]# ls -l
总用量 8
-rw-r--r--. 1 root root 196 1128 16:33 CMakeLists.txt
-rw-r--r--. 1 root root  77 1128 16:31 main.cpp
  1. 在当前目录下建立一个build目录(可以在任何目录下,建议当前目录下)

    [root@localhost cmake_learning]# mkdir build
    [root@localhost cmake_learning]# ls
    build  CMakeLists.txt  main.cpp
    
  2. 进入build,运行cmake .. 当然…表示上一级目录,你可以写CMakeLists.txt所在的绝对路径,生产的文件都在build目录下了

    [root@localhost cmake_learning]# cd build/
    [root@localhost build]# cmake ..
    CMake Warning (dev) in CMakeLists.txt:
      Syntax Warning in cmake code at
    
        /learning/cmake_learning/CMakeLists.txt:7:37
    
      Argument not separated from preceding token by whitespace.
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    -- The C compiler identification is GNU 4.8.5
    -- The CXX compiler identification is GNU 4.8.5
    -- Check for working C compiler: /usr/bin/cc
    -- Check for working C compiler: /usr/bin/cc -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- This is BINARY dir /learning/cmake_learning/build
    -- This is SOURCE dir /learning/cmake_learning
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /learning/cmake_learning/build
    
  3. 在build目录下,运行make来构建工程

    [root@localhost build]# make
    Scanning dependencies of target hello
    [100%] Building CXX object CMakeFiles/hello.dir/main.cpp.o
    Linking CXX executable hello
    [100%] Built target hello
    [root@localhost build]# ls -l
    总用量 40
    -rw-r--r--. 1 root root 12023 1128 16:36 CMakeCache.txt
    drwxr-xr-x. 5 root root   232 1128 16:36 CMakeFiles
    -rw-r--r--. 1 root root  1594 1128 16:36 cmake_install.cmake
    -rwxr-xr-x. 1 root root 71776 1128 16:36 hello
    -rw-r--r--. 1 root root  4680 1128 16:36 Makefile
    

注意外部构建的两个变量

1、HELLO_SOURCE_DIR 还是工程路径

2、HELLO_BINARY_DIR 编译路径 也就是 /learning/cmake_learning/bulid

七、让Hello World看起来更像一个工程

  • 为工程添加一个子目录 src,用来放置工程源代码
  • 添加一个子目录 doc,用来放置这个工程的文档 hello.txt
  • 在工程目录添加文本文件 COPYRIGHT(版权), README
  • 在工程目录添加一个 runhello.sh 脚本,用来调用 hello 二进制
  • 将构建后的目标文件放入构建目录的 bin 子目录
  • 将 doc 目录 的内容以及 COPYRIGHT/README 安装到/usr/share/doc/cmake/

注意:每个目录下都需要有一个CMakeLists.txt文件

[root@localhost cmake_learning]# tree
.
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

2 directories, 3 files

最外层(.目录下)CMakeLists.txt内容

[root@localhost cmake_learning]# cat CMakeLists.txt 
PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)

ADD_SUBDIRECTORY 指令

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
  • 这个指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置

  • EXCLUDE_FROM_ALL函数是将写的目录从编译中排除,如程序中的example

  • ADD_SUBDIRECTORY(src bin)

    将 src 子目录加入工程并指定编译输出(包含编译中间结果)路径为bin 目录
    如果不进行 bin 目录的指定,那么编译结果(包括中间结果)都将存放在build/src 目录

src目录下

[root@localhost src]# cat CMakeLists.txt 
ADD_EXECUTABLE(hello main.cpp)

build目录下

[root@localhost build]# pwd
/learning/cmake_learning/build
[root@localhost build]# cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 2.8)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /learning/cmake_learning/build
[root@localhost build]# ls
bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
[root@localhost build]# make 
Scanning dependencies of target hello
[100%] Building CXX object bin/CMakeFiles/hello.dir/main.o
Linking CXX executable hello
[100%] Built target hello
[root@localhost build]# ls
bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
[root@localhost build]# cd bin
[root@localhost bin]# ls
CMakeFiles  cmake_install.cmake  hello  Makefile
[root@localhost bin]# ./hello 
hello world

在这里再解释一下ADD_SUBDIRECTORY指令,根据最后的结果可以看到,可执行文件hello是在src/bin/下,这就验证了开始所说的将构建后的目标文件放入构建目录的 bin 子目录

八、安装

1、安装的两种方式

  1. 从代码编译后直接 make install 安装
  2. 是打包时的指定 目录安装。
    • 简单的可以这样指定目录:make install DESTDIR=/tmp/test
    • 稍微复杂一点可以这样指定目录:./configure –prefix=/usr

2、安装HelloWorld

  1. 删除build目录下的内容

    [root@localhost cmake_learning]# tree
    .
    ├── build
    ├── CMakeLists.txt
    └── src
        ├── CMakeLists.txt
        └── main.cpp
    
  2. 创建部分文件

    [root@localhost cmake_learning]# touch COPYRIGHT
    [root@localhost cmake_learning]# mkdir doc 
    [root@localhost cmake_learning]# cd doc/
    [root@localhost doc]# touch hello.txt
    [root@localhost doc]# cd ..
    [root@localhost cmake_learning]# touch README
    [root@localhost cmake_learning]# touch runhello.sh
    [root@localhost cmake_learning]# ll
    总用量 4
    drwxr-xr-x. 2 root root  6 1128 18:38 build
    -rw-r--r--. 1 root root 41 1128 17:53 CMakeLists.txt
    -rw-r--r--. 1 root root  0 1128 18:40 COPYRIGHT
    drwxr-xr-x. 2 root root 23 1128 18:41 doc
    -rw-r--r--. 1 root root  0 1128 18:41 README
    -rw-r--r--. 1 root root  0 1128 18:42 runhello.sh
    drwxr-xr-x. 2 root root 44 1128 17:50 src
    

    目录树结构为:

    [root@localhost cmake_learning]# tree
    .
    ├── build
    ├── CMakeLists.txt
    ├── COPYRIGHT
    ├── doc
    │   └── hello.txt
    ├── README
    ├── runhello.sh
    └── src
        ├── CMakeLists.txt
        └── main.cpp
    
    3 directories, 7 files
    

2.1、安装文件COPYRIGHT和README

使用CMAKE一个新的指令:INSTALL

INSTALL的安装可以包括:二进制、动态库、静态库以及文件、目录、脚本等

使用CMAKE一个新的变量:CMAKE_INSTALL_PREFIX

[root@localhost cmake_learning]# vim CMakeLists.txt 

PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)
INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake)

FILES:表示安装文件

DESTINATION:表示路径

  1. 写绝对路径

  2. 可以写相对路径,相对路径实际路径是:

    ${CMAKE_INSTALL_PREFIX}/<DESTINATION 定义的路径>
    

    CMAKE_INSTALL_PREFIX 默认是在 /usr/local/

    cmake -DCMAKE_INSTALL_PREFIX=/usr    
    在cmake的时候指定CMAKE_INSTALL_PREFIX变量的路径
    

2.2、安装脚本runhello.sh

[root@localhost cmake_learning]# vim CMakeLists.txt 

PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)
INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake)
INSTALL(PROGRAMS runhello.sh DESTINATION bin)

PROGRAMS:表示安装的是非目标文件的可执行程序安装(比如脚本之类)

INSTALL(PROGRAMS runhello.sh DESTINATION bin)

说明:实际安装到的是 /usr/local/bin

2.3、安装doc中hello.txt

两种方式

  1. 是通过在 doc 目录建立CMakeLists.txt ,通过install下的file

  2. 是直接在工程目录通过

    INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake)

这里采用第二种

[root@localhost cmake_learning]# vim CMakeLists.txt 

PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)
INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake)
INSTALL(PROGRAMS runhello.sh DESTINATION bin)
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake)

DIRECTORY 后面连接的是所在 Source 目录的相对路径

注意:abc 和 abc/有很大的区别

目录名不以/结尾:这个目录将被安装为目标路径下的

目录名以/结尾:将这个目录中的内容安装到目标路径

2.4、安装步骤

[root@localhost cmake_learning]# cd build/
[root@localhost build]# cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 2.8)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /learning/cmake_learning/build
[root@localhost build]# ll
总用量 28
drwxr-xr-x. 3 root root    67 1128 19:23 bin
-rw-r--r--. 1 root root 12353 1128 19:23 CMakeCache.txt
drwxr-xr-x. 4 root root   215 1128 19:23 CMakeFiles
-rw-r--r--. 1 root root  2730 1128 19:23 cmake_install.cmake
-rw-r--r--. 1 root root  5735 1128 19:23 Makefile
[root@localhost build]# make 
Scanning dependencies of target hello
[100%] Building CXX object bin/CMakeFiles/hello.dir/main.o
Linking CXX executable hello
[100%] Built target hello
[root@localhost build]# ll 
总用量 28
drwxr-xr-x. 3 root root    80 1128 19:24 bin
-rw-r--r--. 1 root root 12353 1128 19:23 CMakeCache.txt
drwxr-xr-x. 4 root root   215 1128 19:24 CMakeFiles
-rw-r--r--. 1 root root  2730 1128 19:23 cmake_install.cmake
-rw-r--r--. 1 root root  5735 1128 19:23 Makefile
[root@localhost build]# ll bin/
总用量 28
drwxr-xr-x. 3 root root    84 1128 19:23 CMakeFiles
-rw-r--r--. 1 root root  1152 1128 19:23 cmake_install.cmake
-rwxr-xr-x. 1 root root 71776 1128 19:24 hello
-rw-r--r--. 1 root root  6703 1128 19:23 Makefile
[root@localhost build]# make install
[100%] Built target hello
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/share/doc/cmake/COPYRIGHT
-- Installing: /usr/local/share/doc/cmake/README
-- Installing: /usr/local/bin/runhello.sh
-- Installing: /usr/local/share/doc/cmake
-- Installing: /usr/local/share/doc/cmake/hello.txt

九、静态库和动态库的构建

新建了一个目录 /learning/cmake_learning_1/

任务:

  1. 建立一个静态库和动态库,提供 HelloFunc 函数供其他程序编程使用,HelloFunc 向终端输出 Hello World 字符串
  2. 安装头文件与共享库

静态库和动态库的区别

  • 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”。
  • 静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行
  • 动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行。

当N个人共用一份代码时,就可以使用动态库,如果不一样,那就使用静态裤。

[root@localhost cmake_learning_1]# tree
.
├── build
├── CMakeLists.txt
└── lib
    ├── CMakeLists.txt
    ├── hello.cpp
    └── hello.h

2 directories, 4 files

hello.h中的内容

#ifndef HELLO_H
#define Hello_H

void HelloFunc();

#endif

hello.cpp中的内容

#include "hello.h"
#include <iostream>
void HelloFunc(){
    std::cout << "Hello World" << std::endl;
}

项目中的CMakeLists.txt中的内容

PROJECT(HELLO)
ADD_SUBDIRECTORY(lib bin)

lib中CMakeLists.txt中的内容

SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

  • hello:就是正常的库名,生成的名字前面会加上lib,最终产生的文件是libhello.so
  • SHARED,动态库 STATIC,静态库
  • ${LIBHELLO_SRC} :源文件

1、同时构建静态和动态库

// 如果用这种方式,只会构建一个动态库,不会构建出静态库,虽然静态库的后缀是.a
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})

// 修改静态库的名字,这样是可以的,但是我们往往希望他们的名字是相同的,只是后缀不同而已
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本

同时构建静态和动态库

SET(LIBHELLO_SRC hello.cpp)

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

//对hello_static的重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES  OUTPUT_NAME "hello")
//cmake 在构建一个新的target 时,会尝试清理掉其他使用这个名字的库,因为,在构建 libhello.so 时, 就会清理掉 libhello.a
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

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

2、动态库的版本号

一般动态库都有一个版本号的关联

libhello.so.1.2
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.2

CMakeLists.txt 插入如下

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

VERSION 指代动态库版本,SOVERSION 指代 API 版本。

3、安装共享库和头文件

本例中我们将 hello 的共享库安装到/lib目录,

将 hello.h 安装到/include/hello 目录

SET(LIBHELLO_SRC hello.cpp)

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

//对hello_static的重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES  OUTPUT_NAME "hello")
//cmake 在构建一个新的target 时,会尝试清理掉其他使用这个名字的库,因为,在构建 libhello.so 时, 就会清理掉 libhello.a
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES(hello PROPERTIES  OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
//文件放到该目录下
INSTALL(FILES hello.h DESTINATION include/hello)

//二进制,静态库,动态库安装都用TARGETS
//ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME 特指可执行目标二进制。
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)

注意:

安装的时候,指定一下路径,放到系统下

cmake -D CMAKE_INSTALL_PREFIX=/usr .. // .. 表示上一级目录

九、使用外部共享库和头文件

准备工作:建立一个新的目录 /learning/cmake_learing_2/

[root@localhost cmake_learning_2]# tree
.
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

main.cpp

#include <hello.h>

int main(){
	HelloFunc();
}
[root@localhost build]# cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 2.8)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /learning/cmake_learning_2/build
[root@localhost build]# ls
bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
[root@localhost build]# make
Scanning dependencies of target hello
[100%] Building CXX object bin/CMakeFiles/hello.dir/main.o
/learning/cmake_learning_2/src/main.cpp:1:19: 致命错误:hello.h:没有那个文件或目录
 #include <hello.h>
                   ^
编译中断。
make[2]: *** [bin/CMakeFiles/hello.dir/main.o] 错误 1
make[1]: *** [bin/CMakeFiles/hello.dir/all] 错误 2
make: *** [all] 错误 2

1、解决make后头文件找不到

第一种:include <hello/hello.h>

第二种:利用关键字:INCLUDE_DIRECTORIES 这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割

在CMakeLists.txt中加入头文件搜索路径

INCLUDE_DIRECTORIES(/usr/include/hello)

2、解决引用的函数问题

[root@localhost build]# cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 2.8)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /learning/cmake_learning_2/build
[root@localhost build]# make
Scanning dependencies of target hello
[100%] Building CXX object bin/CMakeFiles/hello.dir/main.o
Linking CXX executable hello
CMakeFiles/hello.dir/main.o:在函数‘main’中:
main.cpp:(.text+0x8):对‘HelloFunc()’未定义的引用
collect2: 错误:ld 返回 1
make[2]: *** [bin/hello] 错误 1
make[1]: *** [bin/CMakeFiles/hello.dir/all] 错误 2
make: *** [all] 错误 2

报错信息:undefined reference to `HelloFunc()’

关键字:LINK_DIRECTORIES 添加非标准的共享库搜索路径

指定第三方库所在路径,LINK_DIRECTORIES(/home/myproject/libs)

关键字:TARGET_LINK_LIBRARIES 添加需要链接的共享库

TARGET_LINK_LIBRARIES的时候,只需要给出动态链接库的名字就行了。

在CMakeLists.txt中插入链接共享库,主要要插在executable的后面

注意:64位的虚拟机需要执行一下mv操作, 就可以执行./hello 了

[root@localhost bin]# ./hello 
./hello: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
[root@localhost bin]# mv /usr/lib/libhello.so /usr/lib64/

链接静态库

TARGET_LINK_LIBRARIES(main libhello.a)

特殊的环境变量 CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH

注意:这两个是环境变量而不是 cmake 变量,可以在linux的bash中进行设置

我们上面例子中使用了绝对路径INCLUDE_DIRECTORIES(/usr/include/hello)来指明include路径的位置

我们还可以使用另外一种方式,使用环境变量export CMAKE_INCLUDE_PATH=/usr/include/hello

补充:生产debug版本的方法:
cmake … -DCMAKE_BUILD_TYPE=debug

references

B站教学视频

相关文章:

  • CorelDRAW破解版是如何一步一步坑人的
  • 堆排序讲解
  • 网络工程师备考3章
  • 算法day42|背包问题
  • 《构建中小企业网络V7.1》实验
  • R语言贝叶斯Poisson泊松-正态分布模型分析职业足球比赛进球数
  • Matplotlib入门[05]——注释与标签
  • HarmonyOS/OpenHarmony应用开发-FA模型综述
  • Vue中的diff算法深度解析
  • redis常用数据结构基本命令
  • 公路交叉数(POJ3067)-树状数组解决逆序对
  • k8s删除node
  • 使用SpringBoot快速构建Web API
  • vue 如何获取路由详细内容信息
  • 【数据库系统】数据更新
  • 【视觉高级篇】23 # 如何模拟光照让3D场景更逼真?(上)
  • itss是什么证书
  • 排序算法-计数排序、桶排序、基数排序
  • postgresql 11.2+gis+pgpool 4.2.2 离线安装步骤
  • 项目管理(如何进行项目风险管理)
  • 电加热油锅炉工作原理_电加热导油
  • 大型电蒸汽锅炉_工业电阻炉
  • 燃气蒸汽锅炉的分类_大连生物质蒸汽锅炉
  • 天津市维修锅炉_锅炉汽化处理方法
  • 蒸汽汽锅炉厂家_延安锅炉厂家
  • 山西热水锅炉厂家_酒店热水 锅炉
  • 蒸汽锅炉生产厂家_燃油蒸汽发生器
  • 燃煤锅炉烧热水_张家口 淘汰取缔燃煤锅炉
  • 生物质锅炉_炉
  • 锅炉天然气_天燃气热风炉