首先,对于最简单的,把一个cpp文件编译成一个可执行文件,需要对CMakeLists.txt中写入如下三步内容:
#声明Cmake的最低版本
cmake_minimum_required( VERSION 3.0)
#声明一个cmake工程
project( Hello )
#添加一个可执行程序
add_executable( Hello hello.cpp)
所以最简单的就是三步,1.声明最低版本,2.声明cmake工程,3.添加可执行程序。
但是如果要使用库函数,那么就不是这么简单了。
首先我们先简述一下需要了解库的文件结构。
大部分库都是这样的结构,头文件和cpp文件同名,但是不互相用include关联。一个放函数的声明,一个放函数的具体定义。
举例来说:
有一个函数print_hello()的定义放在libhello.cpp中,print_hello()的声明放在libhello.h中,库的头文件和库的cpp文件没有互相关联。
这时候我想写一个主函数main.cpp,其中想调用print_hello()这个函数,该怎么办?
当然,得把库libhello.h给include进来。
这时候就有一个问题,主函数main.cpp虽然include了libhello.h,但是这个头文件里只是声明了一下void print_hello(),并没有介绍print_hello()到底是怎么运作的,具体怎么运作放在libhello.cpp文件中。而主函数并没有#include"libhello.cpp",因此,main.cpp编译成的可执行文件是缺东西的,一定不能正常工作(缺print_hello()的内容,目前只有一个声明)。
那么libhello.cpp和main.cpp如何建立联系呢?
这个建立联系的中介,就是可执行文件。
对于这个,有两种方式:
第一种比较简单和直观,直接在add_executable的时候,把两个cpp文件都add进来。
#声明Cmake的最低版本
cmake_minimum_required( VERSION 3.0)
#声明一个cmake工程
project( Hello )
#添加一个可执行程序
add_executable( Hello main.cpp libhello.cpp)
第二种,需要把libhello.cpp打包成一个library,然后把library链接到可执行文件上。
目前的脉络是这样:
所以这种情况下,应该这么写CMakeLists.txt:
cmake_minimum_required( VERSION 3.0)
project( Hello_project )
add_executable( Hello main.cpp )
add_library( hello_library libhello.cpp)
target_link_libraries( Hello hello_library)
因此有如下几点特点:
1.头文件不在cmakelist中出现
2.声明cmake版本,再声明工程
3.主函数做成执行文件
4.cpp文件做成library
5.library链接到执行文件上
除此之外,还有几点内容值得学习一下:
第一,头文件最好写成如下形式:
#ifndef __XXX_H
#define __XXX_H
头文件内容
#endif
其中,__XXX_H也是宏,它不是头文件名,不过习惯上把这个宏定义成跟头文件名相似或一样。(不一样也是可以的!)
这个宏主要是用于编译的时候避免重复include同一头文件而出现一些额重复定义/声明的问题。
第二,正常来说,只有在add_library以后生成的hello_library,才能称它为“库”。再把库再链接到可执行文件上。我前面所述“库的头文件和库的cpp文件”主要是为了方便读者理解。
第三,在add_library的时候,有两种方式,一种是静态库,一种是动态库。静态库以.a为后缀,共享库以.so为后缀。
二者的差别在于:静态库每次调用会生成一个副本,共享库只有一个副本。
如果想用共享库,在add_library的语句中,库名 和 cpp文件 之间,加一个SHARED即可。
像这样:
add_library( hello_library SHARED libhello.cpp)
以上是第二种方式。
这一节的内容相当于是做了一个简单的实例,让人明白Cmake的基本用法。