之前学习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(<dir> <variable>)
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 <min> value or use a ...<max> 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 <iostream>
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的引用格式。