UseSWIG: use swig tool to generate dependencies

add_custom_command() supports option DEPFILE when generator is
Makefiles or Ninja. And swig tool is able to generate a dependencies
file which is compatible with DEPFILE option.
This commit is contained in:
Marc Chevrier
2021-01-12 16:38:23 +01:00
parent c69567e56a
commit 89b01b04fa
5 changed files with 93 additions and 18 deletions

View File

@@ -0,0 +1,6 @@
UseSWIG-dependencies
--------------------
* :module:`UseSWIG` module gained the capability, for
:ref:`Makefile <Makefile Generators>` and :ref:`Ninja <Ninja Generators>`
generators, to use ``swig`` tool to generate implicit dependencies.

View File

@@ -48,11 +48,12 @@ Defines the following command for use with ``SWIG``:
.. note:: .. note::
For Make-based generators, ``swig_add_library`` does not track file For :ref:`Makefile Generators`, if, for some sources, the
dependencies, so depending on the ``<name>_swig_compilation`` custom target ``USE_SWIG_DEPENDENCIES`` property is ``FALSE``, ``swig_add_library`` does
is required for targets which require the ``swig``-generated files to not track file dependencies, so depending on the ``<name>_swig_compilation``
exist. Other generators may depend on the source files that would be custom target is required for targets which require the ``swig``-generated
generated by SWIG. files to exist. Other generators may depend on the source files that would
be generated by SWIG.
``TYPE`` ``TYPE``
``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the ``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the
@@ -179,6 +180,14 @@ ensure generated files will receive the required settings.
Specify additional dependencies to the source file. Specify additional dependencies to the source file.
``USE_SWIG_DEPENDENCIES``
.. versionadded:: 3.20
If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool
itself. This property is only meaningful for
:ref:`Makefile <Makefile Generators>` and
:ref:`Ninja <Ninja Generators>` generators. Default value is ``FALSE``.
``SWIG_MODULE_NAME`` ``SWIG_MODULE_NAME``
Specify the actual import name of the module in the target language. Specify the actual import name of the module in the target language.
This is required if it cannot be scanned automatically from source This is required if it cannot be scanned automatically from source
@@ -316,6 +325,17 @@ as well as ``SWIG``:
.. code-block:: cmake .. code-block:: cmake
set(SWIG_SOURCE_FILE_EXTENSIONS ".i" ".swg") set(SWIG_SOURCE_FILE_EXTENSIONS ".i" ".swg")
``SWIG_USE_SWIG_DEPENDENCIES``
.. versionadded:: 3.20
If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool
itself. This property is only meaningful for
:ref:`Makefile <Makefile Generators>` and
:ref:`Ninja <Ninja Generators>` generators. Default value is ``FALSE``.
Source file property ``USE_SWIG_DEPENDENCIES``, if not defined, will be
initialized with the value of this variable.
#]=======================================================================] #]=======================================================================]
cmake_policy(GET CMP0078 target_name_policy) cmake_policy(GET CMP0078 target_name_policy)
@@ -486,6 +506,14 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
set(target_name ${name}) set(target_name ${name})
endif() endif()
set (use_swig_dependencies ${SWIG_USE_SWIG_DEPENDENCIES})
if (CMAKE_GENERATOR MATCHES "Make|Ninja")
get_property(use_swig_dependencies_set SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES SET)
if (use_swig_dependencies_set)
get_property(use_swig_dependencies SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES)
endif()
endif()
set (swig_source_file_flags ${CMAKE_SWIG_FLAGS}) set (swig_source_file_flags ${CMAKE_SWIG_FLAGS})
# handle various swig compile flags properties # handle various swig compile flags properties
get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES) get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES)
@@ -591,7 +619,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS}) list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
# dependencies # dependencies
set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${target_name},SWIG_DEPENDS>) set (swig_dependencies DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${target_name},SWIG_DEPENDS>)
get_source_file_property(file_depends "${infile}" DEPENDS) get_source_file_property(file_depends "${infile}" DEPENDS)
if (file_depends) if (file_depends)
list (APPEND swig_dependencies ${file_depends}) list (APPEND swig_dependencies ${file_depends})
@@ -609,10 +637,11 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
unset (swig_copy_command) unset (swig_copy_command)
endif() endif()
# IMPLICIT_DEPENDS below can not handle situations where a dependent file is set(swig_depends_flags)
# removed. We need an extra step with timestamp and custom target, see #16830 if(NOT use_swig_dependencies AND CMAKE_GENERATOR MATCHES "Make")
# As this is needed only for Makefile generator do it conditionally # IMPLICIT_DEPENDS can not handle situations where a dependent file is
if(CMAKE_GENERATOR MATCHES "Make") # removed. We need an extra step with timestamp and custom target, see #16830
# As this is needed only for Makefile generator do it conditionally
__swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
"${infile}" "${workingdir}" swig_generated_timestamp) "${infile}" "${workingdir}" swig_generated_timestamp)
set(swig_custom_output "${swig_generated_timestamp}") set(swig_custom_output "${swig_generated_timestamp}")
@@ -620,11 +649,19 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files}) BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
set(swig_timestamp_command set(swig_timestamp_command
COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}") COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
list(APPEND swig_dependencies IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}")
else() else()
set(swig_generated_timestamp)
set(swig_custom_output set(swig_custom_output
"${swig_generated_file_fullname}" ${swig_extra_generated_files}) "${swig_generated_file_fullname}" ${swig_extra_generated_files})
set(swig_custom_products) set(swig_custom_products)
set(swig_timestamp_command) set(swig_timestamp_command)
if (use_swig_dependencies)
cmake_path(GET infile FILENAME swig_depends_filename)
set(swig_depends_filename "${workingdir}/${swig_depends_filename}.d")
list(APPEND swig_dependencies DEPFILE "${swig_depends_filename}")
set(swig_depends_flags -MF "${swig_depends_filename}" -MD)
endif()
endif() endif()
add_custom_command( add_custom_command(
OUTPUT ${swig_custom_output} OUTPUT ${swig_custom_output}
@@ -639,13 +676,13 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
-outdir "${swig_file_outdir}" -outdir "${swig_file_outdir}"
${swig_special_flags} ${swig_special_flags}
${swig_extra_flags} ${swig_extra_flags}
${swig_depends_flags}
"${swig_include_dirs}" "${swig_include_dirs}"
-o "${swig_generated_file_fullname}" -o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}" "${swig_source_file_fullname}"
${swig_copy_command} ${swig_copy_command}
MAIN_DEPENDENCY "${swig_source_file_fullname}" MAIN_DEPENDENCY "${swig_source_file_fullname}"
DEPENDS ${swig_dependencies} ${swig_dependencies}
IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
COMMENT "Swig compile ${infile} for ${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" COMMENT "Swig compile ${infile} for ${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
COMMAND_EXPAND_LISTS) COMMAND_EXPAND_LISTS)
set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files} set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
@@ -666,6 +703,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
endif() endif()
set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE) set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
set(swig_timestamp "${swig_generated_timestamp}" PARENT_SCOPE)
# legacy support # legacy support
set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE) set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
@@ -794,6 +832,15 @@ function(SWIG_ADD_LIBRARY name)
set(SWIG_SOURCE_FILE_EXTENSIONS ".i") set(SWIG_SOURCE_FILE_EXTENSIONS ".i")
endif() endif()
if (CMAKE_GENERATOR MATCHES "Make|Ninja")
# For Makefiles and Ninja generators, use SWIG generated dependencies
if (NOT DEFINED SWIG_USE_SWIG_DEPENDENCIES)
set (SWIG_USE_SWIG_DEPENDENCIES OFF)
endif()
else()
set (SWIG_USE_SWIG_DEPENDENCIES OFF)
endif()
# Generate a regex out of file extensions. # Generate a regex out of file extensions.
string(REGEX REPLACE "([$^.*+?|()-])" "\\\\\\1" swig_source_ext_regex "${SWIG_SOURCE_FILE_EXTENSIONS}") string(REGEX REPLACE "([$^.*+?|()-])" "\\\\\\1" swig_source_ext_regex "${SWIG_SOURCE_FILE_EXTENSIONS}")
list (JOIN swig_source_ext_regex "|" swig_source_ext_regex) list (JOIN swig_source_ext_regex "|" swig_source_ext_regex)
@@ -821,9 +868,7 @@ function(SWIG_ADD_LIBRARY name)
foreach(swig_it IN LISTS swig_dot_i_sources) foreach(swig_it IN LISTS swig_dot_i_sources)
SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}") SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}")
list (APPEND swig_generated_sources "${swig_generated_source}") list (APPEND swig_generated_sources "${swig_generated_source}")
if(CMAKE_GENERATOR MATCHES "Make") if(swig_timestamp)
__swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}"
"${workingdir}" swig_timestamp)
list (APPEND swig_generated_timestamps "${swig_timestamp}") list (APPEND swig_generated_timestamps "${swig_timestamp}")
endif() endif()
get_source_file_property(swig_source_file_outdir "${swig_it}" OUTPUT_DIR) get_source_file_property(swig_source_file_outdir "${swig_it}" OUTPUT_DIR)
@@ -842,7 +887,7 @@ function(SWIG_ADD_LIBRARY name)
${_SAM_TYPE} ${_SAM_TYPE}
${swig_generated_sources} ${swig_generated_sources}
${swig_other_sources}) ${swig_other_sources})
if(CMAKE_GENERATOR MATCHES "Make") if(swig_generated_timestamps)
# see IMPLICIT_DEPENDS above # see IMPLICIT_DEPENDS above
add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps}) add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
add_dependencies(${target_name} ${name}_swig_compilation) add_dependencies(${target_name} ${name}_swig_compilation)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1...3.13) cmake_minimum_required(VERSION 3.1...3.20)
project(TestBasicPerl CXX) project(TestBasicPerl CXX)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1...3.13) cmake_minimum_required(VERSION 3.1...3.20)
project(TestBasicPython CXX) project(TestBasicPython CXX)

View File

@@ -1,3 +1,5 @@
find_package(SWIG QUIET)
add_test(NAME UseSWIG.LegacyPython COMMAND add_test(NAME UseSWIG.LegacyPython COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test --build-and-test
@@ -64,6 +66,28 @@ add_test(NAME UseSWIG.BasicPerl COMMAND
--build-options ${build_options} --build-options ${build_options}
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
) )
if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2")
add_test(NAME UseSWIG.Depfile.BasicPython COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
"${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicPython"
"${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPython.Depfile"
${build_generator_args}
--build-project TestBasicPython
--build-options ${build_options} -DSWIG_USE_SWIG_DEPENDENCIES=ON
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
add_test(NAME UseSWIG.Depfile.BasicPerl COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
"${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicPerl"
"${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPerl.Depfile"
${build_generator_args}
--build-project TestBasicPerl
--build-options ${build_options} -DSWIG_USE_SWIG_DEPENDENCIES=ON
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
endif()
if (CMake_TEST_UseSWIG_Fortran) if (CMake_TEST_UseSWIG_Fortran)
check_language(Fortran) check_language(Fortran)