CMake: Handle custom_target indirection

Building custom targets that depend on custom commands such as our
keyword lexer requires two layers of indirection to pick up changes
properly and not overwrite the same file in parallel builds.

Fixes: lp:1831643
* https://bugs.launchpad.net/kicad/+bug/1831643
This commit is contained in:
Seth Hillbrand 2019-06-04 22:09:54 -07:00
parent 2d40425e4d
commit c6af38477d
5 changed files with 48 additions and 78 deletions

View File

@ -25,17 +25,28 @@
# Function make_lexer # Function make_lexer
# is a standard way to invoke TokenList2DsnLexer.cmake. # is a standard way to invoke TokenList2DsnLexer.cmake.
# Extra arguments are treated as source files which depend on the generated # Extra arguments are treated as source files which depend on the generated
# outHeaderFile # files. Some detail here on the indirection:
# - Parallel builds all depend on the same files, and CMake will generate the same file multiple times in the same location.
# This can be problematic if the files are generated at the same time and overwrite each other.
# - To fix this, we create a custom target (outputTarget) that the parallel builds depend on.
# - This almost works except that our targets that depend on targets don't get the file-level dependencies
# - So we have one additional layer of indirection to create an intermediate target with file dependencies
# AND build dependencies. This creates the needed rebuild for appropriate source object changes.
function( make_lexer outputTarget inputFile outHeaderFile outCppFile enum )
get_filename_component( outHeaderFileBase ${outHeaderFile} NAME )
get_filename_component( outCppFileBase ${outCppFile} NAME )
set( intermediateHeader "${CMAKE_CURRENT_BINARY_DIR}/${outHeaderFileBase}.1" )
set( intermediateCpp "${CMAKE_CURRENT_BINARY_DIR}/${outCppFileBase}.1" )
set( intermediateTarget "${outHeaderFileBase}.target" )
function( make_lexer inputFile outHeaderFile outCppFile enum )
add_custom_command( add_custom_command(
OUTPUT ${outHeaderFile} OUTPUT ${intermediateHeader}
${outCppFile} ${intermediateCpp}
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
-Denum=${enum} -Denum=${enum}
-DinputFile=${inputFile} -DinputFile=${inputFile}
-DoutHeaderFile=${outHeaderFile} -DoutHeaderFile=${intermediateHeader}
-DoutCppFile=${outCppFile} -DoutCppFile=${intermediateCpp}
-P ${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake -P ${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake
DEPENDS ${inputFile} DEPENDS ${inputFile}
${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake ${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake
@ -45,11 +56,31 @@ function( make_lexer inputFile outHeaderFile outCppFile enum )
${inputFile}" ${inputFile}"
) )
add_custom_target(
${intermediateTarget}
DEPENDS ${intermediateHeader}
${intermediateCpp}
)
add_custom_command(
OUTPUT ${outHeaderFile}
${outCppFile}
DEPENDS ${intermediateTarget} ${intermediateHeader} ${intermediateCpp}
COMMAND ${CMAKE_COMMAND} -E copy ${intermediateHeader} ${outHeaderFile}
COMMAND ${CMAKE_COMMAND} -E copy ${intermediateCpp} ${outCppFile}
)
add_custom_target(
${outputTarget} ALL
DEPENDS ${outHeaderFile}
${outCppFile}
)
# extra_args, if any, are treated as source files (typically headers) which # extra_args, if any, are treated as source files (typically headers) which
# are known to depend on the generated outHeader. # are known to depend on the generated outHeader.
foreach( extra_arg ${ARGN} ) foreach( extra_arg ${ARGN} )
set_source_files_properties( ${extra_arg} set_source_files_properties( ${extra_arg}
PROPERTIES OBJECT_DEPENDS ${outHeaderFile} PROPERTIES OBJECT_DEPENDS ${outputTarget}
) )
endforeach() endforeach()

View File

@ -508,6 +508,7 @@ target_link_libraries( pcbcommon PUBLIC
# auto-generate netlist_lexer.h and netlist_keywords.cpp # auto-generate netlist_lexer.h and netlist_keywords.cpp
make_lexer( make_lexer(
netlist_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/netlist.keywords ${CMAKE_CURRENT_SOURCE_DIR}/netlist.keywords
${PROJECT_SOURCE_DIR}/include/netlist_lexer.h ${PROJECT_SOURCE_DIR}/include/netlist_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/netlist_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/netlist_keywords.cpp
@ -517,18 +518,12 @@ make_lexer(
${CMAKE_PROJECT_SOURCE_DIR}/pcbnew/netlist_reader.h ${CMAKE_PROJECT_SOURCE_DIR}/pcbnew/netlist_reader.h
) )
add_custom_target(
netlist_lexer_source_files ALL
DEPENDS
${PROJECT_SOURCE_DIR}/include/netlist_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/netlist_keywords.cpp
)
add_dependencies( common netlist_lexer_source_files ) add_dependencies( common netlist_lexer_source_files )
add_dependencies( pcbcommon netlist_lexer_source_files ) add_dependencies( pcbcommon netlist_lexer_source_files )
# auto-generate pcb_plot_params_lexer.h and pcb_plot_params_keywords.cpp # auto-generate pcb_plot_params_lexer.h and pcb_plot_params_keywords.cpp
make_lexer( make_lexer(
pcb_plot_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params.keywords ${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params.keywords
${PROJECT_SOURCE_DIR}/include/pcb_plot_params_lexer.h ${PROJECT_SOURCE_DIR}/include/pcb_plot_params_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params_keywords.cpp
@ -538,17 +533,11 @@ make_lexer(
${PROJECT_SOURCE_DIR}/pcbnew/pcb_plot_params.h ${PROJECT_SOURCE_DIR}/pcbnew/pcb_plot_params.h
) )
add_custom_target(
pcb_plot_lexer_source_files ALL
DEPENDS
${PROJECT_SOURCE_DIR}/include/pcb_plot_params_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params_keywords.cpp
)
add_dependencies( pcbcommon pcb_plot_lexer_source_files ) add_dependencies( pcbcommon pcb_plot_lexer_source_files )
# auto-generate pcbnew_sexpr.h and pcbnew_sexpr.cpp # auto-generate pcbnew_sexpr.h and pcbnew_sexpr.cpp
make_lexer( make_lexer(
pcb_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/pcb.keywords ${CMAKE_CURRENT_SOURCE_DIR}/pcb.keywords
${PROJECT_SOURCE_DIR}/include/pcb_lexer.h ${PROJECT_SOURCE_DIR}/include/pcb_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/pcb_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pcb_keywords.cpp
@ -558,49 +547,30 @@ make_lexer(
${PROJECT_SOURCE_DIR}/pcbnew/pcb_parser.h ${PROJECT_SOURCE_DIR}/pcbnew/pcb_parser.h
) )
add_custom_target(
pcb_lexer_source_files ALL
DEPENDS
${PROJECT_SOURCE_DIR}/include/pcb_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/pcb_keywords.cpp
)
add_dependencies( pcbcommon pcb_lexer_source_files ) add_dependencies( pcbcommon pcb_lexer_source_files )
# auto-generate s-expression library table code. # auto-generate s-expression library table code.
make_lexer( make_lexer(
lib_table_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/lib_table.keywords ${CMAKE_CURRENT_SOURCE_DIR}/lib_table.keywords
${PROJECT_SOURCE_DIR}/include/lib_table_lexer.h ${PROJECT_SOURCE_DIR}/include/lib_table_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/lib_table_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/lib_table_keywords.cpp
LIB_TABLE_T LIB_TABLE_T
) )
add_custom_target(
lib_table_lexer_source_files ALL
DEPENDS
${PROJECT_SOURCE_DIR}/include/lib_table_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/lib_table_keywords.cpp
)
add_dependencies( common lib_table_lexer_source_files ) add_dependencies( common lib_table_lexer_source_files )
add_dependencies( pcbcommon lib_table_lexer_source_files ) add_dependencies( pcbcommon lib_table_lexer_source_files )
# auto-generate page layout reader s-expression page_layout_reader_lexer.h # auto-generate page layout reader s-expression page_layout_reader_lexer.h
# and title_block_reader_keywords.cpp. # and title_block_reader_keywords.cpp.
make_lexer( make_lexer(
page_layout_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader.keywords ${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader.keywords
${PROJECT_SOURCE_DIR}/include/page_layout_reader_lexer.h ${PROJECT_SOURCE_DIR}/include/page_layout_reader_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader_keywords.cpp
TB_READER_T TB_READER_T
) )
add_custom_target(
page_layout_lexer_source_files ALL
DEPENDS
${PROJECT_SOURCE_DIR}/include/page_layout_reader_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader_keywords.cpp
)
add_dependencies( common page_layout_lexer_source_files ) add_dependencies( common page_layout_lexer_source_files )
# This one gets made only when testing. # This one gets made only when testing.

View File

@ -443,22 +443,17 @@ endif()
# auto-generate cmp_library_lexer.h and cmp_library_keywords.cpp for the component # auto-generate cmp_library_lexer.h and cmp_library_keywords.cpp for the component
# library format. # library format.
make_lexer( make_lexer(
cmp_library_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords
${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp
TLIB_T TLIB_T
) )
add_custom_target(
cmp_library_lexer_source_files ALL
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp
)
add_dependencies( eeschema_kiface cmp_library_lexer_source_files ) add_dependencies( eeschema_kiface cmp_library_lexer_source_files )
make_lexer( make_lexer(
field_template_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames.keywords ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames.keywords
${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_keywords.cpp
@ -468,16 +463,10 @@ make_lexer(
template_fieldnames.h template_fieldnames.h
) )
add_custom_target(
field_template_lexer_source_files ALL
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_keywords.cpp
)
add_dependencies( eeschema_kiface field_template_lexer_source_files ) add_dependencies( eeschema_kiface field_template_lexer_source_files )
make_lexer( make_lexer(
dialog_bom_cfg_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg.keywords ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg.keywords
${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_keywords.cpp
@ -487,13 +476,6 @@ make_lexer(
dialogs/dialog_bom_cfg.h dialogs/dialog_bom_cfg.h
) )
add_custom_target(
dialog_bom_cfg_lexer_source_files ALL
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_keywords.cpp
)
add_dependencies( eeschema_kiface dialog_bom_cfg_lexer_source_files ) add_dependencies( eeschema_kiface dialog_bom_cfg_lexer_source_files )
add_subdirectory( plugins ) add_subdirectory( plugins )

View File

@ -147,6 +147,7 @@ endif()
# auto-generate pcb_calculator_datafile.h and pcb_calculator_datafile_keywords.cpp # auto-generate pcb_calculator_datafile.h and pcb_calculator_datafile_keywords.cpp
# for the storage data file format. # for the storage data file format.
make_lexer( make_lexer(
pcb_calculator_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile.keywords ${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile.keywords
${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_keywords.cpp
@ -156,13 +157,6 @@ make_lexer(
datafile_read_write.h datafile_read_write.h
) )
add_custom_target(
pcb_calculator_lexer_source_files ALL
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_keywords.cpp
)
# #
# Conversion of .html doc source files to .h files included in cpp sources # Conversion of .html doc source files to .h files included in cpp sources
# #

View File

@ -346,6 +346,7 @@ set( PCBNEW_SCRIPTING_PYTHON_HELPERS
# auto-generate specctra_lexer.h and specctra_keywords.cpp # auto-generate specctra_lexer.h and specctra_keywords.cpp
make_lexer( make_lexer(
specctra_lexer_source_files
${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra.keywords ${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra.keywords
${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra_keywords.cpp
@ -355,14 +356,6 @@ make_lexer(
specctra_import_export/specctra.h specctra_import_export/specctra.h
) )
add_custom_target(
specctra_lexer_source_files ALL
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/specctra_import_export/specctra_keywords.cpp
)
if( COMPILER_SUPPORTS_WSHADOW ) if( COMPILER_SUPPORTS_WSHADOW )
# .cpp files are compiled with extra ${WSHADOW_FLAGS}, but not .cxx files # .cpp files are compiled with extra ${WSHADOW_FLAGS}, but not .cxx files
set_source_files_properties( set_source_files_properties(