欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CMake宏-根据操作系统类型添加子目录

程序员文章站 2024-03-14 11:10:28
...

  现在我们有一个需求,在编译项目时要求在Windows下添加库DemoWin的源源码进入工程,在Linux下要求添加库DemoLinux的源码进入工程。但是从现有的cmake命令来看,是没有这项功能的。我们现在实现一个add_sub_dir()函数来完成这个功能。

需求分析

  1. 实现这个功能,我们可以有两种方法,第一种是编写一个宏,第二种是编写函数,两种实现方式大同小异看,本章,我们用宏来实现

  2. 要实现功能,该宏应该接受几个参数,第一应该指定操作系统类型,第二应该指定要添加的目录,所以这个宏的用法就像这样 add_sub_dir(Linux DemoWin)

  3. 我们还需要知道当前操作系统的类型,cmake为我们提供了一下内置变量供我们使用,他们如下

    CMAKE_SYSTEM_VERSION
    CMAKE_SYSTEM_NAME
    CMAKE_HOST_SYSTEM_NAME
    

CMAKE_SYSTEM_NAME

The name of the operating system for which CMake is to build. See the CMAKE_SYSTEM_VERSION variable for the OS version.

System Name for Host Builds

CMAKE_SYSTEM_NAME is by default set to the same value as the CMAKE_HOST_SYSTEM_NAME variable so that the build targets the host system.

System Name for Cross Compiling

CMAKE_SYSTEM_NAME may be set explicitly when first configuring a new build tree in order to enable cross compiling. In this case the CMAKE_SYSTEM_VERSION variable must also be set explicitly.

摘自cmake文档

  下面我们开始动手搞定这件事情`

准备工作

  1. 我们需要掌握cmake宏的写法下面请看官方语法介绍
macro(<name> [arg1 [arg2 [arg3 ...]]])
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
endmacro(<name>)

定义完成后,我们可以通过cmake内置的变量来访问宏的参数,这些变量的说明如下:

变量名 说明
argv# #是一个下标,0指向第一个参数,累加
argv 所有的参数
argn 定义参数以为的参数
argc 传入的实际参数的个数,也就是调用函数是传入的参数个数

释一下argvargn

定义时 调用时 argn argv
CMake宏-根据操作系统类型添加子目录 CMake宏-根据操作系统类型添加子目录 demo linux win demo linux win
CMake宏-根据操作系统类型添加子目录 CMake宏-根据操作系统类型添加子目录 linux win demo linux win
  1. 我们需要掌握cmake的参数解析函数cmake_parse_arguments

    语法如下

    cmake_parse_arguments(<prefix> <options> <one_value_keywords>
                          <multi_value_keywords> args...)
    

    下面是官方给出的例子
    CMake宏-根据操作系统类型添加子目录

  2. 下面我们来动手实现这个功能

    现在我们先分析一下逻辑

    • 获取当前操作系统类型

    • 解析参数,看当前系统是否需要添加子目录

    • 将子目录的CMakeLists.txt添加到工程中

    代码如下

    if("!${CMAKE_SYSTEM_NAME}" STREQUAL "!Windows")
        set(OS_WIN TRUE)
    elseif("!${CMAKE_SYSTEM_NAME}" STREQUAL "!Linux")
        set(OS_LINUX TRUE)
    elseif("!${CMAKE_SYSTEM_NAME}" STREQUAL "!Darwin")
        set(OS_MAC TRUE)
    else()
        message(FATAL_ERROR "Unknown platform: ${CMAKE_SYSTEM_NAME}!")
    endif()
    
    
    macro(add_sub_dir)
        set(os Linux win mac)
        cmake_parse_arguments(tmp "${os}" "" "" ${ARGN})
        
        #如果没有传入参数,所有系统都添加
        if(NOT tmp_Linux AND NOT tmp_win AND NOT tmp_mac)
            set(tmp_Linux ON)
            set(tmp_win ON)
            set(tmp_mac ON)
        endif()
        if(tmp_Linux)
            set(tmp_Linux ON)
        endif()
        if(tmp_win)
            set(tmp_win ON)
        endif()
        if(tmp_mac)
          set(tmp_mac ON)
        endif()
    
        set(isAdd OFF)
        if(OS_WIN)
            set(isAdd ${tmp_win})
        elseif(OS_LINUX)
            set(isAdd ${tmp_Linux})
        elseif(OS_MAC)
            set(isAdd ${tmp_mac})
        endif()
    
        if(isAdd)
    		set(dir ${tmp_UNPARSED_ARGUMENTS})
    		if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
    			if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir}/CMakeLists.txt")
    				add_subdirectory(${dir})
    			endif()
    		else()
    			message(WARNING "${dir} does not exists")
    		endif()
    	endif()
    endmacro(add_sub_dir)
    

CMake宏-根据操作系统类型添加子目录

可以看到,在Linux平台下编译,只有linuxDemo参与了。
工程全部代码在这里

相关标签: cmake