From 63f18f0b03a304a57cde38339d926554896fa48b Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 4 Jun 2019 22:09:54 -0700 Subject: [PATCH] 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 (cherry picked from commit c6af38477d07b2b464c17b1232557f433047baa8) --- CMakeModules/Functions.cmake | 45 +++++++++++++++++++++++++++++------ common/CMakeLists.txt | 40 ++++--------------------------- eeschema/CMakeLists.txt | 24 +++---------------- pcb_calculator/CMakeLists.txt | 8 +------ pcbnew/CMakeLists.txt | 9 +------ 5 files changed, 48 insertions(+), 78 deletions(-) diff --git a/CMakeModules/Functions.cmake b/CMakeModules/Functions.cmake index e3d7f8c9ec..c854723ca2 100644 --- a/CMakeModules/Functions.cmake +++ b/CMakeModules/Functions.cmake @@ -25,17 +25,28 @@ # Function make_lexer # is a standard way to invoke TokenList2DsnLexer.cmake. # 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( - OUTPUT ${outHeaderFile} - ${outCppFile} + OUTPUT ${intermediateHeader} + ${intermediateCpp} COMMAND ${CMAKE_COMMAND} -Denum=${enum} -DinputFile=${inputFile} - -DoutHeaderFile=${outHeaderFile} - -DoutCppFile=${outCppFile} + -DoutHeaderFile=${intermediateHeader} + -DoutCppFile=${intermediateCpp} -P ${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake DEPENDS ${inputFile} ${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake @@ -45,11 +56,31 @@ function( make_lexer inputFile outHeaderFile outCppFile enum ) ${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 # are known to depend on the generated outHeader. foreach( extra_arg ${ARGN} ) set_source_files_properties( ${extra_arg} - PROPERTIES OBJECT_DEPENDS ${outHeaderFile} + PROPERTIES OBJECT_DEPENDS ${outputTarget} ) endforeach() diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 5b47172ba1..45337092c2 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -515,6 +515,7 @@ target_link_libraries( pcbcommon PUBLIC # auto-generate netlist_lexer.h and netlist_keywords.cpp make_lexer( + netlist_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/netlist.keywords ${PROJECT_SOURCE_DIR}/include/netlist_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/netlist_keywords.cpp @@ -524,18 +525,12 @@ make_lexer( ${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( pcbcommon netlist_lexer_source_files ) # auto-generate pcb_plot_params_lexer.h and pcb_plot_params_keywords.cpp make_lexer( + pcb_plot_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params.keywords ${PROJECT_SOURCE_DIR}/include/pcb_plot_params_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/pcb_plot_params_keywords.cpp @@ -545,17 +540,11 @@ make_lexer( ${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 ) # auto-generate pcbnew_sexpr.h and pcbnew_sexpr.cpp make_lexer( + pcb_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/pcb.keywords ${PROJECT_SOURCE_DIR}/include/pcb_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/pcb_keywords.cpp @@ -565,49 +554,30 @@ make_lexer( ${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 ) # auto-generate s-expression library table code. make_lexer( + lib_table_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/lib_table.keywords ${PROJECT_SOURCE_DIR}/include/lib_table_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/lib_table_keywords.cpp 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( pcbcommon lib_table_lexer_source_files ) # auto-generate page layout reader s-expression page_layout_reader_lexer.h # and title_block_reader_keywords.cpp. make_lexer( + page_layout_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader.keywords ${PROJECT_SOURCE_DIR}/include/page_layout_reader_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/page_layout/page_layout_reader_keywords.cpp 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 ) # This one gets made only when testing. diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 244d25bfd5..425686f82f 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -449,22 +449,17 @@ endif() # auto-generate cmp_library_lexer.h and cmp_library_keywords.cpp for the component # library format. make_lexer( + cmp_library_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp 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 ) make_lexer( + field_template_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames.keywords ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_keywords.cpp @@ -474,16 +469,10 @@ make_lexer( 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 ) 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_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_keywords.cpp @@ -493,13 +482,6 @@ make_lexer( 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_subdirectory( plugins ) diff --git a/pcb_calculator/CMakeLists.txt b/pcb_calculator/CMakeLists.txt index e040451298..0cfeb538e4 100644 --- a/pcb_calculator/CMakeLists.txt +++ b/pcb_calculator/CMakeLists.txt @@ -145,6 +145,7 @@ endif() # auto-generate pcb_calculator_datafile.h and pcb_calculator_datafile_keywords.cpp # for the storage data file format. make_lexer( + pcb_calculator_lexer_source_files ${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile.keywords ${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_lexer.h ${CMAKE_CURRENT_SOURCE_DIR}/pcb_calculator_datafile_keywords.cpp @@ -154,13 +155,6 @@ make_lexer( 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 # diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 1d3cc5cf54..0662b75d57 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -378,6 +378,7 @@ set( PCBNEW_SCRIPTING_PYTHON_HELPERS # auto-generate specctra_lexer.h and specctra_keywords.cpp make_lexer( + specctra_lexer_source_files ${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_keywords.cpp @@ -387,14 +388,6 @@ make_lexer( 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 ) # .cpp files are compiled with extra ${WSHADOW_FLAGS}, but not .cxx files set_source_files_properties(