From c6af38477d07b2b464c17b1232557f433047baa8 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 --- 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 5a564a58ad..1905826334 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -508,6 +508,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 @@ -517,18 +518,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 @@ -538,17 +533,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 @@ -558,49 +547,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 6f1fb8f55b..0c1e6d5c30 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -443,22 +443,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 @@ -468,16 +463,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 @@ -487,13 +476,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 12668ab668..7196a32816 100644 --- a/pcb_calculator/CMakeLists.txt +++ b/pcb_calculator/CMakeLists.txt @@ -147,6 +147,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 @@ -156,13 +157,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 3bfa338a55..37184ab8ea 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -346,6 +346,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 @@ -355,14 +356,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(