Browse Source

Merge topic 'SWIG-dependencies'

89b01b04fa UseSWIG: use swig tool to generate dependencies

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5724
Brad King 4 years ago
parent
commit
6bd251ace7

+ 6 - 0
Help/release/dev/UseSWIG-dependencies.rst

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

+ 61 - 16
Modules/UseSWIG.cmake

@@ -48,11 +48,12 @@ Defines the following command for use with ``SWIG``:
 
   .. note::
 
-    For Make-based generators, ``swig_add_library`` does not track file
-    dependencies, so depending on the ``<name>_swig_compilation`` custom target
-    is required for targets which require the ``swig``-generated files to
-    exist. Other generators may depend on the source files that would be
-    generated by SWIG.
+    For :ref:`Makefile Generators`, if, for some sources, the
+    ``USE_SWIG_DEPENDENCIES`` property is ``FALSE``, ``swig_add_library`` does
+    not track file dependencies, so depending on the ``<name>_swig_compilation``
+    custom target is required for targets which require the ``swig``-generated
+    files to exist. Other generators may depend on the source files that would
+    be generated by SWIG.
 
   ``TYPE``
     ``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.
 
+``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``
   Specify the actual import name of the module in the target language.
   This is required if it cannot be scanned automatically from source
@@ -316,6 +325,17 @@ as well as ``SWIG``:
   .. code-block:: cmake
 
     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)
@@ -486,6 +506,14 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
     set(target_name ${name})
   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})
   # handle various swig compile flags properties
   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})
 
   # 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)
   if (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)
   endif()
 
-  # IMPLICIT_DEPENDS below can not handle situations where a dependent file is
-  # removed. We need an extra step with timestamp and custom target, see #16830
-  # As this is needed only for Makefile generator do it conditionally
-  if(CMAKE_GENERATOR MATCHES "Make")
+  set(swig_depends_flags)
+  if(NOT use_swig_dependencies AND CMAKE_GENERATOR MATCHES "Make")
+    # IMPLICIT_DEPENDS can not handle situations where a dependent file is
+    # 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}
       "${infile}" "${workingdir}" 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})
     set(swig_timestamp_command
       COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
+    list(APPEND swig_dependencies IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}")
   else()
+    set(swig_generated_timestamp)
     set(swig_custom_output
       "${swig_generated_file_fullname}" ${swig_extra_generated_files})
     set(swig_custom_products)
     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()
   add_custom_command(
     OUTPUT ${swig_custom_output}
@@ -639,13 +676,13 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
     -outdir "${swig_file_outdir}"
     ${swig_special_flags}
     ${swig_extra_flags}
+    ${swig_depends_flags}
     "${swig_include_dirs}"
     -o "${swig_generated_file_fullname}"
     "${swig_source_file_fullname}"
     ${swig_copy_command}
     MAIN_DEPENDENCY "${swig_source_file_fullname}"
-    DEPENDS ${swig_dependencies}
-    IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
+    ${swig_dependencies}
     COMMENT "Swig compile ${infile} for ${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
     COMMAND_EXPAND_LISTS)
   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()
 
   set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
+  set(swig_timestamp "${swig_generated_timestamp}" PARENT_SCOPE)
 
   # legacy support
   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")
   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.
   string(REGEX REPLACE "([$^.*+?|()-])" "\\\\\\1" swig_source_ext_regex "${SWIG_SOURCE_FILE_EXTENSIONS}")
   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)
     SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}")
     list (APPEND swig_generated_sources "${swig_generated_source}")
-    if(CMAKE_GENERATOR MATCHES "Make")
-      __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}"
-        "${workingdir}" swig_timestamp)
+    if(swig_timestamp)
       list (APPEND swig_generated_timestamps "${swig_timestamp}")
     endif()
     get_source_file_property(swig_source_file_outdir "${swig_it}" OUTPUT_DIR)
@@ -842,7 +887,7 @@ function(SWIG_ADD_LIBRARY name)
     ${_SAM_TYPE}
     ${swig_generated_sources}
     ${swig_other_sources})
-  if(CMAKE_GENERATOR MATCHES "Make")
+  if(swig_generated_timestamps)
     # see IMPLICIT_DEPENDS above
     add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
     add_dependencies(${target_name} ${name}_swig_compilation)

+ 1 - 1
Tests/UseSWIG/BasicPerl/CMakeLists.txt

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

+ 1 - 1
Tests/UseSWIG/BasicPython/CMakeLists.txt

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

+ 24 - 0
Tests/UseSWIG/CMakeLists.txt

@@ -1,3 +1,5 @@
+find_package(SWIG QUIET)
+
 add_test(NAME UseSWIG.LegacyPython COMMAND
   ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
   --build-and-test
@@ -64,6 +66,28 @@ add_test(NAME UseSWIG.BasicPerl COMMAND
   --build-options ${build_options}
   --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)
   check_language(Fortran)