¿Cómo itero sobre todos los objetivos de CMake mediante programación?

7 minutos de lectura

avatar de usuario
aprendervst

¿Hay alguna forma de obtener todos los objetivos de un proyecto de CMake desde el nivel superior? CMakeLists.txtes decir, iterar sobre los objetivos programáticamente?

La razón por la que quiero hacer esto es para aplicar algunas configuraciones específicas de XCode a cada objetivo. .

if (CMAKE_GENERATOR MATCHES "Xcode")
    include(sanitize_xcode)
    sanitize_xcode(myTarget)
endif()

FYI: el módulo de desinfección se ve así. .

macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
    set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
endmacro (set_xcode_property)

macro (sanitize_xcode TARGET)
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=MinSizeRel] "NO")
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=RelWithDebInfo] "YES")
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "NO")

    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=Debug] "NO")
    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=MinSizeRel] "YES")
    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=RelWithDebInfo] "NO")
    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=Release] "YES")

    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=Debug] "0")
    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=MinSizeRel] "s")
    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=RelWithDebInfo] "3")
    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=Release] "3")

    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=Debug] "7.0")
    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=MinSizeRel] "7.0")
    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=RelWithDebInfo] "7.0")
    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=Release] "7.0")
endmacro (sanitize_xcode)

  • ¿Quiere decir iterar los objetivos en su secuencia de comandos cmake mediante programación?

    – Tamás Szelei

    25 de mayo de 2016 a las 11:19


  • ¿Con qué propósito? (Oler un problema XY.) Cualquier cosa que quieras hacer probablemente se haga mejor en CMakeLists.txt.

    – DevSolar

    25 mayo 2016 a las 11:33


  • @DevSolar ver ediciones.

    – aprendervst

    25 de mayo de 2016 a las 11:38

  • ¿Puede por favor también dar el código para sanitize_xcode()? agregas POST_BUILD pasos o simplemente agrega opciones de compilador? Si es más tarde, no habrá necesidad de iterar sobre todos los objetivos.

    – Florián

    25 mayo 2016 a las 12:42

  • Gracias. solo mirando XCODE_ATTRIBUTE_<an-attribute> propiedad de destino ¿no sería suficiente establecer el equivalente CMAKE_XCODE_ATTRIBUTE_<an-attribute> variables en el nivel raíz para ser aplicadas a todos los objetivos?

    – Florián

    25 mayo 2016 a las 14:01


avatar de usuario
ceztko

En corrección a la respuesta de Florian, BUILDSYSTEM_TARGETS no es realmente una propiedad global sino una directorio uno con alcance. Una solicitud de mejora está actualmente abierto para solicitar una propiedad verdaderamente global. Utilizando SUBDIRECTORIOS propiedad es posible recuperar recursivamente todos los objetivos en el ámbito del directorio actual con la siguiente función:

function(get_all_targets var)
    set(targets)
    get_all_targets_recursive(targets ${CMAKE_CURRENT_SOURCE_DIR})
    set(${var} ${targets} PARENT_SCOPE)
endfunction()

macro(get_all_targets_recursive targets dir)
    get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
    foreach(subdir ${subdirectories})
        get_all_targets_recursive(${targets} ${subdir})
    endforeach()

    get_property(current_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
    list(APPEND ${targets} ${current_targets})
endmacro()

get_all_targets(all_targets)
message("All targets: ${all_targets}")

  • Oh dios, te amo, esto resolvió un problema que me atrapó todo el día. +1

    – duende

    28 de marzo de 2021 a las 19:52


  • Esto es genial, había estado buscando una manera de hacer esto durante mucho tiempo, pero básicamente me había dado por vencido.

    – Andrés W.

    22 de abril de 2021 a las 5:55

  • Cabe señalar que esta solución producirá una lista de realmente todos destinos, incluidos aquellos que se han excluido explícitamente de “todos” mediante: add_executable(some_target EXCLUDE_FROM_ALL some_target.c) Esto es realmente útil para agregar un objetivo que construirá realmente todoincluyendo incluso los objetivos excluidos: add_custom_target(really_all DEPENDS ${all_targets})

    – n0dus

    25 de febrero a las 11:12


avatar de usuario
florián

Convirtiendo mi comentario en una respuesta.

Tener una lista de todos los objetivos es un deseo que ha existido por un tiempo, pero la propiedad global TARGETS aún no está implementado (a partir de mayo de 2016, consulte la discusión “Listado de todos los objetivos”).

Editar: Ya está implementado: Global BUILDSYSTEM_TARGETS la propiedad se lanzó con CMake 3.7

Por lo tanto, puede implementar esto usted mismo utilizando el script CMake en sí mismo, como @DevSolar como comentado/respondido o como aquí, pero a lo largo del tiempo he aprendido que también puede cambiar muchas propiedades de destino a nivel mundial. Por ejemplo, la mayoría de las propiedades de destino tienen por defecto una configuración de variable global equivalente.

Puede aprovechar esto en su caso y resolverlo agregando lo siguiente a su global CMakeLists.txt expediente:

set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=MinSizeRel] "NO")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=RelWithDebInfo] "YES")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "NO")

set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=MinSizeRel] "YES")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=RelWithDebInfo] "NO")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Release] "YES")

set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=Debug] "0")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=MinSizeRel] "s")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=RelWithDebInfo] "3")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=Release] "3")

set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=Debug] "7.0")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=MinSizeRel] "7.0")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=RelWithDebInfo] "7.0")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=Release] "7.0")

Referencias

  • no, mundial BUILDSYSTEM_TARGETS no se ha agregado, es una propiedad del directorio. Hay un rfe para eso

    – ceztko

    10 de junio de 2020 a las 17:29


  • Utilizando BUILDSYSTEM_TARGETS y SUBDIRECTORIES es posible recuperar recursivamente los objetivos definidos en el ámbito del directorio actual. Mira mi respuesta.

    – ceztko

    10 de junio de 2020 a las 19:17

Si desea repasar una lista de objetivos, configure su CMakeLists.txt hasta proveer esa lista en primer lugar.

if ( CMAKE_GENERATOR MATCHES "Xcode" )
    include(sanitize_xcode)
endif()

# A list of executables to build
set( project_EXECUTABLES
     foo
     bar
   )

# List of sources for each executable, following some naming scheme

# foo
set( EXE_foo_SOURCES
     foo/main.c
   )

# bar
set( EXE_bar_SOURCES
     bar/main.c
   )

# For each executable in the list...
foreach( exe ${project_EXECUTABLES} )
    # declare the target...
    add_executable( ${exe} ${EXE_${exe}_SOURCES} )

    # ...and do whatever additional configuration you need
    if ( CMAKE_GENERATOR MATCHES "Xcode" )
        sanitize_xcode( ${exe} )
    endif()
endforeach()

  • Generalmente me pareció un buen truco tener una serie de set() comandos al principio, configurando todo y haciendo toda la “magia” al final. Realmente, en mi marco CMake reutilizableYO solamente hacer set()está en mi CMakeLists.txty luego include() un archivo con toda la “magia”. Si agrego/cambio archivos fuente, solo “toco” el CMakeLists.txt, si modifico la “magia” “toco” un archivo diferente. Más fácil de mantener, en mi humilde opinión.

    – DevSolar

    25 mayo 2016 a las 11:49

  • Esta no es una respuesta ya que la lista de objetivos puede ser desconocida/impredecible.

    – ceztko

    19 de agosto de 2020 a las 11:26

  • @ceztko: 1) Si tu lista de objetivos es impredecible, tienes otros problemas. 2) La respuesta muestra un camino para tener una lista de objetivos configurados para iterar. 3) BUILDSYSTEM_TARGETS se presentó hace medio año después Florian y yo escribimos nuestras respuestas (iniciales), por lo que no puede culparnos por no haberlas utilizado cuando escribimos nuestras respuestas. En su momento, estos fueron las respuestas a la pregunta. La aparición posterior de mejores mecánicas puede hacer que esta respuesta sea un poco obsoleta, pero “no es una respuesta” no se requiere.

    – DevSolar

    19 de agosto de 2020 a las 12:03


  • @ceztko: Oh, creo que ahora lo entiendo. Tiene CMakeLists.txt en subdirectorios también, y es por eso que considera que la lista de objetivos es “desconocida / impredecible”? Bueno, yo no hago eso, viniendo de la escuela de pensamiento “recursiva que se considera dañina”, teniendo solo un CMakeLists.txt de nivel superior. Así que estamos trabajando desde diferentes suposiciones aquí.

    – DevSolar

    19 de agosto de 2020 a las 18:54

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad