cmake:不同目录下多个源文件

1060 篇文章 295 订阅

一般来说,当程序文件比较多时,我们会进行分类管理,把代码根据功能放在不同的目录下,这样方便查找。那么这种情况下如何编写CMakeLists.txt呢?

实验

实验一

我们把之前的源文件整理一下(新建2个目录test_func和test_func1),整理好后整体文件结构如下:
在这里插入图片描述

修改CMakeLists.txt

cmake_minimum_required (VERSION 2.8)

project (demo)

# 向工程添加多个指定头文件的搜索路径,路径之间用空格分隔
include_directories (test_func test_func1)

#使用aux_source_directory把当前目录下的源文件存列表存放到变量SRC_LIST里
aux_source_directory (test_func SRC_LIST)
aux_source_directory (test_func1 SRC_LIST1)

add_executable (${PROJECT_NAME} main.c ${SRC_LIST} ${SRC_LIST1})

  • 这里出现了一个新的命令:include_directories。该命令是用来向工程添加多个指定头文件的搜索路径,路径之间用空格分隔。
    • (方法一)因为main.c里include了testFunc.h和testFunc1.h,如果没有include_directories命令来指定头文件所在位置,就会无法编译。
    • (方法二,不推荐)如果不适用如果没有include_directories命令,可以在main.c里使用include来指定路径。如下
#include "test_func/testFunc.h"
#include "test_func1/testFunc1.h"
  • 另外,我们使用了2次aux_source_directory,因为源文件分布在2个目录下,所以添加2次

优化:正规一点的组织结构

正规一点来说,一般会把源文件放到src目录下,把头文件放入到include文件下,生成的对象文件放入到build目录下,最终输出的elf文件会放到bin目录下,这样整个结构更加清晰。

让我们把前面的文件再次重新组织下,
在这里插入图片描述

main.c内容如下:

#include <stdio.h>

#include "testFunc.h"
#include "testFunc1.h"

int main(void)
{
    func(100);
    func1(200);

    return 0;
}

testFunc.c内容如下:

/*
** testFunc.c
*/

#include <stdio.h>
#include "testFunc.h"

void func(int data)
{
    printf("data is %d\n", data);
}

testFunc1.c内容如下:

/*
** testFunc1.c
*/

#include <stdio.h>
#include "testFunc1.h"

void func1(int data)
{
    printf("data is %d\n", data);
}

testFunc.h内容如下:

/*
** testFunc.h
*/

#ifndef _TEST_FUNC_H_
#define _TEST_FUNC_H_

void func(int data);

#endif

testFunc1.h内容如下:

/*
** testFunc1.h
*/

#ifndef _TEST_FUNC1_H_
#define _TEST_FUNC1_H_

void func1(int data);

#endif

实验一

操作

当前项目路径如下:
在这里插入图片描述

(1)最外层目录CMakeLists.txt内容如下

cmake_minimum_required (VERSION 2.8)

project (demo)


set(SOURCES
        src/testFunc.c
        src/testFunc1.c
        src/main.c
        )


add_executable(${PROJECT_NAME} ${SOURCES})


target_include_directories(${PROJECT_NAME}
        PRIVATE
        ${PROJECT_SOURCE_DIR}/include
        )

(2)构建并说明

执行下面命令:

$ cd build/
$ cmake ..
$ make
$ ./demo

在这里插入图片描述

理论:CMakeLists.txt说明

(1)源文件变量

  • 创建包含源码文件的变量可使你更清楚地了解这些文件,并轻松将其添加到多个命令中,例如,add_executable()功能。(不推荐的写法)
set(SOURCES
        src/testFunc.c
        src/testFunc1.c
        src/main.c
        )


add_executable(${PROJECT_NAME} ${SOURCES})
  • Note:另一种替代方案是使用 GLOB 命令使用通配符模式匹配查找文件
file(GLOB SOURCES "src/*.c")

add_executable(${PROJECT_NAME} ${SOURCES})
  • 对于现代的CMake,不建议对源代码使用变量,通常直接在add_xxx函数中声明源代码。也就是建议写成:
add_executable(${PROJECT_NAME} 
	    src/testFunc.c
        src/testFunc1.c
        src/main.c
)

(2)头文件目录

  • 当你有不同的头文件目录时,可以使用target_include_directories()函数让编译器知道它们编译此目标时,会将这些目录添加到带有-i标志的编译指令中,例如-i/directory/path
target_include_directories(target
    PRIVATE
        ${PROJECT_SOURCE_DIR}/include
)
  • PRIVATE标识符指定include的范围,这对库很重要,这些内容将在下一节中进行说明

(3)目录路径

  • 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目录已经被添加到了编译命令中。

$ make clean

$ make VERBOSE=1

在这里插入图片描述

实验二

项目结构如下
在这里插入图片描述
(1)最外层录下CMakeLists.txt,内容如下,

cmake_minimum_required (VERSION 2.8)

project (demo)

add_subdirectory (src)

这里出现一个新的命令add_subdirectory()

  • 这个命令可以向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置
  • 这里指定src目录下存放了源文件,当执行cmake时,就会进入src目录下去找src目录下的CMakeLists.txt
  • 所以在src目录下也建立一个CMakeLists.txt

(2)src/CMakeLists.txt 内容如下

#include_directories (../include)
include_directories (${PROJECT_SOURCE_DIR}/include)

aux_source_directory (. SOURCES)
add_executable (${PROJECT_NAME}  ${SOURCES})

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
  • 命令set,是用于定义变量的。
  • EXECUTABLE_OUT_PATH和PROJECT_SOURCE_DIR是CMake自带的预定义变量,其意义如下,
    • EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
    • PROJECT_SOURCE_DIR:工程的根目录

所以,这里set的意思是把存放elf文件的位置设置为工程根目录下的bin目录。

运行cmake

  • 先我们切到build目录下,然后输入以下命令,cmake ..,Makefile会在build目录下生成,然后在build目录下运行make

在这里插入图片描述

  • 运行ok,我们再切到bin目录下,发现main已经生成,并运行测试,

在这里插入图片描述

测试OK!

这里解释一下为什么在build目录下运行cmake?

  • 从前面几个case中可以看到,如果不这样做,cmake运行时生成的附带文件就会跟源码文件混在一起,这样会对程序的目录结构造成污染
  • 而在build目录下运行cmake,生成的附带文件就只会待在build目录下,如果我们不想要这些文件了就可以直接清空build目录,非常方便。

两种结构对比:

  • 对于实验一:只生成一个elf文件,推荐使用这种结构
  • 对于实验二:这种写法是为了处理需要生成多个elf文件的情况,最外层的CMakeLists.txt用于掌控全局,使用add_subdirectory来添加要生成elf文件的源码目录。

总结

命令总结:

命令说明示例
include_directories该命令是用来向工程添加多个指定头文件的搜索路径,路径之间用空格分隔include_directories (../include)
add_subdirectory()向当前工程添加存放源文件的子目录add_subdirectory (src)
set用于定义变量的set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

CMake自带的预定义变量总结:

示例说明
EXECUTABLE_OUTPUT_PATH目标二进制可执行文件的存放位置
PROJECT_SOURCE_DIR工程的根目录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值