【问题标题】:How to prepend ${CMAKE_CURRENT_SOURCE_DIR} to all files in variable?如何将 ${CMAKE_CURRENT_SOURCE_DIR} 添加到变量中的所有文件?
【发布时间】:2012-10-27 18:36:46
【问题描述】:

我有带有子目录的项目,我想将每个目录的源列表分开。

我有:

SET( SUBDIR_SOURCES
  ${CMAKE_CURRENT_SOURCE_DIR}/a.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/b.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/c.cpp
  PARENT_SCOPE
)

我想要:

SET( SUBDIR_SOURCES
  a.cpp
  b.cpp
  c.cpp
  PARENT_SCOPE
)
some_magic_fuction( SUBDIR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR} )

【问题讨论】:

    标签: cmake


    【解决方案1】:

    我通常为每个子目录写一个小的CMakeLists.txt,它将那个目录中的所有文件编译成一个库。

    在父目录的CMakeLists.txt 中,我用add_subdirectory( blah ) 添加每个子目录。

    如果你必须有一个指定的变量,以下应该可以工作(注意,我还没有实际测试过):

    MACRO( prepend_path _srcs _path )
        unset( _tmp )
        foreach( src ${_srcs} )
            list( append _tmp ${_path}/${src} )
        endforeach( src ${_srcs} )
        set( _srcs ${_tmp} )
    ENDMACRO( prepend_path _srcs )
    

    这样称呼它:

    prepend_path( SUBDIR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR} )
    

    【讨论】:

    • "我通常为每个子目录写一个小的 CMakeLists.txt,它将那个目录中的所有文件编译成一个库。"我也这样做,我发现它更容易处理。
    • @drescherjm 是的 - 我应该更清楚。这 一种处理子目录的常见(和正确)方式,但按照 OP 建议的方式进行操作并不一定是错误的。但是,我的观点是,显示的代码 sn-p 在几个方面是不正确的。
    【解决方案2】:

    对于要传递源列表的some_magic_function,首先您需要避免将它们设置在PARENT_SCOPE 中,因为它们在子目录的CMakeList 范围内不可用。

    您也不需要将${CMAKE_CURRENT_SOURCE_DIR} 传递给函数,因为无论函数本身在何处定义,它都可以在函数内部使用。

    所以你可以这样做:

    SET( SUBDIR_SOURCES a.cpp b.cpp c.cpp )
    some_magic_function( SUBDIR_SOURCES )
    SET( SUBDIR_SOURCES ${SUBDIR_SOURCES} PARENT_SCOPE )
    

    函数可以是:

    FUNCTION( some_magic_function SOURCE_FILES )
      FOREACH( SOURCE_FILE ${${SOURCE_FILES}} )
        SET( MODIFIED ${MODIFIED} ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} )
      ENDFOREACH()
      SET( ${SOURCE_FILES} ${MODIFIED} PARENT_SCOPE )
    ENDFUNCTION()
    

    在函数内部,${SOURCE_FILES}SUBDIR_SOURCES,所以我们需要使用${${SOURCE_FILES}}来获取实际的文件列表。

    函数有自己的作用域,所以由于我们要在函数外的作用域内替换SUBDIR_SOURCES的值,所以在调用SET( ${SOURCE_FILES}...时需要使用PARENT_SCOPE

    有关这些命令的更多信息,请运行:

    cmake --help-command set
    cmake --help-command function
    

    【讨论】:

      【解决方案3】:

      我通常也更喜欢具有自己的局部变量范围的函数,但在您的情况下,我建议您编写自己的宏命令。

      因此,使用 Fraser 的代码如下所示:

      macro( set_subdir_sources )
          foreach( SOURCE_FILE ${ARGN} )
              set( SUBDIR_SOURCES ${SUBDIR_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} )
          endforeach()
          set( SUBDIR_SOURCES ${SUBDIR_SOURCES} PARENT_SCOPE )
      endmacro()
      

      或者使用相对路径:

      macro( set_subdir_sources )
          get_directory_property( _PARENTDIR PARENT_DIRECTORY )
          file( RELATIVE_PATH _SUBDIR ${_PARENTDIR} ${CMAKE_CURRENT_SOURCE_DIR} )
          foreach( SOURCE_FILE ${ARGN} )
              set( SUBDIR_SOURCES ${SUBDIR_SOURCES} ${_SUBDIR}/${SOURCE_FILE} )
          endforeach()
          set( SUBDIR_SOURCES ${SUBDIR_SOURCES} PARENT_SCOPE )
      endmacro()
      

      然后打电话:

      set_subdir_sources( a.cpp b.cpp c.cpp )
      

      你的父母CMakeLists.txt 无论如何都必须知道SUBDIR_SOURCES 变量。这还有一个好处是您可以在子目录的CMakeLists.txt 中多次调用它。

      但是你真的需要一个CMakeLists.txt 在一个没有首先定义它自己的目标的子目录中吗?我只是将源添加到您的父目录CMakeLists.txt

      set( 
        SUBDIR_SOURCES
        SubDir/a.cpp
        SubDir/b.cpp
        SubDir/c.cpp
      )
      

      另见CMakeLists.txt files for multiple libraries and executables

      【讨论】:

        猜你喜欢
        • 2013-09-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-28
        • 2012-12-16
        • 2021-12-27
        • 2018-04-27
        • 2019-12-17
        • 1970-01-01
        相关资源
        最近更新 更多