如何在CMake中为Gambit Scheme自定义编译器添加额外编译步骤
I’ve dealt with similar headaches when hooking non-standard compilers into CMake—its built-in compiler modules are tailored for traditional C/C++ workflows, so they don’t play nicely with Gambit’s unique multi-file pipeline. Here’s a practical, reliable way to replicate your manual compilation steps in CMake, ensuring the link file generation and object compilation run once in the correct order:
Step 1: Compile Scheme Sources to C Files
First, we’ll handle converting each Scheme source to a C file individually, replacing the single-file behavior of CMAKE_Gambit_COMPILE_OBJECT with explicit per-source control:
# List all your Scheme source files set(SCHEME_SOURCES factmodule.scm main.scm) # Generate C files from each Scheme source set(GENERATED_C_SOURCES "") foreach(SRC_FILE ${SCHEME_SOURCES}) get_filename_component(C_FILE ${SRC_FILE} NAME_WE) set(C_FILE "${C_FILE}.c") add_custom_command( OUTPUT ${C_FILE} COMMAND gambitc -c ${SRC_FILE} DEPENDS ${SRC_FILE} COMMENT "Compiling Scheme source ${SRC_FILE} to C" ) list(APPEND GENERATED_C_SOURCES ${C_FILE}) endforeach()
Step 2: Generate the Gambit Link File
Next, add a custom command to create link_file.c. This step will only run once all initial C files are ready, thanks to the dependency on GENERATED_C_SOURCES:
add_custom_command( OUTPUT link_file.c COMMAND gambitc -o link_file.c -link ${GENERATED_C_SOURCES} DEPENDS ${GENERATED_C_SOURCES} COMMENT "Generating Gambit link file" ) # Add the link file to our list of C sources to compile list(APPEND GENERATED_C_SOURCES link_file.c)
Step 3: Compile All C Files to Object Files
Now compile every generated C file (including the link file) into object files, mirroring your manual workflow:
set(GENERATED_OBJS "") foreach(C_FILE ${GENERATED_C_SOURCES}) get_filename_component(OBJ_FILE ${C_FILE} NAME_WE) set(OBJ_FILE "${OBJ_FILE}.o") add_custom_command( OUTPUT ${OBJ_FILE} COMMAND gambitc -obj ${C_FILE} DEPENDS ${C_FILE} COMMENT "Compiling C source ${C_FILE} to object" ) list(APPEND GENERATED_OBJS ${OBJ_FILE}) endforeach()
Step 4: Link the Final Executable
Finally, create a custom target to link all object files into your executable. CMake will automatically ensure this step runs only after all object files are ready:
add_custom_target(myexec ALL COMMAND gcc -o myexec ${GENERATED_OBJS} -lgambit DEPENDS ${GENERATED_OBJS} COMMENT "Linking final executable 'myexec'" )
Why This Solves Your Issues
- Correct Ordering: Each custom command explicitly depends on its inputs, so CMake enforces the workflow you need: Scheme → C files → link file → object files → executable.
- Single Execution: The link file generation and object compilation steps only run once (or when their dependencies change), avoiding the per-file repetition from
CMAKE_Gambit_COMPILE_OBJECT. - Flexibility: This approach doesn’t force Gambit into CMake’s standard compiler model—perfect, since Gambit’s multi-file process deviates from typical C/C++ compilation.
If you want to reuse this logic, you can wrap these steps into a function inside your CMakeGambitInformation.cmake module, accepting a target name and source list as parameters.
内容的提问来源于stack exchange,提问作者koalag

