由于我们构建一个项目的时候,通常不会将所有的源文件放在一个文件目录下,这样既不方便开发,也不方便源码阅读,我们通常会对项目文件进行分层,比如分为include、src、res、lib这些目录,src下又分为model、controller、view这些目录。所以跨文件编译C++文件就相当必要了,如果使用g++指令将这些文件统一进行编译,指令就太冗长了,就算将这些指令写成一个shell脚本,每次要添加新的目录的时候,又要对这个shell脚本进行修改,非常麻烦。Makefile可以很好解决这个问题,但是Makefile的书写还是太过复杂了,因此我们可以使用Makefile的升级版,也就是CMake来解决这一问题。
假如我们有一个test4文件夹。文件目录如右图树状图所示。
main.cpp
#include<iostream>
#include"test/test.h"
using namespace std;
int main()
{
test();
return 0;
}
test.h
#ifndef TEST_HEADER
#define TEST_HEADER
void test();
#endif
test.cpp
#include"test.h"
#include<iostream>
void test()
{
std::cout<<"hello world"<<std::endl;
}
test4目录下的CMakeLists.txt文件如下:
cmake_minimum_required(VERSION 3.0)
project(MyProject)
# 添加子目录
add_subdirectory(test)
# 生成可执行文件
add_executable(myapp main.cpp)
# 链接test目录下生成的动态库或者静态库
target_link_libraries(myapp test)
test目录下的CMakeLists.txt文件如下:
# 设置库文件
aux_source_directory(. LIB_SRCS)
add_library(test STATIC ${LIB_SRCS})
实际上CMake编译不同文件目录下C++文件的原理就是将各个目录C++文件做成链接库,然后在主目录的main.cpp下引用这些库。
我们在test4目录下创建一个build文件,用来存放CMake构建产生的中间文件。
mkdir build
cd build
cmake ..
make
./myapp
成功运行。
假如我在test目录下再创建一个sum目录呢,并且将test目录的test.h和sum.h都放到include目录下呢,剩余的.cpp文件都放在src目录下。
main.cpp代码如下,其实就是加了一个mysum函数,用来求和,就不展示sum.cpp的源码了。
#include<iostream>
#include"../include/test/test.h"
#include"../include/sum/sum.h"
using namespace std;
int main()
{
test();
cout<<mysum(1,2)<<endl;
return 0;
}
整个目录树变为下面这种形式的。
.
├── build
├── CMakeLists.txt
├── include
│ ├── sum
│ │ └── sum.h
│ └── test
│ └── test.h
└── src
├── CMakeLists.txt
├── main.cpp
└── test
├── CMakeLists.txt
├── sum
│ ├── CMakeLists.txt
│ └── sum.cpp
└── test.cpp
根目录的CMakeLists.txt就变为了这样,这里需要指定可执行文件生成的目录在build下,不然默认就是生成在build/src目录下了,不方便我们执行。
cmake_minimum_required(VERSION 3.0)
project(MyProject)
# 设置编译输出目录
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/build)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/build)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
# 包含src目录
add_subdirectory(src)
src目录下的CMake文件如下:
cmake_minimum_required(VERSION 3.0)
project(MyProject)
# 添加子目录
add_subdirectory(test)
add_subdirectory(test/sum) # 添加sum子目录
# 生成可执行文件
add_executable(myapp main.cpp)
# 链接test库
target_link_libraries(myapp test)
src/test目录下的CMake文件如下
# 设置库文件
aux_source_directory(. LIB_SRCS)
add_library(test STATIC ${LIB_SRCS})
# 链接sum库
target_link_libraries(test sum)
src/test/sum目录下的CMake文件如下
# 设置库文件
aux_source_directory(. LIB_SRCS)
add_library(sum STATIC ${LIB_SRCS})
编译项目。
cd build
cmake ..
make
可执行文件myapp直接生成在了build目录下。
成功执行。