我们已经介绍过单目录结构与多目录结构的CMakeLists.txt使用方法,下面介绍如何利用CMakeLists实现类似于C++模板的东西。下面的内容与单目录结构以及多目录结构CMakeLists实现密接相关,建议看完前两个再看这一篇。
应用场景
开发某个基于C语言的项目,要求实现单精度与双精度计算版本。
目录结构
|--examples
| |--add_example.c
| |--sub_example.c
| |--CMakeLists.txt
|--CMakeLists.txt
|--include
| |--alg.h
|--alg
| |--add
| | |--add.c
| | |--CMakeLists.txt
| |--sub
| | |--sub.c
| | |--CMakeLists.txt
| |--CMakeLists.txt
| |--utils
| | |--alg_template.h
其中examples/add_example.c
#include "alg.h"
#include<stdio.h>
int main(){
double a = 1.1, b = 2.1;
printf("add:%lf\n", my_add64(a, b));
return 0;
}
example/sub_example.c
#include "alg.h"
#include<stdio.h>
int main(){
float a = 1.1, b = 2.0;
printf("sub:%f\n", my_sub32(a, b));
return 0;
}
include/alg.h
#ifndef __ALG_H
#define __ALG_H
float my_sub32(float a, float b);
float my_add32(float a, float b);
double my_sub64(double a, double b);
double my_add64(double a, double b);
#endif
alg/add/add.c
#include "alg.h"
#include "alg/utils/alg_template.h"
FLOAT DT(my_add)(FLOAT a, FLOAT b){
return a + b;
}
alg/sub/sub.c
#include "alg.h"
#include "alg/utils/alg_template.h"
FLOAT DT(my_sub)(FLOAT a, FLOAT b){
return a - b;
}
alg/utils/alg_template.h
#ifndef __ALG_TEMPLATE_H
#define __ALG_TEMPLATE_H
#ifdef ALG32
#define FLOAT float
#define DT(func) func##32
#endif
#ifdef ALG64
#define FLOAT double
#define DT(func) func##64
#endif
#endif
如果我们可以分别#define ALG32,再#define ALG64,分开编译再合并,那么就可以实现多精度项目了。
注意#include “alg/utils/alg_template.h”,头文件写成这样是因为在CMakeLists.txt中添加了include_directories(${CMAKE_CURRENT_SOURCE_DIR})指定最外层目录为include起始位置。
#最小cmake版本
cmake_minimum_required(VERSION 2.8)
#项目名字,随意起
project(simple_exe)
#设置C/c++版本(如c99,c++11,c++17等版本),下面表示使用c99版本
set(CMAKE_C_STANDARD 99)
#指定include目录,作用域为全局,包括子目录中的CMakeLists
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
#指定静态库输出路径,作用域为全局,包括子目录中的CMakeLists
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
#将文件夹内存在CMakelist的所有文件命名为MODULES
set(MODULES
alg
examples
)
foreach(module ${MODULES})
#执行每一个文件夹里面的CMakeLists.txt脚本
add_subdirectory(${module})
endforeach()
alg/CMakeLists.txt 注意实现多精度精华的地方add_library(… OBJECT …)
#老三段
cmake_minimum_required(VERSION 2.8)
project(simple_alg_exe)
set(CMAKE_C_STANDARD 99)
#设置LIBRARY_OUTPUT_PATH为库的输出位置
SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
#将文件夹内存在CMakelist的所有文件命名为MODULES
set(MODULES
add
sub
)
foreach(module ${MODULES})
#执行每一个文件夹里面的CMakeLists.txt脚本
add_subdirectory(${module})
endforeach()
#注意不同于STATIC,OBJECT并不会在这里生成库,而是在下一次使用add_library()时生成
add_library(alg64 OBJECT ${SRCS})
add_library(alg32 OBJECT ${SRCS})
#分别为alg32/alg64指定编译标识,-D即define,-DALG32 表示在代码开头#define ALG32
#通过这种方式,我们可以为代码分别指定32位版本与64位版本
set_target_properties(alg64
PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DALG64"
)
set_target_properties(alg32
PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DALG32"
)
#第二次使用add_library,生成库
#表示将alg32与alg64合并生成alg库
add_library(alg STATIC $<TARGET_OBJECTS:alg64> $<TARGET_OBJECTS:alg32>)
#将alg.h头文件发布到${CMAKE_CURRENT_SOURCE_DIR}/../output/include目录中,当然可以写一些其它的目录,如/usr/local/lib64/include
install(FILES ../include/alg.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../output/include)
#将libalg.a静态库文件发布到${CMAKE_CURRENT_SOURCE_DIR}/../output/lib目录中
install(FILES ../lib/libalg.a DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../output/lib)
传送门
C语言开发之CMakeLists以及gtest测试在C语言中的使用方法(其四)
C语言开发之CMakeList(其三)
C/C++开发之CMakeList(其二)
C/C++开发之CMakeLists(其一)