承接上文 cmake-外部库的导入引出的问题:假设有这样一个需求,一个大型工程的编译中,不仅要有可执行程序生成,而且还有动态库的生成,或者说构建一个sdk。显然就会涉及子模块的编译问题,接下来我们将要解决这个问题。
文章目录
目录结构
|-- bin
|-- build
|-- CMakeLists.txt
|-- inc
| |-- apple.h
| |-- orange.h
| `-- pear.h
|-- lib
`-- src
|-- apple
| |-- apple.c
| `-- CMakeLists.txt
|-- CMakeLists.txt
|-- main.c
|-- orange
| |-- CMakeLists.txt
| `-- orange.c
`-- pear
|-- CMakeLists.txt
`-- pear.c
目录结构说明
bin目录用来存放生成的可执行文件
lib目录用来存放生成的动态库文件
src目录下有三个子目录 apple、pear、orange,本文中假设这三个水果子模块即为三个对应的so库;同时main.c将调用每个子模块中的函数生成一个可执行文件fruit。
功能说明
apple.c
#include <stdio.h>
void apple()
{
printf("I'm an Apple\n");
}
pear.c
#include <stdio.h>
void pear()
{
printf("I'm a pear\n");
}
orange.c
#include <stdio.h>
void orange()
{
printf("I'm an Orange\n");
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "apple.h"
#include "pear.h"
#include "orange.h"
int main(int argc, char** argv)
{
apple();
pear();
orange();
return 0;
}
从上面的源码可以知道,apple、pear、orange三个库非常简单,就只有一个函数,函数的实现为简单的一句打印。main.c分别调用一次三个库中的函数。由于本文的重点在于cmake的子模块的编译,所以模拟的代码都非常简单。
需要说明的是,除了在顶层目录下有一个CMakeLists.txt外,src目录下也有一个CMakeLists.txt,apple、pear、orange三个子目录下也分别有一个CMakeLists.txt。如果你对这些CMakeLists.txt的作用感到迷惑,接下来就为你揭开这层面纱。
CMakeLists.txt
顶层CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
cmake_policy(SET CMP0048 NEW)
project(test06 VERSION "1.0.0.0")
include_directories(${PROJECT_SOURCE_DIR}/inc) # 指定头文件搜索路径
aux_source_directory(${PROJECT_SOURCE_DIR}/src src_dirs) # 指定源码目录
link_directories(${PROJECT_SOURCE_DIR}/lib) # 指定库搜索路径
add_subdirectory(src) # 指定 编译子目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) # 指定可执行文件输出目录
add_executable(fruit ${src_dirs}) # 指定可执行文件名及源码
target_link_libraries(fruit apple pear orange) # 链接外部库
要想进入子目录进行编译,首先得在父目录的CMakeLists.txt中使用add_subdirectory命令,参数为子目录名。如上所示。
add_subdirectory()
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
src/CMakeLists.txt
add_subdirectory(./apple)
add_subdirectory(./pear)
add_subdirectory(./orange)
要想将编译传递到apple、pear、orange目录,src目录中也要有CMakeLists.txt并使用add_subdirectory命令进行传递。
src/apple/CMakeLists.txt
message("apple---${PROJECT_SOURCE_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) # 指定动态库输出目录
add_library(apple SHARED ./apple.c) # 生成动态库 libapple.so
src/orange/CMakeLists.txt
message("orange---${PROJECT_SOURCE_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) # 指定动态库输出目录
add_library(orange SHARED ./orange.c) # 生成动态库 liborange.so
src/pear/CMakeLists.txt
message("pear---${PROJECT_SOURCE_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) # 指定动态库输出目录
add_library(pear SHARED ./pear.c) # 生成动态库 libpear.so
编译
cd build
cmake ..
make
将会在lib目录下生成libapple.so,liborange.so,libpear.so。
在bin目录下生成fruit。