当前位置:   article > 正文

CMake构建_cmake构建工程

cmake构建工程

参考博客:https://blog.csdn.net/whahu1989/article/details/82078563

使用cmake-gui

在命令行下使用cmake生成Makefile进行进行编译的方法。我们也可以使用图形化界面来生成Makefile文件。cmake-gui是cmake的一个图形化工具。

安装Cmake-gui:sudo apt install cmake-gui
启动cmake-gui:cmake-gui

CMake是用来干啥的?

 CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,无需修改,非常方便。

Ubuntu安装CMake

Ubuntu16.04,安装CMake使用命令:

sudo apt install cmake
  • 1

安装完成之后,在终端下输入cmake -version查看cmake版本:

liefyuan@ubuntu:~$ cmake -version
cmake version 3.5.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).
  • 1
  • 2
  • 3
  • 4

一、CMake构建的简单使用:Helloworld

编写一个hello.c

#include "stdio.h"

int main(void)
{       
    printf("Hello World!\r\n");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在同目录下编写CMakeLists.txt

cmake_minimum_required (VERSION 2.8)
        
project (demo)
        
add_executable(hello hello.c)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1.第一行表示cmake的最低版本是2.8
  • 2.第二行表示工程信息,工程名字叫demo
  • 3.第三行很重要,表示最终生成的可执行文件的名字叫hello,使用的源文件叫hello.c

最后在同目录运行Cmake需输入命令:

cmake .
  • 1

实际输出信息为:

liefyuan@ubuntu:~/Desktop/cmake_test$ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_test
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

同目录下会生成:

liefyuan@ubuntu:~/Desktop/cmake_test$ ls -l
总用量 36
-rw-rw-r-- 1 liefyuan liefyuan 11542 Nov  7 14:50 CMakeCache.txt
drwxrwxr-x 5 liefyuan liefyuan  4096 Nov  7 14:50 CMakeFiles
-rw-rw-r-- 1 liefyuan liefyuan  1377 Nov  7 14:50 cmake_install.cmake
-rw-rw-r-- 1 liefyuan liefyuan    84 Nov  7 14:45 CMakeLists.txt
-rw-rw-r-- 1 liefyuan liefyuan    80 Nov  7 14:44 hello.c
-rw-rw-r-- 1 liefyuan liefyuan  4734 Nov  7 14:50 Makefile
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如上显示已经生成了Makefile文件,另外还有cmake运行而自动生成的文件。
接下来就可以使用make命令进行编译了。

liefyuan@ubuntu:~/Desktop/cmake_test$ make
Scanning dependencies of target hello
[ 50%] Building C object CMakeFiles/hello.dir/hello.c.o
[100%] Linking C executable hello
[100%] Built target hello
  • 1
  • 2
  • 3
  • 4
  • 5

再次看看生成文件:

liefyuan@ubuntu:~/Desktop/cmake_test$ ls -l
总用量 48
-rw-rw-r-- 1 liefyuan liefyuan 11542 Nov  7 14:50 CMakeCache.txt
drwxrwxr-x 5 liefyuan liefyuan  4096 Nov  7 14:53 CMakeFiles
-rw-rw-r-- 1 liefyuan liefyuan  1377 Nov  7 14:50 cmake_install.cmake
-rw-rw-r-- 1 liefyuan liefyuan    84 Nov  7 14:45 CMakeLists.txt
-rwxrwxr-x 1 liefyuan liefyuan  8600 Nov  7 14:53 hello
-rw-rw-r-- 1 liefyuan liefyuan    80 Nov  7 14:44 hello.c
-rw-rw-r-- 1 liefyuan liefyuan  4734 Nov  7 14:50 Makefile
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

可以看到已经生成了一个可执行的hello文件,输入./hello运行该可执行文件:

liefyuan@ubuntu:~/Desktop/cmake_test$ ./hello
Hello World!
  • 1
  • 2

运行成功!如果需要重新编译,可以使用make clean命令进行清除(删除旧的可执行文件)。

二、CMake构建:多源文件

初级:少数源文件 add_executable()

文件目录:

liefyuan@ubuntu:~/Desktop/cmake_multi_test$ ls -l
rw-rw-r-- 1 liefyuan liefyuan    93 Nov  7 16:41 CMakeLists.txt
-rw-rw-r-- 1 liefyuan liefyuan 107 Nov  7 16:34 function.c
-rw-rw-r-- 1 liefyuan liefyuan  86 Nov  7 16:38 function.h
-rw-rw-r-- 1 liefyuan liefyuan  85 Nov  7 16:30 main.c
  • 1
  • 2
  • 3
  • 4
  • 5

function.h

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

void func(unsigned int var);

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

function.c

#include <stdio.h>
#include "function.h"

void func(unsigned int var)
{
	printf("para var:%d\r\n", var);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

main.c

#include <stdio.h>
#include "function.h"

int main(void)
{
	func(200);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)

project (demo)

add_executable(main main.c function.c)
  • 1
  • 2
  • 3
  • 4
  • 5

执行cmake .生成Makefile并运行make

cmake .
  • 1
liefyuan@ubuntu:~/Desktop/cmake_multi_test$ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_multi_test
liefyuan@ubuntu:~/Desktop/cmake_multi_test$ make
Scanning dependencies of target main
[ 33%] Building C object CMakeFiles/main.dir/main.c.o
[ 66%] Building C object CMakeFiles/main.dir/function.c.o
[100%] Linking C executable main
[100%] Built target main
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
liefyuan@ubuntu:~/Desktop/cmake_multi_test$ ./main
para var:200
  • 1
  • 2

运行成功!

总结

 可以类推,如果在同一目录下有多个源文件,那么只要在add_executable里把所有源文件都添加进去就可以了。

进阶:更多源文件 aux_source_directory() 或 set()

 但是如果有一百个源文件,再这样做就有点坑了,无法体现cmake的优越性,cmake提供了一个命令可以把指定目录下所有的源文件存储在一个变量中,这个命令就是 aux_source_directory(dir var)
第一个参数dir是指定目录,第二个参数var是用于存放源文件列表的变量。

再次增加文件function2.c

#include <stdio.h>
#include "function2.h"

void func2(unsigned int var)
{
	printf("para var2:%d\r\n", var);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

增加文件function2.h

#ifndef __FUNCTION2_H__
#define __FUNCTION2_H__

void func2(unsigned int var);

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

修改main.c

#include <stdio.h>
#include "function.h"
#include "function2.h"

int main(void)
{
	func(200);
	func2(100);
	
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

修改CMakeLists.txt

cmake_minimum_required (VERSION 2.8)

project (demo)

aux_source_directory(. SRC_LIST)

add_executable(main ${SRC_LIST})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后运行cmake .make

liefyuan@ubuntu:~/Desktop/cmake_multi_test$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_multi_test
liefyuan@ubuntu:~/Desktop/cmake_multi_test$ make
Scanning dependencies of target main
[ 25%] Building C object CMakeFiles/main.dir/function.c.o
[ 50%] Building C object CMakeFiles/main.dir/function2.c.o
[ 75%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行可执行文件./main

liefyuan@ubuntu:~/Desktop/cmake_multi_test$ ./main
para var:200
para var2:100
  • 1
  • 2
  • 3

运行成功!

总结
aux_source_directory() 也存在弊端,它会把指定目录下的所有源文件都加进来,可能会加入一些我们不需要的文件,此时我们可以使用set命令去新建变量来存放需要的源文件,如下:

cmake_minimum_required (VERISON 2.8)

project (demo)

set(SRC_LIST 
		./main.c
		./function.c
		./function2.c)

add_executable(main ${SRC_LIST})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

三、CMake构建:多目录多源文件

 一般来说,当程序文件比较多时,我们会进行分类管理,把代码根据功能放在不同的目录下,这样方便查找。那么这种情况下如何编写CMakeLists.txt呢?

 我们把之前的源文件整理一下(新建2个目录function和function2),整理好后整体文件结构如下

liefyuan@ubuntu:~/Desktop/cmake_multi_dir_test$ tree
.
├── CMakeLists.txt
├── function
│   ├── function.c
│   └── function.h
├── function2
│   ├── function2.c
│   └── function2.h
└── main.c
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

修改CmakeLists.txt文件

cmake_minimum_required (VERSION 2.8)

project (demo)

include_directories (function function2)
        
aux_source_directory(function SRC_LIST)
aux_source_directory(function2 SRC_LIST2)

add_executable(main main.c ${SRC_LIST} ${SRC_LIST2})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如上:

  • 使用了2次aux_source_directory,因为源文件分布在2个目录下,所以添加2次。

然后cmake .make再运行./main

liefyuan@ubuntu:~/Desktop/cmake_multi_dir_test$ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_multi_dir_test
liefyuan@ubuntu:~/Desktop/cmake_multi_dir_test$ make
Scanning dependencies of target main
[ 25%] Building C object CMakeFiles/main.dir/main.c.o
[ 50%] Building C object CMakeFiles/main.dir/function/function.c.o
[ 75%] Building C object CMakeFiles/main.dir/function2/function2.c.o
[100%] Linking C executable main
[100%] Built target main
liefyuan@ubuntu:~/Desktop/cmake_multi_dir_test$ ./main
para var:200
para var2:100
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

正常运行!

新命令:include_directories()

 这里出现了一个新的命令:include_directories。该命令是用来向工程添加多个指定头文件的搜索路径,路径之间用空格分隔。

 因为main.c里include了function.h和function2.h,如果没有这个命令来指定头文件所在位置,就会无法编译。当然,也可以在main.c里使用include来指定路径,如下:

#include "function/function.h"
#include "function2/function2.h"
  • 1
  • 2

这种写法不好看!

四、CMake构建:正规组织结构

首先构建一个目录树下:

  • bin文件夹:
  • build文件夹:
  • include文件夹:
  • src文件夹:
liefyuan@ubuntu:~/Desktop/cmake_dir$ tree
.
├── bin
├── build
├── include
│   ├── function2.h
│   └── function.h
└── src
    ├── function2.c
    ├── function.c
    └── main.c

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

方式一:两个CMakeLists.txt

根目录下新建一个新的CMakeLists.txt文件,内容如下:

cmake_minimum_required (VERSION 2.8)

project (demo)

add_subdirectory (src)
  • 1
  • 2
  • 3
  • 4
  • 5

src目录下也需要新建一个新的CMakeLists.txt文件,内容如下:

aux_source_directory (. SRC_LIST)

include_directories (../include)

add_executable (main ${SRC_LIST})

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 这里使用了一个新的命令set,是用于定义变量的,EXECUTABLE_OUT_PATHPROJECT_SOURCE_DIR是CMake自带的预定义变量,其意义如下,

  • EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
  • PROJECT_SOURCE_DIR:工程的根目录

所以,这里set的意思是把存放elf文件的位置设置为工程根目录下的bin目录。(cmake有很多预定义变量,详细的可以网上搜索一下)

添加好以上这2个CMakeLists.txt后,整体文件结构如下,

liefyuan@ubuntu:~/Desktop/cmake_dir$ tree
.
├── bin
├── build
├── CMakeLists.txt
├── include
│   ├── function2.h
│   └── function.h
└── src
    ├── CMakeLists.txt
    ├── function2.c
    ├── function.c
    └── main.c

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

构建,编译,运行

  • 第一步:进入build文件夹运行命令:cmake ..
  • 第二步:经过上一步,Makefile文件会在build目录下生成,然后再运行make进行编译,在根目录的bin目录下就会生成一个可执行文件make
  • 第三步:进入根目录下的bin文件里面运行可执行文件./main
liefyuan@ubuntu:~/Desktop/cmake_dir/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_dir/build
liefyuan@ubuntu:~/Desktop/cmake_dir/build$ make
Scanning dependencies of target main
[ 25%] Building C object src/CMakeFiles/main.dir/function.c.o
[ 50%] Building C object src/CMakeFiles/main.dir/function2.c.o
[ 75%] Building C object src/CMakeFiles/main.dir/main.c.o
[100%] Linking C executable ../../bin/main
[100%] Built target main
liefyuan@ubuntu:~/Desktop/cmake_dir/build$ cd ..
liefyuan@ubuntu:~/Desktop/cmake_dir$ cd bin
liefyuan@ubuntu:~/Desktop/cmake_dir/bin$ ls
main
liefyuan@ubuntu:~/Desktop/cmake_dir/bin$ ./main
para var:200
para var2:100
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

正常运行!

 为什么在build目录下运行cmake?从前面几个例子中可以看到,如果不这样做,cmake运行时生成的附带文件就会跟源码文件混在一起,这样会对程序的目录结构造成污染,而在build目录下运行cmake,生成的附带文件就只会待在build目录下,如果我们不想要这些文件了就可以直接清空build目录,非常方便。

方式二:一个CMakeLists.txt

 前面的工程使用了2个CMakeLists.txt,最外层的CMakeLists.txt用于掌控全局,使用add_subdirectory来控制其它目录下的CMakeLists.txt的运行。

 上面的例子也可以只使用一个CMakeLists.txt,把最外层的CMakeLists.txt内容改成如下:

cmake_minimum_required (VERSION 2.8)

project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

aux_source_directory (src SRC_LIST)

include_directories (include)

add_executable (main ${SRC_LIST})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

再把src目录下的CMakeLists.txt删除掉。
目录如下:

liefyuan@ubuntu:~/Desktop/cmake_dir2$ tree
.
├── bin
├── build
├── CMakeLists.txt
├── include
│   ├── function2.h
│   └── function.h
└── src
    ├── function2.c
    ├── function.c
    └── main.c

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
liefyuan@ubuntu:~/Desktop/cmake_dir2/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_dir2/build
liefyuan@ubuntu:~/Desktop/cmake_dir2/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
liefyuan@ubuntu:~/Desktop/cmake_dir2/build$ make
Scanning dependencies of target main
[ 25%] Building C object CMakeFiles/main.dir/src/function.c.o
[ 50%] Building C object CMakeFiles/main.dir/src/function2.c.o
[ 75%] Building C object CMakeFiles/main.dir/src/main.c.o
[100%] Linking C executable ../bin/main
[100%] Built target main
liefyuan@ubuntu:~/Desktop/cmake_dir2/build$ cd ..
liefyuan@ubuntu:~/Desktop/cmake_dir2$ cd bin
liefyuan@ubuntu:~/Desktop/cmake_dir2/bin$ ls
main
liefyuan@ubuntu:~/Desktop/cmake_dir2/bin$ ./main
para var:200
para var2:100
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

正常运行!

五、CMake构建:编译动态库和静态库

 CMake编译动态库和静态库也是可以的。

构建一个文件架构:

liefyuan@ubuntu:~/Desktop/cmake_lib$ tree
.
├── build
├── CMakeLists.txt
├── function
│   ├── function.c
│   └── function.h
└── lib
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在build目录下运行cmake,并把生成的库文件存放到lib目录下。

新建的CMakeLists.txt内容为:

cmake_minimum_required (VERSION 2.8)
        
project (demo)
        
set (SRC_LIST ${PROJECT_SOURCE_DIR}/function/function.c)
        
add_library (function_shared SHARED ${SRC_LIST})
add_library (function_static STATIC ${SRC_LIST})
        
set_target_properties (function_shared PROPERTIES OUTPUT_NAME "function")
set_target_properties (function_static PROPERTIES OUTPUT_NAME "function")
        
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里出现了新的命令和预定义变量:

  • add_library: 生成动态库或静态库(第1个参数指定库的名字;第2个参数决定是动态还是静态,如果没有就默认静态;第3个参数指定生成库的源文件)
  • set_target_properties: 设置最终生成的库的名称,还有其它功能,如设置库的版本号等等
  • LIBRARY_OUTPUT_PATH: 库文件的默认输出路径,这里设置为工程目录下的lib目录

进入build目录运行命令cmake ..,生成Makefile文件后再运行make

liefyuan@ubuntu:~/Desktop/cmake_lib/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_lib/build
liefyuan@ubuntu:~/Desktop/cmake_lib/build$ make
Scanning dependencies of target function_static
[ 25%] Building C object CMakeFiles/function_static.dir/function/function.c.o
[ 50%] Linking C static library ../lib/libfunction.a
[ 50%] Built target function_static
Scanning dependencies of target function_shared
[ 75%] Building C object CMakeFiles/function_shared.dir/function/function.c.o
[100%] Linking C shared library ../lib/libfunction.so
[100%] Built target function_shared
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

编译成功后,进入lib目录下查看,发现已经成功生成了动态库和静态库。

  • libfunction.a
  • libfunction.so
liefyuan@ubuntu:~/Desktop/cmake_lib/build$ cd ..
liefyuan@ubuntu:~/Desktop/cmake_lib$ cd lib
liefyuan@ubuntu:~/Desktop/cmake_lib/lib$ ls
libfunction.a  libfunction.so
  • 1
  • 2
  • 3
  • 4

 前面使用set_target_properties重新定义了库的输出名称,如果不使用set_target_properties也可以,那么库的名称就是add_library里定义的名称,只是连续2次使用add_library指定库名称时(第一个参数),这个名称不能相同,而set_target_properties可以把名称设置为相同,只是最终生成的库文件后缀不同(一个是.so,一个是.a),这样相对来说会好看点。

六、CMake构建:链接库

前面已经生成了库,现在就进行库链接。

liefyuan@ubuntu:~/Desktop/cmake_lib_link$ tree
.
├── bin
├── build
├── CMakeLists.txt
├── function
│   ├── inc
│   │   └── function.h
│   └── lib
│       ├── libfunction.a
│       └── libfunction.so
└── src
    └── main.c
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

main.c

#include <stdio.h>
#include "function.h"

int main(void)
{       
    func(300);

    return 0;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)
        
project (demo)
        
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
        
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.c)
        
include_directories (${PROJECT_SOURCE_DIR}/function/inc)
        
find_library(FUNCTION_LIB function HINTS ${PROJECT_SOURCE_DIR}/function/lib)
        
add_executable (main ${SRC_LIST})
        
target_link_libraries (main ${FUNCTION_LIB})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

新命令解释:

  • find_library: 在指定目录下查找指定库,并把库的绝对路径存放到变量里,其第一个参数是变量名称,第二个参数是库名称,第三个参数是HINTS,第4个参数是路径,其它用法可以参考cmake文档
  • target_link_libraries: 把目标文件与库文件进行链接

 使用find_library的好处是在执行cmake ..时就会去查找库是否存在,这样可以提前发现错误,不用等到链接时。

 cd到build目录下,然后运行cmake .. && make,最后进入到bin目录下查看,发现main已经生成,运行就好。

liefyuan@ubuntu:~/Desktop/cmake_lib_link/build$ cmake ..&& make
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/liefyuan/Desktop/cmake_lib_link/build
Scanning dependencies of target main
[ 50%] Building C object CMakeFiles/main.dir/src/main.c.o
[100%] Linking C executable ../bin/main
[100%] Built target main
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行:

liefyuan@ubuntu:~/Desktop/cmake_lib_link/build$ cd ..
liefyuan@ubuntu:~/Desktop/cmake_lib_link$ cd bin
liefyuan@ubuntu:~/Desktop/cmake_lib_link/bin$ ./main
para var:300
  • 1
  • 2
  • 3
  • 4

运行成功!

在lib目录下有function的静态库和动态库,find_library(FUNCTION_LIB function …默认是查找动态库,如果想直接指定使用动态库还是静态库,可以写成find_library(FUNCTION_LIB libfunction.so …或者find_library(FUNCTION_LIB libfunction.a …

七、CMake构建:添加编译选项

 有时编译程序时需要添加一些编译选项,如-Wall, -std=c++11等,就可以使用add_compile_option来进行操作。

#include <iostream>

int main(void)
{
	auto data = 100;
	std:cout << "data:" << data << "\n";
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)

project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

add_compile_options(-std=c++11 -Wall)

add_executable(main main.cpp)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

目录树如下:

liefyuan@ubuntu:~/Desktop/cmake_cpp$ tree
.
├── bin
├── build
├── CMakeLists.txt
└── main.cpp
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后cd到build目录下,执行cmake … && make命令,就可以在bin目录下得到main的elf文件

八、CMake构建:添加控制

 有时在编译代码时只编译一些指定的代码,可以使用cmake的option命令,主要遇到的情况分为2种:

  • 1.本来要生成多个bin或库文件,现在只想生成部分指定的bin或库文件
  • 2.对于同一个bin文件,只想编译其中部分代码(使用宏来控制)

情况一:


  • 1

情况二:

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号