Installation 使用CMake,我如何处理文件并安装它们

Installation 使用CMake,我如何处理文件并安装它们,installation,cmake,Installation,Cmake,我是CMake的新手,我有一个无法解决的问题。我正在使用CMake编译一个包含一堆可选子目录的项目,它会按照预期构建共享库文件。那部分似乎很好用。每个子目录都包含一个sql文件。我需要将所有选定的sql文件合并到一个sql头文件中,然后安装结果。所以有一个文件是这样的: sql_header.sql sub_dir_A.sql sub_dir_C.sql sub_dir_D.sql 如果我直接在make文件中执行此操作,我可能会执行以下类似操作,以便只处理选定的子目录: cat sql_hea

我是CMake的新手,我有一个无法解决的问题。我正在使用CMake编译一个包含一堆可选子目录的项目,它会按照预期构建共享库文件。那部分似乎很好用。每个子目录都包含一个sql文件。我需要将所有选定的sql文件合并到一个sql头文件中,然后安装结果。所以有一个文件是这样的:

sql_header.sql
sub_dir_A.sql
sub_dir_C.sql
sub_dir_D.sql
如果我直接在make文件中执行此操作,我可能会执行以下类似操作,以便只处理选定的子目录:

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")
我假设我可以将其放置在每个sub dirs CMakeLists.txt文件中以收集文件名。我可以创建一个宏,如:

CAT(IN "${PACKAGE_SQL_FILES}" OUT "${INSTALL_PATH}/somefile.sql")
但我在CMake最初运行和从make安装运行之间迷失了方向。也许有更好的办法。我需要这个在Windows和Linux上工作


我很乐意得到一些提示,为我指明正确的方向。

您可以主要使用CMake和命令创建连接文件

首先,创建一个
cat
函数:

功能(cat输入文件输出文件)
文件(读取${IN_file}内容)
文件(附加${OUT\u file}“${CONTENTS}”)
endfunction()
假设变量
PACKAGE\u SQL\u files
中有输入文件列表,则可以使用如下函数:

#准备一个临时文件“cat”以:
文件(将somefile.sql.in写入“”)
#为每个输入文件调用“cat”函数
foreach(包\u SQL\u文件${PACKAGE\u SQL\u文件})
cat(${PACKAGE\u SQL\u FILE}somefile.SQL.in)
endforeach()
#将临时文件复制到最终位置
配置_文件(somefile.sql.in somefile.sql COPYONLY)
写入临时文件的原因是,只有当实际目标文件的内容发生更改时,才会更新该文件。看看为什么这是件好事

您应该注意,如果您通过
add_subdirectory
命令包含子目录,那么就CMake变量而言,子目录都有自己的作用域。在子目录中,使用
列表
只会影响该子目录范围内的变量

如果要创建父作用域中可用的列表,则需要使用,例如

到目前为止,所有这些都只是在构建树的根目录中创建了连接文件。要安装它,您可能需要使用以下命令:


因此,每当CMake运行时(因为您手动调用它,或者因为您执行“make”时它检测到更改),它都会更新构建树中的连接文件。只有运行“make install”后,文件才会最终从生成根目录复制到安装位置。

从CMake 3.18开始,CMake可以使用
cat
连接文件。因此,假设变量
PACKAGE\u SQL\u FILES
包含文件列表,可以使用以下命令运行
cat
命令:

解决方案的其余部分与弗雷泽的回答类似。您可以使用
configure_file
,以便只在必要时更新生成的文件

configure_file(final.sql.in final.sql COPYONLY)
您仍然可以使用
install
以相同的方式安装文件:

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/final.sql
    DESTINATION ${INSTALL_PATH})

很好地使用了configure_文件…;-)谢谢,这很有帮助。如果你有多个深度的多个目录,那么很难得到冒泡的结果,但是我使用了你非常有用的建议。谢谢我试过这个,它成功了。。。除非文件有分号,否则它会失败,因为分号会被自动删除。这是分号作为cmake中的列表分隔符的正常结果。显示问题的最简单测试用例是
set(CONTENTS“a;b;c\n”)文件(WRITE out.txt${CONTENTS})
修复方法是在编写时引用内容,例如
“${CONTENTS}”
cmake-ecat
在cmake3.17.3中不起作用。也许它只在更新版本的cmake?@amphetamachine中可用,正如我在回复中指定的,这在cmake版本3.18和更高版本中可用。版本3.17.3是比3.18更早的版本,因此它没有此功能。
# Concatenate the sql files into a variable 'FINAL_FILE'.
execute_process(COMMAND ${CMAKE_COMMAND} -E cat ${PACKAGE_SQL_FILES}
    OUTPUT_VARIABLE FINAL_FILE
    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
)
# Write out the concatenated contents to 'final.sql.in'.
file(WRITE final.sql.in ${FINAL_FILE})
configure_file(final.sql.in final.sql COPYONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/final.sql
    DESTINATION ${INSTALL_PATH})