使用get_target_property判断Target是否存在

使用Cmake的add_custom_target建立自定义的Target后,必须将这个Target加入all依赖,否则生成的Makefile不会执行这个Target的内容。这样会有个问题,如果需要编译如下目录:

目录下有N个目录,这些目录下或是目录,或是文件,那么递归下去,就会有若干CMakeLists.txt,也就是说,会有若干个add_custom_target(all ...)的存在。进入单独目录编译或许不要紧,但是如果我们在顶层或者中间层执行cmake生成Makefile,就会报重复Target的错误,这个重复的Target就是多次添加的all。错误如下:

add_custom_target cannot create target "all" because
  another target with the same name already exists.  The existing target is a
  custom target created in source directory
See documentation
  for policy CMP0002 for more details.

只能在叶子编译而不能在中上层编译,这样显然不行。一个可行的解决方案是,在向all中添加Target前,先判断Target‘是否存在,如果不存在,则使用add_custom_target添加依赖(add_custom_target的问题在于,它本身不判断Target是否存在,每次都是新建);如果存在,则使用add_dependencies添加依赖(add_dependencies只是添加依赖,而不会新建Target)。在这里,使用get_target_property判断Target存在与否,原型如下:

get_target_property(VAR target property)

这里的property和VAR相当于一个map键值对,property是键,VAR是值,这个键值对从属于target,如果这个target没有这个键,那么VAR将返回OUTPUT_VALUE-NOTFOUND。

有get必有set,向一个Target添加键值的方法是set_property,原型如下:

set_property(<GLOBAL                            |
              DIRECTORY [dir]                   |
              TARGET    [target1 [target2 ...]] |
              SOURCE    [src1 [src2 ...]]       |
              TEST      [test1 [test2 ...]]     |
              CACHE     [entry1 [entry2 ...]]>
             [APPEND] [APPEND_STRING]
             PROPERTY <name> [value1 [value2 ...]])

这里功能较多,我们只需要设置TARGET为指定的target名,PROPERTY设置为需要的键值对即可。如此,判断一个Target是否存在就可以这么写:

get_target_property(OUTPUT_VALUE all STATUS)
if(${OUTPUT_VALUE} STREQUAL OUTPUT_VALUE-NOTFOUND)
	#Target all 不存在
else()
	#Target all 存在
endif()

在此基础上,包装一个自定义的函数append_dependencies,它向all中添加依赖,在all不存在的情况下,使用add_custom_target新建Target all并且增加依赖,对Target增加键值对讯息,如果all存在,则使用add_dependencies添加依赖,代码如下:

function(append_dependencies)
    set(multiValueArgs DEPENDENCIES)
    cmake_parse_arguments(APPEND_DEPENDENCIES "" "" "${multiValueArgs}" ${ARGN})
    
    get_target_property(OUTPUT_VALUE all STATUS)
    if(${OUTPUT_VALUE} STREQUAL OUTPUT_VALUE-NOTFOUND)
        add_custom_target(all DEPENDS ${APPEND_DEPENDENCIES_DEPENDENCIES})
        set_property(TARGET all PROPERTY STATUS AVAILABLE)
    else()
        add_dependencies(all DEPENDS ${APPEND_DEPENDENCIES_DEPENDENCIES})
    endif()
    
endfunction()<pre name="code" class="plain">

使用append_dependencies向all添加依赖,这样就能有效解决在中上层目录中Target冲突的现象。

使用get_target_property判断Target是否存在

时间: 2024-11-03 22:43:22

使用get_target_property判断Target是否存在的相关文章

FreeMarker中if标签内的判断条件

reeMarker中的<#if>标签除了里面直接判断 boolean 类型的变量外,也可以进行表达式判断,有几个细节记录一下 1. 判断对象是否存在(null) 经常会用到,如果对象 != null 则xxxx,在freemarker中表达比较奇怪,例如判断 target 是否为null,如果不为 nll 则做xxx动作 <#if target??> xxxx </#if> (目标变量后面连续两个??) 2. 字符串或数字比较 java里标准字符串比较需要 .equal

CMake命令:CMake构建系统的骨架

CMake命令:CMake构建系统的骨架 80个命令(转载自http://www.cnblogs.com/coderfenghc/archive/2012/06/16/CMake_ch_01.html#2996205) CMD#1: add_custom_command为生成的构建系统添加一条自定义的构建规则. add_custom_command命令有两种主要的功能:第一种是为了生成输出文件,添加一条自定义命令. add_custom_command(OUTPUT output1 [outpu

cmake

前言cmake 已经开发了 5,6 年的时间,如果没有 KDE4,也许不会有人或者 Linux 发行版本重视cmake,因为除了 Kitware 似乎没有人使用它.通过 KDE4 的选型和开发,cmake 逐渐进入了人们的视线,在实际的使用过程中,cmake 的优势也逐渐的被大家所认识,至少 KDE 的开发者们给予了 cmake极高的评价,同时庞大的 KDE 项目使用 cmake 来作为构建工具也证明了 cmake 的可用性和大项目管理能力.所以,cmake 应该感谢 KDE,也正因为如此,cm

(转)HelloWorld CMake CMake中构建静态库与动态库及其使用

继续完善Hello World,建立它的共享库, 包括静态库和动态库. 本节的任务: 1,建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc 向终端输出Hello World字符串. 2,安装头文件与共享库. 3, 编写一个程序使用创建的共享库(静态库和动态库). cd /home/ccj/CMakeDemo mkdir t3   cd /backup/cmake/t3 mkdir lib   在t3目录下建立CMakeLists.txt,内容如下: PRO

HelloWorld CMake Demo 03:CMake中构建静态库与动态库及其使用

? 继续完善Hello World,建立它的共享库, 包括静态库和动态库. ? 本节的任务: 1,建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc 向终端输出Hello World字符串. 2,安装头文件与共享库. 3, 编写一个程序使用创建的共享库(静态库和动态库). ? 一,准备工作: 在/home/ccj/CMakeDemo目录建立t3目录,用于存放本节涉及到的工程. cd /home/ccj/CMakeDemo mkdir t3 ? 二,建立共享库

CMake 手册详解

CMake 手册详解 来源 http://www.cnblogs.com/coderfenghc/tag/cmake/ 公司的一个项目使用CMake作为跨平台构建工具:业务有需求,当然要好好研读一下官方的技术手册.目前的计划是先把官方手册翻译一下,了解清楚CMake中的各种命令.属性和变量的用法.同时在工作中也会阅读CMake的真实源码,后续会基于此陆续写一些工程中使用CMake的心得.CMake的版本也在不停更新,有些新的命令和变量会随着版本更新添加进来,这是后事了,暂且不管:现在锁定CMak

CMakeListx.txt 编辑语法学习

已hello.cpp为源文件,构建一个CMakeLists.txt cmake_minimum_required(VERSION 2.8) project(hello) add_executable(hello hello.cpp) 在目录中的build 文件夹中进行cmake ..和make ,就可以编译源文件生成可运行文件. cmake的常用命令: project 命令 语句 : project(<projectname> [languageName1 languageName2 - ]

事件委托详解

基本概念 事件委托,通俗地来讲,就是把一个元素响应事件(click.keydown......)的函数委托到另一个元素: 一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数. 举个例子,比如一个宿舍的同学同时快递到了,一种方法就是他们都傻傻地一个个去领取,还有一种方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一一分发

Contiki 2.7 Makefile 文件(二)

二.Makefile.include 1.第一部分 (1) ifndef CONTIKI ${error CONTIKI not defined! You must specify where Contiki resides} endif 含义: 如果没有定义CONTIKI变量,make停止运行. 并产生一个致命的错误信息,CONTIKI not  defined! You must specify where Contiki resides. hello-world这个例子在主控Makefil