2013-03-07 4 views
8

Я новичок в CMake, и у меня есть проблема, из-за которой я не могу найти решение. Я использую CMake для компиляции проекта с кучей дополнительных поддиректоров, и он, как и ожидалось, строит файлы общей библиотеки. Эта часть, похоже, работает нормально. Каждый из этих поддиректоров содержит файл sql. Мне нужно выполнить все выбранные файлы sql в один файл заголовка sql и установить результат. Так один файл, как:Использование CMake, как я могу конкатенировать файлы и устанавливать их

sql_header.sql 
sub_dir_A.sql 
sub_dir_C.sql 
sub_dir_D.sql 

Если бы я сделал это непосредственно в замыкающий файл я мог бы сделать что-то вроде следующего только умнее, чтобы иметь дело только с выбранным суб-директорий:

cat sql_header.sql > "${INSTALL_PATH}/somefile.sql" 
cat sub_dir_A.sql >> "${INSTALL_PATH}/somefile.sql" 
cat sub_dir_C.sql >> "${INSTALL_PATH}/somefile.sql" 
cat sub_dir_D.sql >> "${INSTALL_PATH}/somefile.sql" 

У меня есть своего рода из выяснял куски этого, как я могу использовать:

LIST(APPEND PACKAGE_SQL_FILES "some_file.sql") 

, который я предполагаю, что я могу разместить в каждом из файлов суб-каталоги CMakeLists.txt собирать имена файлов. И я могу создать макрос, как:

CAT(IN "${PACKAGE_SQL_FILES}" OUT "${INSTALL_PATH}/somefile.sql") 

Но я теряюсь, когда между CMake изначально работает и когда он работает от марки установки. Возможно, есть лучший способ сделать это. Мне нужно это для работы как в Windows, так и в Linux.

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

ответ

10

Вы можете создать объединенный файл главным образом с помощью команд CMake и function.

Во-первых, создать cat функцию:

function(cat IN_FILE OUT_FILE) 
    file(READ ${IN_FILE} CONTENTS) 
    file(APPEND ${OUT_FILE} "${CONTENTS}") 
endfunction() 

Если у вас есть список входных файлов в переменной PACKAGE_SQL_FILES, вы можете использовать функцию следующим образом:

# Prepare a temporary file to "cat" to: 
file(WRITE somefile.sql.in "") 

# Call the "cat" function for each input file 
foreach(PACKAGE_SQL_FILE ${PACKAGE_SQL_FILES}) 
    cat(${PACKAGE_SQL_FILE} somefile.sql.in) 
endforeach() 

# Copy the temporary file to the final location 
configure_file(somefile.sql.in somefile.sql COPYONLY) 

Поводом для написания к временному, так что реальный целевой файл обновляется только в том случае, если его содержимое изменилось. См. this answer, почему это хорошо.

Следует отметить, что если вы включаете подкаталоги с помощью команды add_subdirectory, все поддиры имеют свою собственную область действия в отношении переменных CMake. В поддирелях использование list повлияет только на переменные в объеме этого субдира.

Если вы хотите создать список, доступный в родительской области, вам нужно будет использовать set(... PARENT_SCOPE), например.

set(PACKAGE_SQL_FILES 
    ${PACKAGE_SQL_FILES} 
    ${CMAKE_CURRENT_SOURCE_DIR}/some_file.sql 
    PARENT_SCOPE) 

Все это до сих пор просто создало конкатенированный файл в корне дерева сборки. Чтобы установить его, вы, вероятно, хотите использовать install(FILES ...) команду:

install(FILES ${CMAKE_BINARY_DIR}/somefile.sql 
     DESTINATION ${INSTALL_PATH}) 

Таким образом, всякий раз, когда запускается CMake (либо потому, что вы вручную вызвать его или потому, что он обнаруживает изменения, когда вы «сделать»), то она обновит каскадный файл в дереве сборки. Только после запуска «make install» файл, наконец, будет скопирован из корня сборки в место установки.

+0

Приятное использование configure_file ... ;-) – DLRdave

+0

Спасибо, это было очень полезно.Это сложно сделать, чтобы получить результаты, если у вас несколько каталогов на нескольких глубинах, но я получил его для работы, используя ваши очень полезные советы. Благодаря! –

+0

Я пробовал это, и это сработало ... если у файла нет точек с запятой, после чего он терпит неудачу, потому что точки с запятой молча стираются. Это нормальное следствие того, что точки с запятой являются разделителями списков в cmake. Простой тестовый пример, показывающий проблему, - 'set (CONTENTS" a; b; c \ n ") файл (WRITE out.txt $ {СОДЕРЖАНИЕ})' Исправление заключается в цитировании содержимого при записи, например. '' $ {CONTENTS} "' –

Смежные вопросы