目标\为多个CMake目标编译\定义?

目标\为多个CMake目标编译\定义?,cmake,dry,idioms,compiler-options,Cmake,Dry,Idioms,Compiler Options,我发现在CMake中直接设置CFLAGS是一种不好的做法,相反,我应该使用target\u compile\u definitions()命令 好的,但是-如果我想对多个(独立)目标使用类似/相同的定义,该怎么办?我不想一次又一次地重复我自己。我看到了三种可能的方法: 首选的一种,使用它可以通过命令将编译器定义自传播到目标,具体取决于它 使用可为多个目标设置相同的定义 您仍然可以使用和的“旧命令”来修改目录属性(这将预先设置此目录范围内的所有目标属性) 工具书类 tl;dr:您可以在循环中

我发现在CMake中直接设置
CFLAGS
是一种不好的做法,相反,我应该使用
target\u compile\u definitions()
命令


好的,但是-如果我想对多个(独立)目标使用类似/相同的定义,该怎么办?我不想一次又一次地重复我自己。

我看到了三种可能的方法:

  • 首选的一种,使用它可以通过命令将编译器定义自传播到目标,具体取决于它

  • 使用可为多个目标设置相同的定义

  • 您仍然可以使用和的“旧命令”来修改目录属性(这将预先设置此目录范围内的所有目标属性)

  • 工具书类

      • tl;dr:您可以在循环中迭代目标。

        如果你有一堆具有一些共同/相似特性的目标,你可能想简单地在一个循环中操纵它们!记住——CMake不像GNU Make,它是一种成熟的脚本语言(嗯,有点像)。所以你可以写:

        set(my_targets
            foo
            bar
            baz)
        
        foreach(TARGET ${my_targets})
            add_executable(${TARGET} "${TARGET}.cu")
            target_compile_options(${TARGET} PRIVATE "--some_option=some_value")
            target_link_libraries(${TARGET} PRIVATE some_lib)
            # and so on
            set_target_properties(
                ${TARGET}
                PROPERTIES
                C_STANDARD 99
                C_STANDARD_REQUIRED YES
                C_EXTENSIONS NO )
        endforeach(TARGET)
        
        您还可以初始化一个空的目标列表,然后在这里和那里添加,最后只对所有目标集中应用您的公共选项和设置


        注意:在本例中,我添加了
        PRIVATE
        编译选项,但如果需要使用目标将其中一些选项传播到目标,可以将它们设置为
        PUBLIC
        )。

        另一个简洁的解决方案是定义接口库目标(不生成任何二进制文件的伪目标)使用所有必需的属性和编译器定义,然后针对它链接其他现有目标

        例如:

        add_library(myfakelib INTERFACE)
        target_compile_definitions(myfakelib INTERFACE MY_NEEDED_DEFINITION)
        
        add_executable(actualtarget1 main1.cpp)
        add_executable(actualtarget2 main2.cpp)
        
        set_property(
            TARGET actualtarget1 actualtarget2
            APPEND PROPERTY LINK_LIBRARIES myfakelib
        )
        
        参考文献:


        编辑了我的问题,排除了选项1——我不是这个意思。我会尝试选择2。。。它是有效的。谢谢。注意选项2。如果所有目标都在与
        set\u属性
        调用相同的目录中创建,这可能是一个好主意。现代的CMake依赖于您将设置本地化并接近目标的定义。我个人会考虑对目标属性进行“长距离”的操作。代码>在CMake中直接设置CFLAGS之类的错误做法——如果您谈论设置变量CMake_CXX_FLAGS,那么这取决于您想要设置的选项类型。无需完全避免设置变量。@Tsyvarev:添加了一个视频链接。@einpoklum对于我们的内部构建系统,我们公司的每个人都在所有构建中使用,我们直接设置
        CMAKE\u CXX\u标志
        ,因此它们对于所有目标都是相同的。在我们的情况下,这是有道理的。如果您希望开放项目的源代码,并让其他人通过ExternalProject使用您的CmakeList,那么这样做将被视为不好的做法,因为您将构建标志强加给您的用户。这取决于你的爱好situation@SteveLorimer-
        。。。让其他人通过ExternalProject使用您的CmakeList,那么这样做将被视为不好的做法
        -ExternalProject不会影响project的
        CMAKE\u CXX\u标志
        。你是说改为添加_子目录吗?@SteveLorimer:实际上,在第二个问题上,请注意,无论其他人是否通过ExternalProject使用您的CmakeList,或者只是用户在构建它,这都是不好的做法,因为如果用户使用不同的C/C++编译器和不同的标志语法,那么您可能会被任何一种方式搞砸。它必须是接口库目标吗?它难道不是某种普通的人造目标吗?另外,库目标会传播C语言属性吗?任何库目标都会传播属性,“接口”类型实际上是一种“人工”类型,不会产生任何二进制文件,正如我所提到的