I've got the following problem:
Many libs in my project use code generated via an ADD_CUSTOM_COMMAND
cmake macro.
MACRO(CODE_GEN_MACRO srcList xmlFile_in)
_getLibName( "${xmlFile_in}" libName) //gets the lib name B
SET(in_files "${CURRENT_SOURCE_DIR}/templates/out_templace.h")
SET(out_files "${CURRENT_BINARY_DIR}/output_${libName}.h")
_CODE_GEN("${srcList}" "${xmlFile_in}" in_files out_files)
ENDMACRO()
MACRO(_CODE_GEN srcList xmlIn in_files out_files)
LIST(APPEND dependFiles ${ARGN} ${xmlIn} ${${in_files}}) //ok that one I don't know
set(_cg codegen) //code gen executable
ADD_CUSTOM_COMMAND( OUTPUT ${${out_files}}
COMMAND ${_cg}
ARGS -s ${xmlIN}
-o ${CMAKE_CURRENT_BINARY_DIR}
-i ${{${in_files}}
DEPENDS ${_cg} ${dependFiles}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
LIST(APPEND ${srcList} ${${out_files}}
ENDMACRO()
in a simple example consider the following structure
Lib A depends on B So lib B is created via
set(SRCS_B
b_init.cpp
b_ini.h
)
set(INPUT_XML b.xml)
CODE_GEN_MACRO(SRCS_B ${INPUT_XML} ) //here input_xml will be used to generate h and cpp files like output_b.h and the output will be added to SRCS_B)
add_library(B SHARED ${SRCS_B} )
target_include_directories(B
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
target_link_libraries(B
PUBLIC
someotherlib
)
and A
set(SRCS_A
a_init.cpp //here the output_b.h from lib B is included
a_ini.h
)
add_library(A SHARED ${SRCS_A} )
target_link_libraries(A
PUBLIC
B
)
On most machines this works perfectly fine. Even with +20 compile jobs. But on Windows (Visual Studio 2017 [15.9.36] and CMake 3.16.2) I get more and more issues that A and B are compiled around the same time, so that both are finished at the linking stage.
But as B generates files that are included in A.
Sometimes the ADD_CUSTOM_COMMAND
of B runs after A needs the generated header file.
Resulting in a 'No such file or directory' error.
So is there a way to tell CMake that the custom command of the depdendency needs to be executed first or that all dependencies should be linked before start compiling the current project?
I've got the following problem:
Many libs in my project use code generated via an ADD_CUSTOM_COMMAND
cmake macro.
MACRO(CODE_GEN_MACRO srcList xmlFile_in)
_getLibName( "${xmlFile_in}" libName) //gets the lib name B
SET(in_files "${CURRENT_SOURCE_DIR}/templates/out_templace.h")
SET(out_files "${CURRENT_BINARY_DIR}/output_${libName}.h")
_CODE_GEN("${srcList}" "${xmlFile_in}" in_files out_files)
ENDMACRO()
MACRO(_CODE_GEN srcList xmlIn in_files out_files)
LIST(APPEND dependFiles ${ARGN} ${xmlIn} ${${in_files}}) //ok that one I don't know
set(_cg codegen) //code gen executable
ADD_CUSTOM_COMMAND( OUTPUT ${${out_files}}
COMMAND ${_cg}
ARGS -s ${xmlIN}
-o ${CMAKE_CURRENT_BINARY_DIR}
-i ${{${in_files}}
DEPENDS ${_cg} ${dependFiles}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
LIST(APPEND ${srcList} ${${out_files}}
ENDMACRO()
in a simple example consider the following structure
Lib A depends on B So lib B is created via
set(SRCS_B
b_init.cpp
b_ini.h
)
set(INPUT_XML b.xml)
CODE_GEN_MACRO(SRCS_B ${INPUT_XML} ) //here input_xml will be used to generate h and cpp files like output_b.h and the output will be added to SRCS_B)
add_library(B SHARED ${SRCS_B} )
target_include_directories(B
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
target_link_libraries(B
PUBLIC
someotherlib
)
and A
set(SRCS_A
a_init.cpp //here the output_b.h from lib B is included
a_ini.h
)
add_library(A SHARED ${SRCS_A} )
target_link_libraries(A
PUBLIC
B
)
On most machines this works perfectly fine. Even with +20 compile jobs. But on Windows (Visual Studio 2017 [15.9.36] and CMake 3.16.2) I get more and more issues that A and B are compiled around the same time, so that both are finished at the linking stage.
But as B generates files that are included in A.
Sometimes the ADD_CUSTOM_COMMAND
of B runs after A needs the generated header file.
Resulting in a 'No such file or directory' error.
So is there a way to tell CMake that the custom command of the depdendency needs to be executed first or that all dependencies should be linked before start compiling the current project?
Share Improve this question edited Mar 27 at 8:54 Imunar asked Mar 27 at 6:43 ImunarImunar 112 bronze badges 18 | Show 13 more comments1 Answer
Reset to default 0A few years back I had a problem that seems similar to what you describe.
I wrote my build system using CMake 3.17 then. Everything worked fine on Linux with the makefile generator. In Windows build I got errors that dependencies were not built in the right order. I was using default the Visual Studio generator there.
Solution was to change the order in which targets and generated files were defined in CMake. In my case this was simple by changing the sequence of add_subdirectory statements like from
...
add_subdirectory(bin)
add_subdirectory(doc)
add_subdirectory(lib)
add_subdirectory(tools)
...
to
...
add_subdirectory(tools)
add_subdirectory(bin)
add_subdirectory(doc)
add_subdirectory(lib)
...
where the depencies where created in the tools directory.
I never explored that further so I can not be sure whether my situation is identical to yours. But it might be something to look after.
target_link_libraries(A PUBLIC B)
? If code generation for B runs after compilation of A, it means that your CMake logic is incorrect. Post minimal reproducible example ale we'll see what might be the fix. – pptaszni Commented Mar 27 at 6:47CODE_GEN_MACRO
definition and how you define the dependency between autogenerated code and yourB
(orA
) library is crucial here. – pptaszni Commented Mar 27 at 8:32