最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Run CMake custom command of dependency before build - Stack Overflow

programmeradmin6浏览0评论

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
  • 3 You mean 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:47
  • If your custom command produces an output, reference that output in another target so the sequencing is enforced. – Botje Commented Mar 27 at 7:46
  • @pptaszni I can't post the whole code gen source but I updated the code above as you are right that I switched target_link_libraries and fot add_library – Imunar Commented Mar 27 at 8:27
  • @Botje thanks.. I'm not sure if I understand that right. I hesitate to reference the output (headers) across the whole project via relative paths etc. – Imunar Commented Mar 27 at 8:32
  • 1 Yeah obviously not the whole code, that why it's called Minimal example. CODE_GEN_MACRO definition and how you define the dependency between autogenerated code and your B (or A) library is crucial here. – pptaszni Commented Mar 27 at 8:32
 |  Show 13 more comments

1 Answer 1

Reset to default 0

A 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.

发布评论

评论列表(0)

  1. 暂无评论