CMake多文件编译

之前学习ceres-solver中的3d相关的源码的时候,发现对于CMake多文件工程编译中对于CMakeLists.txt的编写和处理的理解运用还是比较模糊,这里整理梳理一下对于不同文件夹数量如何使用。

参考文章:

CMake使用详解二(多文件编译)_刘凯数据分析的博客-CSDN博客_cmake 多文件编译

1.同一文件夹下,多cpp文件

tree如下所示:

.
└── test1
    ├── add.cpp
    ├── add.hpp
    ├── CMakeLists.txt
    └── main.cpp

其中的源码为:

//add.h
#include "iostream"

using namespace std;

int add1(int a, int b);

//add.cpp
#include "add.hpp"

int add1(int i, int j)
{
    return i + j;
}

//main.cpp
#include "add.hpp"

int main()
{
    cout << add1(1, 10) << endl;
    return 0;
}

CMakeLists.txt如下所示:

cmake_minimum_required(VERSION 2.8)
project(add)

add_executable(add1 main.cpp add.cpp)

2.同一文件夹下,超多cpp文件

如果文件夹下有很多cpp文件5个以上,这样一个个打不方便,可以在CMakeLists.txt中输入命令:

aux_source_directory

aux_source_directory( )

1中使用aux_source_directory如下:

cmake_minimum_required(VERSION 2.8)
project(add)
aux_source_directory(. ALL_SRCS)
add_executable(add1 ${ALL_SRCS})

同样编译可以通过。

CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument  value or use a ... suffix to tell
  CMake that the project does not need compatibility with older versions.


-- Configuring done
-- Generating done
-- Build files have been written to: /home/hhh/test-folder/cmake-test/test1/build
Consolidate compiler generated dependencies of target add1
[ 33%] Building CXX object CMakeFiles/add1.dir/main.cpp.o
[ 66%] Linking CXX executable add1
[100%] Built target add1

3.不同文件夹下

tree如下所示:

.
├── add
│   ├── add.cpp
│   ├── add.hpp
│   └── CMakeLists.txt
├── CMakeLists.txt
└── main.cpp

其中所有的源码如下:

//   add/add.hpp
#include 
using namespace std;

int add1(int i, int j);

//   add/add.cpp
#include "add.hpp"

int add1(int i, int j)
{
    return i + j;
}

//   main.cpp
#include "add/add.hpp"

int main()
{
    cout << add1(10, 1) << endl;
    return 0;
}

最外层的CMakeLists.txt文件:

cmake_minimum_required(VERSION 2.8)
project(add1)

aux_source_directory(. ALL_SRCS)
add_subdirectory(add)
add_executable(add1 ${ALL_SRCS})
target_link_libraries(add1 add2)

分析:

add_subdirectory(add)

是将指明本项目包含一个子目录 add,这样 add 目录下的 CMakeLists.txt 文件和源代码也会被处理 。

通过编译运行后,在build文件夹下,就会出现一个add文件夹:

里面有:

 就是add文件夹的静态库。

target_link_libraries(add1 add2)

指明可执行文件 add1 需要连接一个名为 add2 的链接库 。

然后在add文件夹中CMakeLists.txt文件:

aux_source_directory(. LIB_SRCSSSSS)
add_library(add2 ${LIB_SRCSSSSS})
add_library(add2 ${LIB_SRCSSSSS})

是将当前目录下的工作生成一个静态库,库名为add2。

 这里还有一个命令:

include_directories()

这篇文章写的很详细:

include_directories和find_package_天锡的博客-CSDN博客_include_directories

4.另一形式

tree如下:

.
├── add
│   └── add.h
├── CMakeLists.txt
└── main
    ├── add.cpp
    └── main.cpp

参考文章:

cmake构建多目录项目_今年不吃饭...的博客-CSDN博客_cmake 创建目录

根据这个文章修改tree:

.
├── add
│   ├── add.h
│   └── CMakeLists.txt
├── CMakeLists.txt
└── main
    ├── add.cpp
    └── main.cpp

然后就出现了很多有意思的错误,经过一些列的尝试后发现,不能在.h文件里面写CMakeLists.txt文件,得修改成这个样子:

.
├── add
│   └── add.h
├── CMakeLists.txt
└── main
    ├── add.cpp
    ├── CMakeLists.txt
    └── main.cpp

其中main文件夹中的CMakeLists.txt应该这样写:

include_directories(../add)
add_library(add2 add.cpp)

主要作用是读取add.h头文件的内容,并添加add2的静态库。

最外层的CMakeLists.txt文件应该这样写:

cmake_minimum_required(VERSION 2.8)
project(main)


set(DIR_SRCS ./main/main.cpp)
add_subdirectory(main)
add_executable(add1 ${DIR_SRCS})
target_link_libraries(add1 add2)

set命令直接指向了最后的main.cpp文件,然后将main文件夹加入cmake编译路径,生成add1可执行文件,给add1链接上add2的库。

重点是main.cpp的内容:

#include "../add/add.h"

int main()
{
    cout << add1(1, 12222);
    return 0;
}

头文件必须采用相对地址,才能编译通过。

5.再次编译ceres-slover中3d-pose工程文件

参考文章:

cmake--多级目录工程 - 流浪侠客 - 博客园

tree:

.
├── common
│   └── read_g2o.h
└── pose_graph_3d
    ├── CMakeLists.txt
    ├── plot_results.py
    ├── pose_graph_3d.cc
    ├── pose_graph_3d_error_term.h
    ├── README.md
    └── types.h

然后这里的CMakeLists.txt文件的内容:

cmake_minimum_required(VERSION 2.8)
project(addd)
include_directories(../common)

find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})

aux_source_directory(. ALL_SRCS)
add_executable(pose3d ${ALL_SRCS} )

target_link_libraries(pose3d  ${CERES_LIBRARIES})

target_include_directories( pose3d
 PUBLIC ../common
)

因为这个里面pose_graph_3d.cc里面使用了common文件夹内的read_g2o.h。所以要使用include_directories()和target_include_directories()这里面PUBLIC是必须命令把它加入,如果生成了库的话,可以在common里面写一个CMakeLists.txt里面生成库,然后把库加入到这个CMakeLists.txt文件里面。

之后就编译通过了,注意pose_graph_3d.cc里面read_g2o.h的引用格式。

你可能感兴趣的:(ubuntu,cmake,c++,开发语言)