cmake基础

参考《视觉SLAM十四讲》。

1、第一个cmake

在~目录下新建一个Test文件夹,里面创建Helloworld.cpp和CMakeLists.txt两个文件。
Helloworld.cpp

#include  <iostream>
using namespace std;
int main( int argc, char** argv )
{
 	cout<<"Hello world!"<<endl;
 	return 0;
}

CMakeLists.txt

# 声明要求的 cmake 最低版本
cmake_minimum_required(VERSION 2.8)
# 声明一个 cmake 工程
project( Hello )
# 添加一个可执行程序
# 语法: add_executable( 程序名 源代码文件 )
add_executable( test Helloworld.cpp )

在当前目录~/Test下

cmake .
make
./test

2、加入build文件夹

cmake 生成的中间文件还留在我们代码文件当中。当我们想要发布代码时,并不希望把这些中间文件一同发布出去。这时我们还需把它们一个个删除,这十分的不便。一种更好的做法是让这些中间文件都放在一个中间目录中,在编译成功后,把这个中间目录删除即可。所以,更常见的编译 cmake 工程的做法就是这样:

mkdir build
cd build
cmake ..
make

新建了一个中间文件夹“build”,然后进入 build 文件夹,通过 cmake ..命令,对
上一层文件夹,也就是代码所在的文件夹进行编译。这样, cmake 产生的中间文件就会生成在 build 文件夹中,与源代码分开。当发布源代码时,只要把 build 文件夹删掉即可。

3、使用库

3.1、生成库

在一个 C++ 工程中,并不是所有代码都会编译成可执行文件。只有带有 main 函数的文件才会生成可执行程序。而另一些代码,我们只想把它们打包成一个东西,供其他程序调用。这个东西叫做
要学习如何用 cmake 生成库,并且使用库中的函数。
写一个库文件:
libHello.cpp

 //这是一个库文件
#include <iostream>
using namespace std;
void PrintHello()
{
  cout<<"Hello world"<<endl;
}

这个库提供了一个 printHello 函数,调用此函数将输出一个信息。但是它没有 main函数,这意味着这个库中没有可执行文件。在 CMakeLists.txt 里加一句:

add_library( hello libHello.cpp )

这条命令告诉 cmake,我想把这个文件编译成一个叫做“hello”的库。
编译后,在 build 文件夹中会生成一个 libhello.a 文件,这就是我们得到的库。
在 Linux 中,库文件分成静态库共享库两种。静态库以.a 作为后缀名,共享库以.so结尾。所有库都是一些函数打包后的集合。
差别在于:静态库每次被调用都会生成一个副本,即编译的时候,会把库也复制一份到程序中,最后导致程序很大,但是执行空间下不再需要库文件;而共享库只在链接和程序执行的时候使用,并不会把库编译到程序中,使得最后得到的可执行程序更小,但执行空间下需要有库文件。如果想生成共享库而不是静态库,只需用:

add_library( hello_shared SHARED libHello.cpp )

此时得到的文件是 libhello_shared.so 。

3.2、使用库

库文件是一个压缩包,里头带有编译好的二进制函数。不过,仅有.a 或.so库文件的话,我们并不知道它里头的函数到底是什么,调用的形式又是什么样的。也就是说,没有.h文件,并不知道相应的.cpp中有什么函数;同时,匹配的.h可以作为调用这个库的入口,否则你怎么知道调用了哪个库的哪些文件。为了让别人(或者自己)使用这个库,我们需要提供一个头文件,说明这些库里都有些什么。因此,对于库的使用者, 只要拿到了头文件和库文件,就可以调用这个库了。
libHello.h

#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_

void printHello();
#endif

写一个可执行程序,调用这个简单的函数:
main.cpp

#include "libHello.h"
int main( int argc, char** argv )
{
  PrintHello();
  return 0;
}

然后,在 CMakeLists.txt 中添加一个可执行程序的生成命令,链接到刚才使用的库上:

add_executable(test1 main.cpp)

target_link_libraries(test1 hello_shared)

通过这两句话, main 程序就能顺利使用 hello_shared 库中的代码了。

3.3、小结
①使用库

如果生成库,则add_executable()中只用放main()函数文件,其他文件生成库,再链接库。所以顺序为:先把其他文件生成库,再target_link_libraries()链接该库。但是得把生成库和链接库放在一次cmake、make操作中。如果该一次操作中不生成库,而直接链接早已生成的库,需要把之前生成的库放在相应的路径下链接,还需要命令,find_package()

此时,CMakeLists.txt是这样的:

# 声明要求的 cmake 最低版本
cmake_minimum_required(VERSION 2.8)
# 声明一个 cmake 工程
project( Hello )

add_library( hello libHello.cpp )

add_library( hello_shared SHARED libHello.cpp )

add_executable(test main.cpp)

target_link_libraries(test hello_shared)

②不用库

如果不生成和链接库,则把所有文件都放到add_executable()中。

此时,CMakeLists.txt是这样的:

# 声明要求的 cmake 最低版本
cmake_minimum_required(VERSION 2.8)
# 声明一个 cmake 工程
project( Hello )

add_executable( test main.cpp  libHello.cpp)

add_executable()中不需要放.h文件,或者说,CMakeLists.txt中不需要包含.h文件。
这里把PrintHello()函数的声明放在.h中,定义放在.cpp中。如果上面的CMakeLists.txt是

add_executable( test main.cpp  libHello.h)#不是.cpp

会提示找不到PrintHello()函数的定义。
如果把PrintHello()函数的声明和定义都放在libHello.h中,你甚至可以这么写:

add_executable( test main.cpp)

只需要在main.cpp中

#include "libHello.h"

就可以调用libHello.h中的函数。
此时libHello.h

#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_
#include <iostream>
using namespace std;
void PrintHello();
#endif

void PrintHello()
{
  cout<<"Hello world"<<endl;
}

这也是一种讨巧的办法。即把函数的声明和定义都写在.h文件中,那么调用的时候,只要在主函数文件中#include相应的函数的文件即可,cmakelist和makelist中都不需要包括.h文件。
但是这么做也有一个弊端,容易造成文件混乱,因为我们一般习惯把函数声明放在.h中,定义放在.cpp中。而且也没有办法把调用的函数封装成库。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值