如何为具有多个子目录的大项目编写“CMakeLists.txt”?

时间:2017-11-07 16:23:16

标签: c linux makefile cmake codelite

我正在开展一个模拟项目:从目标平台获取嵌入式C 代码库,并尝试在主机上模拟它以进行调试或单步执行代码。

OS:Ubuntu Linux 14.04,IDE:CodeLite,Makefile Generator: Cmake 。我对如何为项目编写 CMakeLists.txt 感到困惑。以下是代码库的结构(全部用 C 编写):

|ARQSim\  
|-->ARQSim.h  
|-->ARQSim.c  
|-->BaseStationCode\  
|   |->downlink.c  
|   |->neoncopy.c  
|   |->armCore\  
|   |  |->common\  
|   |  |  |->Bsconfig.h  
|   |  |  |->config.h  
|   |  |->MacSource\  
|   |  |  |->lib\  
|   |  |  |  |->arqCommon.h  
|   |  |  |  |->OverTheAir.h  
|   |  |  |->source\  
|   |  |  |  |->beacon.c  
|   |  |  |  |->proxyDhcp.c  
|   |  |  |  |->ARQ\  
|   |  |  |  |  |->arqCommon.c  
|   |  |  |  |  |->arqInterface.c  
|   |  |  |  |  |->fragmentation\  
|   |  |  |  |  |  |->fragBookkeeping.c  
|   |  |  |  |  |  |->fragProcessAck.c  
|   |  |  |  |  |->reassembly\  
|   |  |  |  |  |  |->reasmBookkeeping.c  
|   |  |  |  |  |  |->reasmProcessAck.c

我对Cmake完全不熟悉。我在StackOverflow上读了很多关于CMake和线程的资源。但我每次都感到困惑。我几乎没有问题:

  1. 我是否只需要在根目录下有一个CMakeLists.txt,或者每个目录都需要一个不同的CMakeLists.txt文件?
  2. 如何在CMakeLists.txt中递归添加源文件?
  3. 我需要在CMakeLists.txt中为MakeFile生成添加哪些基本命令?
  4. 基于上述代码结构的示例将不胜感激。

1 个答案:

答案 0 :(得分:13)

  

我是否只需要在根目录下有一个CMakeLists.txt,或者每个目录都需要不同的CMakeLists.txt文件?

您通常会在树的每个级别都有一个 ,这是有意义的

例如:

root/
+--- CMakeLists.txt             // your root CMakeLists
+--- foo/
|    +--- CMakeLists.txt        // foo component's CMakeLists
|    +--- foo.c
|    +--- tests/
|         +--- CMakeLists.txt   // foo test's CMakeLists
|         +--- foo_tests.c
+--- bar/
     +--- CMakeLists.txt        // bar component's CMakeLists
     +--- bar.c
     +--- bar_impl/             // no CMakeLists for this dir, it is part of bar
     |    +--- bar_impl.c
     +--- tests/
          +--- CMakeLists.txt   // bar test's CMakeLists
          +--- bar_tests.c

项目根CMakeLists.txt:

在您的项目根CMakeLists.txt中,您指定了最小cmake要求,项目名称,并包含其中包含各种组件的子目录

<强> root/CMakeLists.txt

cmake_minimum_required (VERSION 3.5)
project (my_project C)

add_subdirectory(foo)
add_subdirectory(bar)

组件CMakeLists.txt:

然后在每个组件子目录中,您有另一个CMakeLists.txt文件,您可以在其中添加库,可执行文件等

<强> root/foo/CMakeLists.txt

add_library(foo foo.c)
target_include_directories(foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

add_subdirectory(tests)

<强> root/foo/tests/CMakeLists.txt

add_executable(foo_test foo_tests.c)
target_link_libraries(foo_test foo)

你可以按照这种结构进行吧等等......

<强> root/foo/CMakeLists.txt

add_library(bar 
    bar.c 
    bar_impl/bar_impl.c)
target_include_directories(bar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(bar foo)

add_subdirectory(tests)

<强> root/bar/tests/CMakeLists.txt

add_executable(bar_test bar_tests.c)
target_link_libraries(bar_test bar)

生成构建文件:

要引导构建,请将cmake指向root/CMakeLists.txt

cd root
mkdir build
cd build
cmake ..

(或使用ide的构建管理器生成其构建配置)

进一步阅读

有关我在此处使用的各种功能的详细信息,请参阅文档:

最后,回答你的第二个问题:

  

如何在CMakeLists.txt中递归添加源文件?

不建议这样做(有关详细信息,请参阅this discussion)。

最好明确列出要包含在目标中的每个文件。

请注意,如果源文件位于多个单独的目录中,但它们都属于同一逻辑目标,则每个目录不需要CMakeLists.txt文件 - 只需列出文件名中的子目录< / p>

示例:

foo/
+--- foo.c
+--- bar.c
+--- baz/
     +--- baz.c
     +--- bang.c

如果您想要所有上述文件的单个目标foo,您可以按如下方式创建它:

add_library(foo 
   foo.c
   bar.c
   baz/baz.c
   baz/bang.c)

或者,如果您真的想使用变量来存储SRCS

的列表
set(SRCS 
   foo.c
   bar.c
   baz/baz.c
   baz/bang.c)

add_library(foo ${SRCS})