CMake编译不同文件目录下的C++文件

        由于我们构建一个项目的时候,通常不会将所有的源文件放在一个文件目录下,这样既不方便开发,也不方便源码阅读,我们通常会对项目文件进行分层,比如分为includesrcreslib这些目录,src下又分为modelcontrollerview这些目录。所以跨文件编译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目录下。 

 

成功执行。 

 

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CMake 是一个跨平台的构建工具,可以用来编译 C++ 代码。要实现只编译更新的文件,可以使用 CMake 的自动侦测功能来判断文件是否被更改,再利用 CMake 的依赖关系来只编译需要更新的文件。 具体实现如下: 1. 在项目根目录下创建 CMakeLists.txt 文件,定义工程名称和版本号等信息。 ``` cmake_minimum_required(VERSION 3.10) project(MyProject VERSION 1.0) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) ``` 2. 定义源文件列表,并设置编译选项。 ``` # 定义源文件列表 set(SOURCES main.cpp foo.cpp bar.cpp ) # 设置编译选项 add_compile_options(-Wall -Wextra -pedantic -Werror) ``` 3. 利用 CMake 的自动侦测功能来判断文件是否被更改。这里使用 CMake 的 check_include_file_cxx 函数来检查头文件是否存在,并将结果保存到 CACHE 变量中。 ``` # 自动侦测头文件 check_include_file_cxx(filesystem HAVE_FILESYSTEM) if (NOT HAVE_FILESYSTEM) message(FATAL_ERROR "Filesystem not supported") endif() ``` 4. 利用 CMake 的依赖关系来只编译需要更新的文件。这里使用 CMake 的 add_executable 函数来定义可执行文件,并将源文件列表作为参数传递。通过 target_sources 函数来为可执行文件添加源文件,并设置依赖关系。 ``` # 定义可执行文件 add_executable(MyApp) # 添加源文件 target_sources(MyApp PRIVATE ${SOURCES}) # 设置依赖关系 add_dependencies(MyApp MyLib) # 链接库 target_link_libraries(MyApp PRIVATE MyLib) ``` 这样,当源文件列表中的某个文件被更改时,CMake 就会自动重新编译这个文件,并重新链接可执行文件。而没有更改的文件则不会被重新编译,从而提高了构建效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咩咩大主教

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值