CMake详细教程

这篇具有很好参考价值的文章主要介绍了CMake详细教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本文用于记录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站教学视频文章来源地址https://www.toymoban.com/news/detail-496371.html

到了这里,关于CMake详细教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《Git入门实践教程》前言+目录

    版本控制系统(VCS)在项目开发中异常重要,但和在校大学生的交流中知道,这个重要方向并未受到重视。具备这一技能,既是项目开发能力的体现,也可为各种面试加码。在学习体验后知道,Git多样化平台、多种操作方式、丰富的资源为业内人士提供了方便的同时,也造成

    2024年02月10日
    浏览(68)
  • 一个用于Allen脑图谱基因数据的工具箱|abagen详细使用教程-获取基于脑区的基因表达矩阵(脑区*gene)

    艾伦人类脑图谱(Allen Human Brain Atlas) 艾伦人类脑图谱是一个由艾伦脑科学研究所(Allen Institute for Brain Science)开发的在线基因表达图谱数据库,旨在提供人类大脑各个区域的细胞类型和基因表达信息。 这个数据库包含了人类全基因组微阵列数据集、RNA测序数据集等,并使用标

    2024年02月16日
    浏览(56)
  • 【RabbitMQ教程】前言 —— 中间件介绍

                                                                       💧 【 R a b b i t M Q 教程】前言——中间件介绍 color{#FF1493}{【RabbitMQ教程】前言 —— 中间件介绍} 【 R abbi tMQ 教程】前言 —— 中间件介绍 💧           🌷 仰望天空,妳

    2024年02月08日
    浏览(69)
  • 《Docker极简教程》--前言--Docker的简介

    Docker 是一种用于构建、部署和运行应用程序的开源平台,它使用容器技术来实现轻量级、可移植和自包含的应用程序环境。Docker 的核心思想是将应用程序及其依赖项打包到一个称为容器的封闭单元中,从而消除了在不同环境中运行应用程序时可能出现的许多兼容性和依赖性

    2024年02月21日
    浏览(49)
  • 【k8s完整实战教程0】前言

    系列文章:这个系列已完结,如对您有帮助,求点赞收藏评论。 读者寄语: 再小的帆,也能远航! 【k8s完整实战教程0】前言 【k8s完整实战教程1】源码管理-Coding 【k8s完整实战教程2】腾讯云搭建k8s托管集群 【k8s完整实战教程3】k8s集群部署kubesphere 【k8s完整实战教程4】使用

    2023年04月24日
    浏览(39)
  • 超详细,多图 PVE 安装 OpenWRT 教程(个人记录)

    - 写这个的目的是因为本人健忘所以做个记录以便日后再折腾时查阅。 - 本人笔拙如有选词,错字,语法,标点错误请忽视,大概率不会修改,我自己能看懂就好。 - 内容仅适用于本人的使用环境,不同环境请忽视或仅作参考。 - 文中出现的内容来自网络和本人浅薄的认知,

    2024年02月14日
    浏览(28)
  • 超详细,多图,PVE安装以及简单设置教程(个人记录)

    - 写这个的目的是因为本人健忘所以做个记录以便日后再折腾时查阅,。 - 本人笔拙如有选词,错字,语法,标点错误请忽视,大概率知道了也不会修改,本人能看懂就好。 - 内容仅适用于本人的使用环境,不同环境请忽视或仅作参考。 - 文中出现的内容来自网络和本人浅薄的

    2024年02月04日
    浏览(41)
  • Cmake笔记记录

    工作后开发内容都是在Linux系统下完成,cmake使用比较频繁,找到一篇很不错的CMake笔记。 记录下来方便自己查阅。 CMake是一种跨平台的编译配置工具,它可以在不同的平台下基于同样的源代码文件生成对应的工程文件。例如Makefile和VS工程. 使用CMake的流程如下: ①编写 CMakeLis

    2024年02月16日
    浏览(30)
  • Cmake学习记录(九)--使用Cmake交叉编译Android .so库

    注意:本教程没有关于JNI接口的写法,只是把C代码编译成适合android平台的so库,想查看完整代码可以参考文末的第9条参考链接 目前Android编译.so的话使用Android Studio比较简单,但是有时候时候Android Studio的话还需要创建一个Android的项目,这里记录下脱离Android Studio单纯使用Cma

    2024年02月12日
    浏览(41)
  • 记录--UNI-APP安卓本地打包详细教程(保姆级)

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 uni-app 官方文档地址 原生开发者支持 1、Android Studio 下载地址:Android Studio官网 OR Android Studio中文社区 2、最新版的HBuilderX 3、App离线SDK下载:最新android平台SDK下载 4、3.1.10版本起需要申请Appkey,申请请参考

    2023年04月09日
    浏览(76)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包