CMake:如何对多个文件运行自定义命令以生成源文件?
我有以下情况:我想将多个Scheme文件编译成一个可执行文件。为此,我使用gambit将所有Scheme文件转换/生成为C和对象文件,然后编译并链接到可执行文件中 假设我有以下三个文件(示例取自Gambit文档): EDIT:记住最后一个命令,这不是打字错误,最后一步是使用CMake:如何对多个文件运行自定义命令以生成源文件?,c,cmake,scheme,C,Cmake,Scheme,我有以下情况:我想将多个Scheme文件编译成一个可执行文件。为此,我使用gambit将所有Scheme文件转换/生成为C和对象文件,然后编译并链接到可执行文件中 假设我有以下三个文件(示例取自Gambit文档): EDIT:记住最后一个命令,这不是打字错误,最后一步是使用gcc进行链接 现在,我希望使用CMake为我做这件事。下面是我的CMakeLists.txt的概要: cmake_minimum_required( VERSION 3.8...3.18 ) if( ${CMAKE_VER
gcc
进行链接
现在,我希望使用CMake为我做这件事。下面是我的CMakeLists.txt
的概要:
cmake_minimum_required( VERSION 3.8...3.18 )
if( ${CMAKE_VERSION} VERSION_LESS 3.12 )
cmake_policy( VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} )
endif()
# Give this project a name
project( schemetemplate VERSION 0.0.1 )
# compile all .scm files into *.c files
# the C files as target
add_custom_target(
compiledSchemeFiles ALL
SOURCES m2.scm
m3.scm
COMMAND # this is where I call gsc(?)
VERBATIM )
# or do I use custom command?
add_custom_command( ... )
# the final executable, how to tell add_executable I want all generated files as dependency?
add_exectuable( finalexec m1.c ...)
除了纯C/C++项目,我从未与CMake合作过。最聪明的方法是什么?最终,我希望有一个
CMakeLists.txt
,我可以把我所有的Scheme文件放在一个子目录中,让它生成所有的C和object文件,并让父目录中的CMake使用它们创建可执行文件和库,使用add_executable
和add_library
可以定义scm源文件,然后为每个源文件创建自定义_命令。这将为每个.scm文件创建一个.c文件。可以将创建的文件添加到列表中(例如,命名的scm_c_文件),并在“添加可执行文件”命令中使用。最后,可以使用目标链接库定义所使用的库
我不知道gsc和相应的增量链接文件是如何工作的,但如果您可以为增量链接文件指定一个自定义名称(是否有某种-o选项?),它将只是另一个add_custom_命令,它仅依赖于从.scm文件生成的.c文件
例如,类似这样的事情:
add_custom_command(
OUTPUT incLink.c
gsc -link ${scm_c_files} -o incLink.c
DEPENDS ${scm_c_files}
)
cmake_minimum_required(VERSION 3.17)
project(finalexec C)
set(CMAKE_C_STANDARD 99)
set(SCM_SOURCES m2.scm m3.scm)
set(scm_c_files)
foreach(scm_source ${SCM_SOURCES})
get_filename_component(file_c ${scm_source} NAME_WE)
set(file_c "${file_c}.c")
add_custom_command(
OUTPUT ${file_c}
COMMAND gsc -c ${CMAKE_CURRENT_SOURCE_DIR}/${scm_source}
DEPENDS ${scm_source}
VERBATIM
)
list(APPEND scm_c_files ${file_c})
endforeach()
add_custom_command(
OUTPUT incLink.c
COMMAND gsc -link ${scm_c_files} -o incLink.c
DEPENDS ${scm_c_files}
)
add_executable(finalexec m1.c ${scm_c_files} incLink.c)
target_link_libraries(finalexec gambit m dl util)
完整的CMakeLists.txt可能如下所示:
add_custom_command(
OUTPUT incLink.c
gsc -link ${scm_c_files} -o incLink.c
DEPENDS ${scm_c_files}
)
cmake_minimum_required(VERSION 3.17)
project(finalexec C)
set(CMAKE_C_STANDARD 99)
set(SCM_SOURCES m2.scm m3.scm)
set(scm_c_files)
foreach(scm_source ${SCM_SOURCES})
get_filename_component(file_c ${scm_source} NAME_WE)
set(file_c "${file_c}.c")
add_custom_command(
OUTPUT ${file_c}
COMMAND gsc -c ${CMAKE_CURRENT_SOURCE_DIR}/${scm_source}
DEPENDS ${scm_source}
VERBATIM
)
list(APPEND scm_c_files ${file_c})
endforeach()
add_custom_command(
OUTPUT incLink.c
COMMAND gsc -link ${scm_c_files} -o incLink.c
DEPENDS ${scm_c_files}
)
add_executable(finalexec m1.c ${scm_c_files} incLink.c)
target_link_libraries(finalexec gambit m dl util)
测试
因为我没有gsc,我只是用一个echo和一个touch替换了自定义命令。如果我跑
cmake .
make
我得到的结果是:
[ 12%] Generating m3.c
gsc -c /Users/stephan/kk/m3.scm
[ 25%] Generating m2.c
gsc -c /Users/stephan/kk/m2.scm
[ 37%] Generating incLink.c
gsc -link m2.c m3.c -o incLink.c
[ 50%] Building C object CMakeFiles/finalexec.dir/m1.c.o
[ 62%] Building C object CMakeFiles/finalexec.dir/m2.c.o
[ 75%] Building C object CMakeFiles/finalexec.dir/m3.c.o
[ 87%] Building C object CMakeFiles/finalexec.dir/incLink.c.o
[100%] Linking C executable finalexec
[100%] Built target finalexec
这似乎就是你要找的。你真的需要一个单独的
-obj
步骤吗?谢谢,这很有效!我在掌握CMake book中找到了类似的解决方案,但更好!