cmake:在构建树的多个位置具有相同名称的“all”和“test”等特殊目标?

时间:2016-02-18 18:03:53

标签: cmake

cmake不允许您使用add_custom_target()在构建树中的不同位置创建具有相同名称的多个目标。 但是,它确实为该属性提供了特殊目标:

  • 所有
  • 测试
  • 安装

在子树中运行时,每个都将仅适用于该子树。 有没有办法达到用户目标的目的?

这是一个简化的例子:

toplevel CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

add_custom_target(thing)

add_subdirectory(sub1)
add_subdirectory(sub2)

SUB1 /的CMakeLists.txt

add_executable(foo foo.cpp)

add_custom_target(thing.sub1 DEPENDS foo)
add_dependencies(thing thing.sub1)

SUB2 /的CMakeLists.txt

add_executable(bar bar.cpp)

add_custom_target(thing.sub2 DEPENDS bar)
add_dependencies(thing thing.sub2)

我几乎可以得到我想要的行为:

  • 在顶层制作东西构建thing.sub1& thing.sub2
  • 使thing.sub1 位于顶层或在sub1中构建thing.sub1
  • 使thing.sub2 在顶层或在sub2中构建thing.sub2

我想要的是能够只运行 make thing 并将其应用于 当前的子目录,如 all 目标。

这可能吗? 如果不是它是一个缺失的功能,或者它是一个错误的,如果是这样的原因?

解决方案(差不多)

@ zuafi的方向让我找到了解决方案。

目前可以但仅使用政策CMP0002中的弃用行为。 实际上有一个缺少的功能,用于添加this open ticket所涵盖的本地目标。

我的解决方法是为自己实现 add_local_target()如下:

# determine whether local targets should be legal
if("${CMAKE_GENERATOR}" MATCHES "Make")
  cmake_policy(SET CMP0002 OLD)
  # property seems to be deprecated
  set_property(GLOBAL PROPERTY ALLOW_DUPLICATE_CUSTOM_TARGETS 1)
  set(ALLOW_LOCAL_TARGETS 1)
  message("using Makefile generator")
else()
  cmake_policy(SET CMP0002 NEW)
  message("Generator=${CMAKE_GENERATOR}")
endif()

# add a custom target with the same name as another (posssibly global) target iff permitted
# see http://stackoverflow.com/questions/35489093/cmake-special-targets-like-all-and-test-having-the-same-name-in-multiple-pl
function(add_local_target target)
  if(ALLOW_LOCAL_TARGETS)   
    set(dependencies "${ARGN}")
    foreach(dependency IN LISTS dependencies)
       if(TARGET ${dependency})
          list(APPEND targets ${dependency})
       else()
          message("${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt: warning: dependency ${dependency} for add_local_target(${target}) is NOT a target")
       endif()
    endforeach()
    add_custom_target(${target} DEPENDS ${targets})
  endif()
endfunction()

这与 target.subdir 等目标路径很好地结合使用,如果使用非Makefile生成器,它可以用作后备路径。 我只是用:

add_local_target(thing DEPENDS thing.sub1)

更新

我认为这个解决方案可能会被巧妙地打破。如果您尝试构建“本地”目标,可以构建其他“本地”目标。但是,它将至少构建它应该构建的内容。它还将构建一个不同于全局项目范围的目标,并且将建立相同的名称。我还没有设法跟踪它,因为cmake生成的makefile有些粗糙。

1 个答案:

答案 0 :(得分:1)

是的,它可能......但不是所有发电机都可以。特别是Ok w / UNIX Makefiles (参见CMP0002描述)。至于我,我想让我的项目树中的所有单元测试具有相同的名称(我有一个bash完成该名称:),所以我使用以下宏帮助我声明可执行文件:

macro(set_unit_test_target_name OUTPUT_VARIABLE DEFAULT_VALUE)
    cmake_policy(GET CMP0002 _may_use_same_name)
    if(_may_use_same_name STREQUAL "OLD")
        set(${OUTPUT_VARIABLE} "unit_tests")
    else()
        set(${OUTPUT_VARIABLE} ${DEFAULT_VALUE})
    endif()
endmacro()

# usage example
set_unit_test_target_name(UNIT_TESTS someTestExecutable)
add_executable(${UNIT_TESTS} ... )

因此对于* NIX构建,所有可执行文件都将命名为unit_tests,并且具有其他生成器的唯一名称...