CMake基础(2)分离编译

简介: CMake基础(2)分离编译

0x01 介绍

概念: 分离编译

首先,CMake是一种开源的构建工具,可以用于自动生成构建文件,比如Makefile和Visual Studio工程文件。它通过一个名为CMakeLists.txt的配置文件来描述项目的构建过程。用户可以使用CMake来生成构建文件,然后使用其他工具来编译和链接项目。其次,CMake支持多种语言,包括C++、C、Fortran、Python等。它的目的是为了消除编译环境的差异,使用户能够在多种平台上轻松构建项目。最后,CMake支持分离编译,即将源文件和中间文件存放在不同的目录中。这样做的好处是可以更好地管理源文件和中间文件,并且可以更方便地进行多次编译。

在CMake中,"分离编译"指的是将源文件和中间文件存放在不同的目录中。这样做的好处是可以更好地管理源文件和中间文件,并且可以更方便地进行多次编译。

概念: CMake变量

CMake 语法指定了许多变量,这些变量可用于帮助在项目或源代码树中找到有用的目录。其中一些包括:

变量

信息

CMAKE_SOURCE_DIR

根源目录

CMAKE_CURRENT_SOURCE_DIR

如果使用子项目和目录,则为当前源目录。

PROJECT_SOURCE_DIR

当前 cmake 项目的源目录。

CMAKE_BINARY_DIR

根二进制文件生成目录。这是运行 cmake 命令的目录。

CMAKE_CURRENT_BINARY_DIR

你当前所处的生成目录。

PROJECT_BINARY_DIR

当前项目的生成目录。

概念: 详细输出调试

在前面的示例中,当运行 make 命令时,输出仅显示构建的状态。要查看用于调试目的的完整输出,可以在运行 make 时添加 VERBOSE=1 标志。

VERBOSE 输出如下所示。可以看到,include 目录已经被添加到了编译命令中。

0x02 示例

展示一个 hello world 示例,它使用不同的文件夹来存储源文件和头文件。

本教程中的文件包括:

 
ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_02$ tree
.
├── CMakeLists.txt
├── include
│   └── hello.h
└── src
    ├── hello.cpp
    └── main.cpp
 
2 directories, 4 files

CMake 中包含头文件的方式有多种,下面是一个示例:首先,我们创建一个 "include" 目录,用于存放头文件:

然后,在 "include" 目录中创建一个头文件,例如 "hello.h":

#include "hello.h"
 
void print_hello()
{
    std::cout << "Hello, World!" << std::endl;
}

接着,在 "src" 目录中创建一个源文件,例如 "hello.cpp":

#include "hello.h"
 
void print_hello()
{
    std::cout << "Hello, World!" << std::endl;
}

然后,在 "src" 目录中创建一个主函数文件,例如 "main.cpp":

#include "hello.h"
 
int main()
{
    print_hello();
    return 0;
}

接下来,我们需要使用 CMake 来构建项目。首先,在项目根目录下创建一个 "CMakeLists.txt" 文件:

cmake_minimum_required(VERSION 3.10)
project(hello)
 
# 设置 C++ 编译器选项
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
 
# 指定C++编译器
set(CMAKE_CXX_COMPILER /usr/bin/g++)
 
# 添加头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)
 
 
# 指定源文件目录
set(CMAKE_SOURCE_DIR src/hello.cpp src/main.cpp)
 
 
# 添加源文件
add_executable(hello ${CMAKE_SOURCE_DIR})
 
 
 
#-------------------------------不行
#target_include_directories(hello
#    PRIVATE 
#    ${PROJECT_SOURCE_DIR}/include
#)
#file(GLOB CMAKE_SOURCE_DIR  "src/*.cpp") 
#-------------------------------

最后,执行cmake ../ && make -j24 VERBOSE=1

ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_02/build$ cmake ../ && make -j24 VERBOSE=1
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/Project/Cmake_examples/cmake_basics_02/build
/usr/bin/cmake -S/mnt/d/Project/Cmake_examples/cmake_basics_02 -B/mnt/d/Project/Cmake_examples/cmake_basics_02/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles /mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_02/build'
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/depend
make[2]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_02/build'
cd /mnt/d/Project/Cmake_examples/cmake_basics_02/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /mnt/d/Project/Cmake_examples/cmake_basics_02 /mnt/d/Project/Cmake_examples/cmake_basics_02 /mnt/d/Project/Cmake_examples/cmake_basics_02/build /mnt/d/Project/Cmake_examples/cmake_basics_02/build /mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles/hello.dir/DependInfo.cmake --color=
Dependee "/mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles/hello.dir/DependInfo.cmake" is newer than depender "/mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles/hello.dir/depend.internal".
Dependee "/mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles/hello.dir/depend.internal".
Scanning dependencies of target hello
make[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_02/build'
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/build
make[2]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_02/build'
[ 33%] Building CXX object CMakeFiles/hello.dir/src/hello.cpp.o
/usr/bin/g++   -I/mnt/d/Project/Cmake_examples/cmake_basics_02/include  -std=c++11 -o CMakeFiles/hello.dir/src/hello.cpp.o -c /mnt/d/Project/Cmake_examples/cmake_basics_02/src/hello.cpp
[ 66%] Building CXX object CMakeFiles/hello.dir/src/main.cpp.o
/usr/bin/g++   -I/mnt/d/Project/Cmake_examples/cmake_basics_02/include  -std=c++11 -o CMakeFiles/hello.dir/src/main.cpp.o -c /mnt/d/Project/Cmake_examples/cmake_basics_02/src/main.cpp
[100%] Linking CXX executable hello
/usr/bin/cmake -E cmake_link_script CMakeFiles/hello.dir/link.txt --verbose=1
/usr/bin/g++     CMakeFiles/hello.dir/src/hello.cpp.o CMakeFiles/hello.dir/src/main.cpp.o  -o hello
make[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_02/build'
[100%] Built target hello
make[1]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_02/build'
/usr/bin/cmake -E cmake_progress_start /mnt/d/Project/Cmake_examples/cmake_basics_02/build/CMakeFiles 0


相关文章
|
编解码 Linux 编译器
使用 C++ 方式实现 GBK 到 UTF-8 转码 (win / linux)
使用 C++ 的方式处理在 Windows 平台和 Linux 平台,编码字符集从 GBK 到 UTF-8 转码,C++ 存在多种方式实现
4213 1
|
JavaScript
Vue中的v-for中:key是必须的吗?为什么?
Vue中的v-for中:key是必须的吗?为什么?
762 0
|
Linux API C++
【C++ 17 新特性 文件管理】探索C++ Filesystem库:文件和目录操作的全面指南(一)
【C++ 17 新特性 文件管理】探索C++ Filesystem库:文件和目录操作的全面指南
3165 3
|
7月前
|
存储 监控 算法
Java程序员必学:JVM架构完全解读
Java 虚拟机(JVM)是 Java 编程的核心,深入理解其架构对开发者意义重大。本文详细解读 JVM 架构,涵盖类加载器子系统、运行时数据区等核心组件,剖析类加载机制,包括加载阶段、双亲委派模型等内容。阐述内存管理原理,介绍垃圾回收算法与常见回收器,并结合案例讲解调优策略。还分享 JVM 性能瓶颈识别与调优方法,分析 Java 语言特性对性能的影响,给出数据结构选择、I/O 操作及并发同步处理的优化技巧,同时探讨 JVM 安全模型与错误处理机制,助力开发者提升编程能力与程序性能。
Java程序员必学:JVM架构完全解读
|
缓存 架构师 Java
图解 Spring 循环依赖,一文吃透!
Spring 循环依赖如何解决,是大厂面试高频,本文详细解析,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
图解 Spring 循环依赖,一文吃透!
|
编译器 C++
#include<> 与#include ""的区别
在C++中,`#include &lt;&gt;` 和 `#include &quot;&quot;` 都用于包含头文件,但使用场景不同。`#include &lt;&gt;` 用于包含系统标准库头文件,编译器会在标准库路径中查找;而 `#include &quot;&quot;` 用于包含用户自定义的头文件,编译器会优先在当前项目目录中查找。
|
分布式计算 算法 大数据
探索操作系统的核心:调度与内存管理机制
【10月更文挑战第11天】 本文深入探讨了操作系统中两大核心功能——调度与内存管理机制。通过分析调度算法、进程状态转换及内存分配策略等关键方面,揭示了它们如何共同维护系统性能和稳定性。旨在为读者提供对操作系统内部运作的深刻理解,同时引起对优化策略的思考。
388 5
|
SQL 分布式计算 Java
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
279 0
|
设计模式 Java 调度
SpringBoot 事件发布监听机制使用、分析、注意点 (一篇到位)
SpringBoot 事件发布监听机制使用、分析、注意点 (一篇到位)
1910 1
SpringBoot 事件发布监听机制使用、分析、注意点 (一篇到位)
|
存储 安全 编译器
C++ std::move以及右值引用全面解析:从基础到实战,掌握现代C++高效编程
C++ std::move以及右值引用全面解析:从基础到实战,掌握现代C++高效编程
933 1