Общее правило от make-файла до CMake

Я пытаюсь "перевести" текущие строки ванильного make-файла в синтаксис CMake.

SRCS = $(wildcard *.foo)
OBJS = $(SRCS:.foo=.bar)

my_rule: $(OBJS)

%.bar: %.foo
    make_bar_from_foo  $@  $<

Рабочая безобразная попытка

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})

Я понимаю, что он будет генерировать одну команду на файл вместо чего-то общего. Любой самый простой / чистый способ сделать это?

3 ответа

Решение

В CMake вы всегда можете объявить свой собственный язык компилятора. Так что в вашем случае вы можете, например, сделать:

cmake_minimum_required(VERSION 2.8)

project(MakeBarFromFoo NONE)

set(
   CMAKE_FOO_COMPILE_OBJECT 
       "make_bar_from_foo <SOURCE> <OBJECT>"
)

file(GLOB SRCS "*.foo")
add_library(my_rule OBJECT ${SRCS})
set_source_files_properties(${SRCS} PROPERTIES LANGUAGE FOO)

Тогда вы можете просто работать с ним так же, как с другими объектами библиотеки объектов. Но вы получите только такие вещи, как .bar расширение, если вы enable_language(FOO) (и это требует больше работы, см. ниже).

Примеры, поставляемые с самим CMake: ASM или же RC компиляторы.


enable_language(FOO) Версия

Для этого нужно добавить еще четыре файла, например, ваш проект CMake папка:

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 "<CMAKE_FOO_COMPILER> <SOURCE> <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 "")

Тогда ваш CMakeLists.txt Файл просто выглядит так:

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})

Ваша попытка верна, и вряд ли она может быть значительно улучшена.

Именно так работает CMake: каждое из его "правил" является конкретным; Вы не можете создать "шаблонное правило". Причиной этого является независимость от платформы: не все системы сборки поддерживают "шаблоны" для правил.

С другой стороны, CMake поддерживает создание "правил" внутри функций / макросов. Таким образом, набор повторяющихся частей может быть легко уменьшен.

В общем, с CMake вы не строите все объектные файлы. Просто добавьте право .foo файлы в правильные команды CMake (add_library или же add_executable) и CMake с этим справится.

CMake намного мощнее по сравнению с обычными марками. Но вы должны признать, что эта сила зависит от того, как вы используете инструмент.

Другие вопросы по тегам