Regla genérica de makefile a CMake

Estoy tratando de “traducir” las líneas fluidas de makefile de vainilla en la syntax de CMake.

SRCS = $(wildcard *.foo) OBJS = $(SRCS:.foo=.bar) my_rule: $(OBJS) %.bar: %.foo make_bar_from_foo $@ $< 

Trabajo feo bash

 FILE(GLOB SRCS "*.foo") SET(outFiles) FOREACH(SRC ${SRCS}) SET(OUTPUT_FILE_NAME "${SRC}.bar") ADD_CUSTOM_COMMAND( OUTPUT "${OUTPUT_FILE_NAME}" COMMAND make_bar_from_foo ${SRC} ${OUTPUT_FILE_NAME} DEPENDS "${SRC}") SET(outFiles ${outFiles} "${OUTPUT_FILE_NAME}") ENDFOREACH(SRC) ADD_CUSTOM_TARGET(my_rule ALL DEPENDS ${outFiles}) 

Entiendo que va a generar un comando por archivo en lugar de generar algo genérico. ¿Alguna forma más simple / limpia de hacerlo?

En CMake, siempre puede declarar su propio lenguaje de comstackción. Entonces, en su caso, puede hacer, por ejemplo:

 cmake_minimum_required(VERSION 2.8) project(MakeBarFromFoo NONE) set( CMAKE_FOO_COMPILE_OBJECT "make_bar_from_foo  " ) file(GLOB SRCS "*.foo") add_library(my_rule OBJECT ${SRCS}) set_source_files_properties(${SRCS} PROPERTIES LANGUAGE FOO) 

Luego puede simplemente trabajar con él como lo haría con otros objetos de la biblioteca de objetos . Pero solo obtendrá cosas como la extensión .bar si enable_language(FOO) (y eso requiere más trabajo, consulte a continuación).

Los ejemplos entregados con CMake son comstackdores ASM o RC .


La enable_language(FOO)

Esto necesita cuatro archivos más que podría poner, por ejemplo, la carpeta CMake su proyecto:

CMake \ CMakeDetermineFOOCompiler.cmake

 # Find the compiler find_program( CMAKE_FOO_COMPILER NAMES "make_bar_from_foo" HINTS "${CMAKE_SOURCE_DIR}" DOC "FOO compiler" ) mark_as_advanced(CMAKE_FOO_COMPILER) set(CMAKE_FOO_SOURCE_FILE_EXTENSIONS foo;FOO) set(CMAKE_FOO_OUTPUT_EXTENSION .bar) set(CMAKE_FOO_COMPILER_ENV_VAR "FOO") # Configure variables set in this file for fast reload later on configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeFOOCompiler.cmake.in ${CMAKE_PLATFORM_INFO_DIR}/CMakeFOOCompiler.cmake) 

CMake \ CMakeFOOCompiler.cmake.in

 set(CMAKE_FOO_COMPILER "@CMAKE_FOO_COMPILER@") set(CMAKE_FOO_COMPILER_LOADED 1) set(CMAKE_FOO_SOURCE_FILE_EXTENSIONS @CMAKE_FOO_SOURCE_FILE_EXTENSIONS@) set(CMAKE_FOO_OUTPUT_EXTENSION @CMAKE_FOO_OUTPUT_EXTENSION@) set(CMAKE_FOO_COMPILER_ENV_VAR "@CMAKE_FOO_COMPILER_ENV_VAR@") 

CMake \ CMakeFOOInformation.cmake

 # This file sets the basic flags for the FOO compiler if(NOT CMAKE_FOO_COMPILE_OBJECT) set(CMAKE_FOO_COMPILE_OBJECT "  ") endif() set(CMAKE_FOO_INFORMATION_LOADED 1) 

CMake \ CMakeTestFOOCompiler.cmake

 # For now just do nothing in here set(CMAKE_FOO_COMPILER_WORKS 1 CACHE INTERNAL "") 

Entonces su archivo CMakeLists.txt ve así:

CMakeLists.txt

 cmake_minimum_required(VERSION 2.8) project(MakeBarFromFoo NONE) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake") enable_language(FOO) file(GLOB SRCS "*.foo") add_library(my_rule OBJECT ${SRCS}) 

Tu bash es correcto y difícilmente puede mejorarse significativamente.

Así es como funciona CMake: cada una de sus “reglas” es concreta; no puedes crear una “regla de plantilla”. El motivo es la independencia de la plataforma : no todos los sistemas de comstackción admiten “plantillas” para las reglas.

Por otro lado, CMake admite la creación de las “reglas” dentro de las funciones / macros. Entonces, escribir partes repetidas se puede reducir fácilmente.

En general, con CMake no comstack todos los archivos de objeto. Simplemente agregue los archivos .foo correctos en los comandos CMake correctos ( add_library o add_executable ) y CMake lo manejará por usted.

CMake es mucho más potente en comparación con la marca simple. Pero debes aceptar que este poder viene con un cambio en cómo usas la herramienta.