《CMake手册》学习笔记

第一步 A Basic Starting Point

CMake从一个cpp代码编译开始,就是从源代码文件构建的可执行文件。只需要三行代码的CMakeLists.txt就可以完成一个简单的CMake。

简单的C程序例子

第一个例子是在文件夹中创建一个main.c文件,同级目录下创建CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.10)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial tutorial.cxx)

程序输出hello,world

#include <stdio.h>
void main(){
    
    
	printf("hello,world\n");
}

cmake_minimum_required用于指定CMake的最低(高)版本的要求。
project命令用于指定cmake工程的名称。如果在CMakeLists.txt文件中没有指定project,在cmake ./后,会提示告警,但不影响cmake ./的执行完成;
在这里插入图片描述
add_executable为可执行目标文件创建一个别名。
在上面的CMakeLists.txt中,我们使用了小写的命令,CMake也支持大写命令,也支持大小写混杂的做法;
在文件夹中写完了CMakeLists.txtmain.c后,就可以使用cmake命令来进行编译;

cmake ./

执行的过程如下:

wang@myubuntu:~/code/t3/demo$ la
CMakeLists.txt  main.c
wang@myubuntu:~/code/t3/demo$ cmake .
CMake Warning (dev) in CMakeLists.txt:
  No project() command is present.  The top-level CMakeLists.txt file must
  contain a literal, direct call to the project() command.  Add a line of
  code such as

    project(ProjectName)

  near the top of the file, but after cmake_minimum_required().

  CMake is pretending there is a "project(Project)" command on the first
  line.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/wang/code/t3/demo

执行后,文件夹内多了一个文件夹和几个文件:

wang@myubuntu:~/code/t3/demo$ ll
total 48
drwxrwxr-x 3 wang wang  4096 Nov 13 04:54 ./
drwxrwxr-x 3 wang wang  4096 Nov 13 04:17 ../
-rw-rw-r-- 1 wang wang 13676 Nov 13 04:54 CMakeCache.txt
drwxrwxr-x 5 wang wang  4096 Nov 13 04:54 CMakeFiles/
-rw-rw-r-- 1 wang wang  1492 Nov 13 04:54 cmake_install.cmake
-rw-rw-r-- 1 wang wang   108 Nov 13 04:23 CMakeLists.txt
-rw-rw-r-- 1 wang wang    78 Nov 13 04:19 main.c
-rw-rw-r-- 1 wang wang  4679 Nov 13 04:54 Makefile

至于文件夹和文件是用来干嘛的,学完这个手册,看看有没有介绍;
执行make命令或者cmake build .命令:

wang@myubuntu:~/code/t3/demo$ make
Scanning dependencies of target MyCode
[ 50%] Building C object CMakeFiles/MyCode.dir/main.c.o
[100%] Linking C executable MyCode
[100%] Built target MyCode
wang@myubuntu:~/code/t3/demo$ ll
total 68
drwxrwxr-x 3 wang wang  4096 Nov 13 04:57 ./
drwxrwxr-x 3 wang wang  4096 Nov 13 04:17 ../
-rw-rw-r-- 1 wang wang 13676 Nov 13 04:54 CMakeCache.txt
drwxrwxr-x 5 wang wang  4096 Nov 13 04:57 CMakeFiles/
-rw-rw-r-- 1 wang wang  1492 Nov 13 04:54 cmake_install.cmake
-rw-rw-r-- 1 wang wang   108 Nov 13 04:23 CMakeLists.txt
-rw-rw-r-- 1 wang wang    78 Nov 13 04:19 main.c
-rw-rw-r-- 1 wang wang  4679 Nov 13 04:54 Makefile
-rwxrwxr-x 1 wang wang 16696 Nov 13 04:57 MyCode*

文件中新增了MyCode*可执行文件,执行如下:

wang@myubuntu:~/code/t3/demo$ ./MyCode 
hello,worldwang@myubuntu:~/code/t3/demo$ 

在文件夹内创建一个build文件夹,在其内执行cmake ../,这样cmake后的所有文件都会在build文件夹内,由于cmake没有clean的命令,只能把输出的中间文件都删除后,重新执行cmake命令,可以直接删除build文件夹后,重新执行cmake命令。

wang@myubuntu:~/code/t3/demo$ mkdir build
wang@myubuntu:~/code/t3/demo$ cd build
wang@myubuntu:~/code/t3/demo/build$ cmake ../
CMake Warning (dev) in CMakeLists.txt:
  No project() command is present.  The top-level CMakeLists.txt file must
  contain a literal, direct call to the project() command.  Add a line of
  code such as

    project(ProjectName)

  near the top of the file, but after cmake_minimum_required().

  CMake is pretending there is a "project(Project)" command on the first
  line.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/wang/code/t3/demo/build
wang@myubuntu:~/code/t3/demo/build$ make
Scanning dependencies of target MyCode
[ 50%] Building C object CMakeFiles/MyCode.dir/main.c.o
[100%] Linking C executable MyCode
[100%] Built target MyCode
wang@myubuntu:~/code/t3/demo/build$ 
wang@myubuntu:~/code/t3/demo/build$ ll
total 60
drwxrwxr-x 3 wang wang  4096 Nov 13 05:01 ./
drwxrwxr-x 3 wang wang  4096 Nov 13 05:01 ../
-rw-rw-r-- 1 wang wang 13694 Nov 13 05:01 CMakeCache.txt
drwxrwxr-x 5 wang wang  4096 Nov 13 05:01 CMakeFiles/
-rw-rw-r-- 1 wang wang  1498 Nov 13 05:01 cmake_install.cmake
-rw-rw-r-- 1 wang wang  4703 Nov 13 05:01 Makefile
-rwxrwxr-x 1 wang wang 16696 Nov 13 05:01 MyCode*

增加版本号

在linux下,动态库So后面是可以跟接版本号的,静态库不行;
首先,清理build文件夹内的文件,使用rm -rf *
project命令中增加VERSION 12.20.0,具体什么效果,我也没有看到,从生成的文件和使用readelf命令都没有看到有什么不一样的地方;

cmake_minimum_required(VERSION 3.10)  
# set the project name
project(MyCode VERSION 12.20.0)
add_library(MyCode main.c)

CMakeLists.txt文件中,增加

configure_file(configure.h.in configure.h)

CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.10)  
# set the project name
project(MyCode VERSION 12.20.0)
set(VERSION_MAJOR 12)
set(VERSION_MINOR 20)
configure_file(configure.h.in configure.h)
add_executable(MyCode main.c)
target_include_directories(MyCode PUBLIC "${PROJECT_BINARY_DIR}")

target_include_directories指定某个具体target的头文件路径,可以更好的控制头文件的可见性。
注意:target_include_directories须在add_executable命令之后,target_include_directories命令的第一个参数和add_executable命令的第一个参数必须一致。
main.c文件夹下,创建configure.h.in文件

#define My_VERSION_MAJOR @VERSION_MAJOR@
#define My_VERSION_MINOR @VERSION_MINOR@

执行上面的CMakeLists.txt文件后,build文件夹(${PROJECT_BINARY_DIR})下出现了configure.h文件;

wang@myubuntu:~/code/t3/demo/build$ vim ../CMakeLists.txt 
wang@myubuntu:~/code/t3/demo/build$ ll
total 48
drwxrwxr-x 3 wang wang  4096 Nov 13 12:40 ./
drwxrwxr-x 3 wang wang  4096 Nov 13 12:46 ../
-rw-rw-r-- 1 wang wang 14012 Nov 13 12:40 CMakeCache.txt
drwxrwxr-x 5 wang wang  4096 Nov 13 12:40 CMakeFiles/
-rw-rw-r-- 1 wang wang  1498 Nov 13 12:40 cmake_install.cmake
-rw-rw-r-- 1 wang wang    56 Nov 13 12:40 configure.h
-rw-rw-r-- 1 wang wang  1830 Nov 13 12:40 libMyCode.a
-rw-rw-r-- 1 wang wang  4703 Nov 13 12:40 Makefile

configure.h文件内容:

#define My_VERSION_MAJOR 12
#define My_VERSION_MINOR 20

configure.h.in文件内的@VERSION_MAJOR@@VERSION_MINOR@CMakeLists.txt文件的设置值替换;

set(VERSION_MAJOR 12)
set(VERSION_MINOR 20)

之前的CMakeLists.txt文件也可以写作如下:

cmake_minimum_required (VERSION 3.10)
project (MyCode)
# 版本号
set (VERSION_MAJOR 12)
set (VERSION_MINOR 20)
# 配置一个头文件,通过它向源代码中传递一些CMake设置。
configure_file (
  "${PROJECT_SOURCE_DIR}/configure.h.in"
  "${PROJECT_BINARY_DIR}/configure.h"
  )
# 将二进制文件树添加到包含文件的搜索路径中,这样我们可以找到TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
# 添加可执行文件
add_executable(MyCode main.cxx)

main.c修改为:

#include <stdlib.h>
#include <stdio.h>
#include "configure.h"
void main(){
    
    
        printf("Vesion is %d.%d",My_VERSION_MAJOR,My_VERSION_MINOR);
}

cmake后的执行结果

wang@myubuntu:~/code/t3/demo/build$ ./MyCode 
Vesion is 12.20

使用C++11

修改上一节的程序使用C++11,则从C程序到了C++程序;
直接修改CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.10)  
# set the project name
project(MyCode VERSION 12.20.0)
# specify the C++ standard 11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(VERSION_MAJOR 12)
set(VERSION_MINOR 20)
configure_file(configure.h.in configure.h)
add_executable(MyCode main.cpp)
target_include_directories(MyCode PUBLIC "${PROJECT_BINARY_DIR}")

CMakeLists.txt文件中的CMAKE_CXX_STANDARD变量设置为11,将CMAKE_CXX_STANDARD_REQUIRED设置为True或者ON。确保在添加可执行文件的调用上方添加CMAKE_CXX_STANDARD声明。
make后,提示错误

wang@myubuntu:~/code/t3/demo/build$ make
[ 50%] Building C object CMakeFiles/MyCode.dir/main.c.o
/home/wang/code/t3/demo/main.c:1:10: fatal error: iostream: No such file or directory
    1 | #include <iostream>
      |          ^~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/MyCode.dir/build.make:63: CMakeFiles/MyCode.dir/main.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/MyCode.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

需要将main.c修改为main.cpp

wang@myubuntu:~/code/t3/demo/build$ make
Scanning dependencies of target MyCode
[ 50%] Building CXX object CMakeFiles/MyCode.dir/main.cpp.o
/home/wang/code/t3/demo/main.cpp:3:1: error: ‘::main’ must return ‘int’
    3 | void main(){
    
    
      | ^~~~
make[2]: *** [CMakeFiles/MyCode.dir/build.make:63: CMakeFiles/MyCode.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/MyCode.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

将main函数从之前的void main()修改为int main()

#include <iostream>
#include "configure.h"
int main(){
    
    
	std::cout<<"Version is"<< My_VERSION_MAJOR << My_VERSION_MINOR<<std::endl;
	return 0;
}

第二步 Adding a Library

第一步只是使用cmake创建了一个可执行文件,只适用于简单项目。常规项目中,必然有各种动态库和静态库。如何使用cmake编译库文件也是C++项目中最常见的cmake实践。
需求:提供一个数学库,里面有开平方的接口;
1.代码项目文件夹下,创建一个MathFunctions文件夹,里面有一个CMakeLists.txt文件,一个头文件MathFunctions.h和源文件mysqrt.cxx

不使用数学库的项目

项目的CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.10)
project(Tutorial)
add_executable(Tutorial tutorial.cxx)

tutorial.cxx使用math.h中的sqrt函数实现开平方,具体内容如下:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main(int argc,char *argv[]){
    
    
	if (argc < 2){
    
    
		printf("Usage:%s number\n",argv[0]);
		return 1;
	}
	double inputValue = atof(argv[1]);
	double outputValue = sqrt(inputValue);
	printf("The square root of %lf is %lf\n",inputValue,outputValue);
	return 0;
}

使用自己的数学库项目

在头文件MathFunctions.h和源文件mysqrt.cxx中,定义一个my_sqrt函数,内部使用math.h中的sqrt函数实现开平方。
MathFunctions文件夹下的CMakeLists.txt文件如下:

add_library(MathFunctions mysqrt.cxx)

试着对MathFunctions文件夹进行cmake,生成的文件如下:

drwxrwxr-x 3 wang wang  4096 Nov 14 03:01 ./
drwxrwxr-x 4 wang wang  4096 Nov 14 02:56 ../
-rw-rw-r-- 1 wang wang 13727 Nov 14 03:00 CMakeCache.txt
drwxrwxr-x 5 wang wang  4096 Nov 14 03:01 CMakeFiles/
-rw-rw-r-- 1 wang wang  1514 Nov 14 03:01 cmake_install.cmake
-rw-rw-r-- 1 wang wang  1716 Nov 14 03:01 libMathFunctions.a
-rw-rw-r-- 1 wang wang  4893 Nov 14 03:01 Makefile

可以看到add_library默认生成了一个.a的静态库;

简单调用MathFunctions库

引入MathFunctions库,使用命令add_subdirectory引入MathFunctions文件夹,使用命令target_link_libraries链接库文件,使用命令target_include_directories引入库的头文件;

cmake_minimum_required(VERSION 3.10)

project(Tutorial)
# add the MathFunctions library
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
        "${PROJECT_BINARY_DIR}"
        "${PROJECT_SOURCE_DIR}/MathFunctions"
        )

tutorial.cxx修改为使用MathFunctions库的my_sqrt函数,如下:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "MathFunctions.h"

int main(int argc,char *argv[]){
    
    
	if (argc < 2){
    
    
		printf("Usage:%s number\n",argv[0]);
		return 1;
	}
	double inputValue = atof(argv[1]);
	//double outputValue = sqrt(inputValue);
	double outputValue = my_sqrt(inputValue);
	printf("The square root of %lf is %lf\n",inputValue,outputValue);
	return 0;
}

使用USE_MYMATH宏控制开平方的接口

在CMake中增加控制是否开启使用数学库的选项USE_MYMATH,当USE_MYMATHON时,使用MathFunctions库的my_sqrt函数,否则使用math.h库中的sqrt函数;

cmake_minimum_required(VERSION 3.10)
project(Tutorial)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

option(USE_MYMATH "Use tutorial provided math implementation" ON)

# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
if(USE_MYMATH)
        # add the MathFunctions library
        add_subdirectory(MathFunctions)
        set(EXTRA_LIBS ${
    
    EXTRA_LIBS} MathFunctions)
        set(EXTRA_INCLUDES ${
    
    EXTRA_INCLUDES} "${PROJECT_SOURCE_DIR}/MathFunctions")
endif(USE_MYMATH)
# add the executable
add_executable(Tutorial tutorial.cxx)
#target_link_libraries(Tutorial PUBLIC MathFunctions)
#message(${
      
      EXTRA_LIBS})
target_link_libraries(Tutorial PUBLIC ${
    
    EXTRA_LIBS})

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
        "${PROJECT_BINARY_DIR}"
        "${EXTRA_INCLUDES}"
        )

使用option生成一个cmake定义的宏变量USE_MYMATH
需要在TutorialConfig.h.in文件中添加:

#cmakedefine USE_MYMATH

就会在TutorialConfig.h文件下生成

/* #undef USE_MYMATH */

或者是

#define USE_MYMATH

这里折腾很久,手册中写的是需要使用list

list(APPEND EXTRA_LIBS MathFuncitons)
list(APPEND EXTRA_INCLUDE "${PROJECT_SOURCE_DIR}/MathFunctions")

按照这个写法,在编译时报错,找不到对应的库文件;
后改成使用set后,就没有问题了。

set(EXTRA_LIBS ${
    
    EXTRA_LIBS} MathFunctions)
set(EXTRA_INCLUDES ${
    
    EXTRA_INCLUDES} "${PROJECT_SOURCE_DIR}/MathFunctions")

在代码中,使用USE_MYMATH

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
int main(int argc,char *argv[]){
    
    
	if (argc < 2){
    
    
		printf("Usage:%s number\n",argv[0]);
		return 1;
	}
	double inputValue = atof(argv[1]);
#ifdef USE_MYMATH
	printf("Use My Math\n");
	double outputValue = my_sqrt(inputValue);
#else
	printf("Use std Math\n");
	double outputValue = sqrt(inputValue);
#endif
	printf("The square root of %lf is %lf\n",inputValue,outputValue);
	return 0;
}

第三步 Adding Usage Requirements for a Library

在使用库时,可以设置编译选项和链接信息等内容,可以更好地控制CMake内目标的传递属性。
主要使用的命令为:

target_compile_definitions()
target_compile_options():指定目标的编译选项
target_include_directories():指定目标包含的头文件路径
target_link_libraries():指定目标链接的库

例子

在使用MathFunctions库时,需要知道SOURCE源文件的路径。
在之前的CMakeLists.txt文件中使用相对路径,在target_include_directories命令时使用;

set(EXTRA_INCLUDES ${
    
    EXTRA_INCLUDES} "${PROJECT_SOURCE_DIR}/MathFunctions")
target_include_directories(Tutorial PUBLIC
        "${PROJECT_BINARY_DIR}"
        "${EXTRA_INCLUDES}"
        )

如果在MathFunctions库生成时,把MathFunctions的源文件引入到使用的CMake下;
使用INTERFACE参数,意味着消费者需要但生产者不需要的东西,即是任何链接到的人都需要包含当前的源目录,而它本身不需要。
MathFunctions文件夹下的CMakeLists.txt文件中,修改为:

add_library(MathFunctions SHARED mysqrt.cxx)
target_include_directories(MathFunctions
        INTERFACE ${
    
    CMAKE_CURRENT_SOURCE_DIR}
        )

CMAKE_CURRENT_SOURCE_DIR:当前正在处理的源目录的路径。
将使用者的CMakeLists.txt修改为:

cmake_minimum_required(VERSION 3.10)
project(Tutorial)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

option(USE_MYMATH "Use tutorial provided math implementation" ON)

# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
if(USE_MYMATH)
        # add the MathFunctions library
        add_subdirectory(MathFunctions)
        set(EXTRA_LIBS ${
    
    EXTRA_LIBS} MathFunctions)        
endif(USE_MYMATH)
# add the executable
add_executable(Tutorial tutorial.cxx)
#target_link_libraries(Tutorial PUBLIC MathFunctions)
#message(${
      
      EXTRA_LIBS})
target_link_libraries(Tutorial PUBLIC ${
    
    EXTRA_LIBS})

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
        "${PROJECT_BINARY_DIR}"        
        )

第四步 Installing and Testing

Installing

之前都是在学习库的生成和使用,在linux下,库总是要被安装到指定位置的。
so,要学习下CMake如何安装库。
库的安装就是把生成的.a或者.so目标文件以及对应的头文件复制到指定文件夹下;
还是以MathFunctions库为例;
MathFunctions文件夹下的CMakeLists.txt文件末尾追加:

install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)

在根目录的CMakeLists.txt文件的末尾增加:

install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
        DESTINATION include
        )

使用cmake命令的install选项安装库文件。

root@myubuntu:/home/wang/code/t3/demo/build# cmake --install .
-- Install configuration: ""
-- Up-to-date: /usr/local/bin/Tutorial
-- Up-to-date: /usr/local/include/TutorialConfig.h
-- Up-to-date: /usr/local/lib/libMathFunctions.so
-- Installing: /usr/local/include/MathFunctions.h

也可以使用prefix选项指定安装位置,例如:

cmake --install . --prefix "/home/wang/installdir"

Testing

第五步 Adding System Introspection

如果实现的库中使用到了系统库的功能,在库使用时,并不能确认当前系统是否有库所需要的功能;就需要在编译时判断系统功能现状进行抉择;
在手册中,假设系统中的logexp函数并不是所有系统都能提供的。
如果该平台具有logexp那我们就用它们来计算平方根的my_sqrt功能。我们首先使用CheckSymbolExists中的模块 MathFunctions/CMakeLists.txt。在某些平台上,我们需要链接到m库。如果logexp没有最初发现,所需要的m库,然后重试。
添加检查logexpMathFunctions/CMakeLists.txt,调用后target_include_directories()
如果可用,请使用target_compile_definitions()指定HAVE_LOG并HAVE_EXP作为PRIVATE编译定义。

#include "MathFunctions.h"
#include <stdio.h>
#include <math.h>
double my_sqrt(double var){
    
    
#if defined(HAVE_LOG) && defined(HAVE_EXP)
	double result = exp(log(var)*0.5);
	printf("Computing sqrt of %lf, using log and exp\n",var);
	return result;
#else
	return sqrt(var);
#endif
}

MathFunctions/CMakeLists.txt的内容如下:

add_library(MathFunctions SHARED mysqrt.cxx)
target_include_directories(MathFunctions
	INTERFACE ${
    
    CMAKE_CURRENT_SOURCE_DIR}
	)
#does this system provide the log and exp functions?
include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)

if(NOT(HAVE_LOG AND HAVE_EXP))
	unset(HAVE_LOG CACHE)
	unset(HAVE_EXP CACHE)
	set(CMAKE_REQUIRED_LIBRARIES "m")
	check_symbol_exists(log "math.h" HAVE_LOG)
	check_symbol_exists(exp "math.h" HAVE_EXP)
	if(HAVE_LOG AND HAVE_EXP)
		target_link_libraries(MathFunctions PRIVATE m)
	endif()
endif()

if(HAVE_LOG AND HAVE_EXP)
	target_compile_definitions(MathFunctions 
		PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)

执行后的结果:

root@myubuntu:/home/wang/code/t3/demo/build# ./Tutorial 4
Use My MathComputing sqrt of 4.000000, using log and exp
The square root of 4.000000 is 2.000000

参考资料

1.CMAKE手册

猜你喜欢

转载自blog.csdn.net/liushao1031177/article/details/121189222