Merge topic 'genex-IN_LIST-operator'

5089f560 Genex: Add IN_LIST logical operator

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1724
diff --git a/Help/command/string.rst b/Help/command/string.rst
index fb3893f..d8da7be 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -282,6 +282,18 @@
 
 Transform a string like :command:`configure_file` transforms a file.
 
+MAKE_C_IDENTIFIER
+"""""""""""""""""
+
+::
+
+  string(MAKE_C_IDENTIFIER <input string> <output variable>)
+
+Convert each non-alphanumeric character in the ``<input string>`` to an
+underscore and store the result in the ``<output variable>``.  If the first
+character of the string is a digit, an underscore will also be prepended to
+the result.
+
 RANDOM
 """"""
 
@@ -346,13 +358,6 @@
    %Y-%m-%dT%H:%M:%S    for local time.
    %Y-%m-%dT%H:%M:%SZ   for UTC.
 
-
-::
-
-  string(MAKE_C_IDENTIFIER <input string> <output variable>)
-
-Write a string which can be used as an identifier in C.
-
 .. note::
 
   If the ``SOURCE_DATE_EPOCH`` environment variable is set,
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 149ec4b..04cb1dc 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -291,7 +291,8 @@
 ``$<UPPER_CASE:...>``
   Content of ``...`` converted to upper case.
 ``$<MAKE_C_IDENTIFIER:...>``
-  Content of ``...`` converted to a C identifier.
+  Content of ``...`` converted to a C identifier.  The conversion follows the
+  same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
 ``$<TARGET_OBJECTS:objLib>``
   List of objects resulting from build of ``objLib``. ``objLib`` must be an
   object of type ``OBJECT_LIBRARY``.
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 00a932f..d3e58d0 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -84,6 +84,7 @@
    /prop_dir/RULE_LAUNCH_LINK
    /prop_dir/SOURCE_DIR
    /prop_dir/SUBDIRECTORIES
+   /prop_dir/TESTS
    /prop_dir/TEST_INCLUDE_FILES
    /prop_dir/VARIABLES
    /prop_dir/VS_GLOBAL_SECTION_POST_section
diff --git a/Help/prop_dir/TESTS.rst b/Help/prop_dir/TESTS.rst
new file mode 100644
index 0000000..c6e1d88
--- /dev/null
+++ b/Help/prop_dir/TESTS.rst
@@ -0,0 +1,7 @@
+TESTS
+-----
+
+List of tests.
+
+This read-only property holds a :ref:`;-list <CMake Language Lists>` of tests
+defined so far by the :command:`add_test` command.
diff --git a/Help/release/dev/UseSWIG-modernize-module.rst b/Help/release/dev/UseSWIG-modernize-module.rst
new file mode 100644
index 0000000..925c119
--- /dev/null
+++ b/Help/release/dev/UseSWIG-modernize-module.rst
@@ -0,0 +1,6 @@
+UseSWIG-modernize-module
+------------------------
+
+* The :module:`UseSWIG` gained a whole refresh and is now more consistent with
+  standard CMake commands to generate libraries and is fully configurable through
+  properties.
diff --git a/Help/release/dev/directory-property-TESTS.rst b/Help/release/dev/directory-property-TESTS.rst
new file mode 100644
index 0000000..9de2531
--- /dev/null
+++ b/Help/release/dev/directory-property-TESTS.rst
@@ -0,0 +1,5 @@
+directory-property-TESTS
+------------------------
+
+* The :prop_dir:`TESTS` directory property was added to hold the list of tests defined by
+  command :command:`add_test`.
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 0a31ac2..119fc13 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -175,7 +175,7 @@
 #   -- Same as CUDA_ADD_EXECUTABLE except that a library is created.
 #
 #   CUDA_BUILD_CLEAN_TARGET()
-#   -- Creates a convience target that deletes all the dependency files
+#   -- Creates a convenience target that deletes all the dependency files
 #      generated.  You should make clean after running this target to ensure the
 #      dependency files get regenerated.
 #
@@ -1564,7 +1564,7 @@
       # Bring in the dependencies.  Creates a variable CUDA_NVCC_DEPEND #######
       cuda_include_nvcc_dependencies(${cmake_dependency_file})
 
-      # Convience string for output ###########################################
+      # Convenience string for output #########################################
       if(CUDA_BUILD_EMULATION)
         set(cuda_build_type "Emulation")
       else()
@@ -1975,9 +1975,9 @@
 ###############################################################################
 ###############################################################################
 macro(CUDA_BUILD_CLEAN_TARGET)
-  # Call this after you add all your CUDA targets, and you will get a convience
-  # target.  You should also make clean after running this target to get the
-  # build system to generate all the code again.
+  # Call this after you add all your CUDA targets, and you will get a
+  # convenience target.  You should also make clean after running this target
+  # to get the build system to generate all the code again.
 
   set(cuda_clean_target_name clean_cuda_depends)
   if (CMAKE_GENERATOR MATCHES "Visual Studio")
diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake
index c16bbf2..881bff1 100644
--- a/Modules/FindImageMagick.cmake
+++ b/Modules/FindImageMagick.cmake
@@ -206,7 +206,7 @@
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY)
   elseif(component STREQUAL "MagickWand")
     FIND_IMAGEMAGICK_API(MagickWand "wand/MagickWand.h;MagickWand/MagickWand.h"
-      Wand MagickWand CORE_RL_wand_
+      Wand MagickWand CORE_RL_wand_ CORE_RL_MagickWand_
       MagickWand-6 MagickWand-7
       MagickWand-Q16 MagickWand-Q8 MagickWand-Q16HDRI MagickWand-Q8HDRI
       MagickWand-6.Q64 MagickWand-6.Q32 MagickWand-6.Q64HDRI MagickWand-6.Q32HDRI
@@ -217,7 +217,7 @@
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY)
   elseif(component STREQUAL "MagickCore")
     FIND_IMAGEMAGICK_API(MagickCore "magick/MagickCore.h;MagickCore/MagickCore.h"
-      Magick MagickCore CORE_RL_magick_
+      Magick MagickCore CORE_RL_magick_ CORE_RL_MagickCore_
       MagickCore-6 MagickCore-7
       MagickCore-Q16 MagickCore-Q8 MagickCore-Q16HDRI MagickCore-Q8HDRI
       MagickCore-6.Q64 MagickCore-6.Q32 MagickCore-6.Q64HDRI MagickCore-6.Q32HDRI
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index 939bd7b..7b138f5 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -36,7 +36,7 @@
 # The default OUTPUT_DIR can also be changed by setting the variable
 # CMAKE_JAVA_TARGET_OUTPUT_DIR.
 #
-# Optionaly, using option GENERATE_NATIVE_HEADERS, native header files can be generated
+# Optionally, using option GENERATE_NATIVE_HEADERS, native header files can be generated
 # for methods declared as native. These files provide the connective glue that allow your
 # Java and C code to interact. An INTERFACE target will be created for an easy usage
 # of generated files. Sub-option DESTINATION can be used to specify output directory for
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 959893f..6d35d1b 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -5,7 +5,7 @@
 UseSWIG
 -------
 
-Defines the following macros for use with SWIG:
+Defines the following command for use with SWIG:
 
 .. command:: swig_add_library
 
@@ -14,20 +14,47 @@
     swig_add_library(<name>
                      [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>]
                      LANGUAGE <language>
+                     [NO_PROXY]
+                     [OUTPUT_DIR <directory>]
+                     [OUTFILE_DIR <directory>]
                      SOURCES <file>...
-                     )
+                    )
 
-  The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name
-  of the swig module target library.
+  Targets created with command ``swig_add_library`` have the same capabilities as targets
+  created with command :command:`add_library`, so can be used with any command accepting a target
+  especially command :command:`target_link_libraries`.
 
-.. command:: swig_link_libraries
+  The arguments are:
 
-  Link libraries to swig module::
+  ``TYPE``
+    ``SHARED``, ``MODULE`` and ``STATIC`` have same semantic as command :command:`add_library`.
+    if ``USE_BUILD_SHARED_LIBS`` is specified, library type will be ``STATIC`` or ``SHARED``
+    based on whether the current value of the variable :variable:`BUILD_SHARED_LIBS` is ``ON``.
+    If none is specified, ``MODULE`` will be used.
 
-    swig_link_libraries(<name> [ libraries ])
+  ``LANGUAGE``
+    Specify the target language.
 
-Source file properties on module files can be set before the invocation
-of the ``swig_add_library`` macro to specify special behavior of SWIG:
+  ``NO_PROXY``
+    Prevent the generation of the wrapper layer (swig ``-noproxy`` option).
+
+  ``OUTPUT_DIR``
+    Specify where to write the language specific files (swig ``-outdir`` option).
+    If not specified, variable ``CMAKE_SWIG_OUTDIR`` will be used. If none is specified,
+    :variable:`CMAKE_CURRENT_BINARY_DIR` is used.
+
+  ``OUTFILE_DIR``
+    Specify an output directory name where the generated source file will be placed
+    (swig -o option). If not specified, variable ``SWIG_OUTFILE_DIR`` will be used.
+    If none is specified, option ``OUTPUT_DIR`` or variable ``CMAKE_SWIG_OUTDIR`` is used.
+
+  ``SOURCES``
+    List of sources for the library. Files with extension ``.i`` will be identified as sources
+    for ``SWIG`` tool. Other files will be handled in the standard way.
+
+Source files properties on module files **must** be set before the invocation
+of the ``swig_add_library`` command to specify special behavior of SWIG and ensure
+generated files will receive required settings.
 
 ``CPLUSPLUS``
   Call SWIG in c++ mode.  For example:
@@ -37,9 +64,17 @@
     set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON)
     swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
 
-``SWIG_FLAGS``
-  Add custom flags to the SWIG executable.
+``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS``
+  Add custom flags to SWIG compiler and have same semantic as properties
+  :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and :prop_sf:`COMPILE_OPTIONS`.
 
+``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS``
+  Add custom flags to the C/C++ generated source. They will fill, respectively,
+  properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
+  :prop_sf:`COMPILE_OPTIONS` of generated C/C++ file.
+
+``DEPENDS``
+  Specify additional dependencies to the source file.
 
 ``SWIG_MODULE_NAME``
   Specify the actual import name of the module in the target language.
@@ -50,6 +85,34 @@
 
     set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname)
 
+Target library properties can be set to apply same configuration to all SWIG input files.
+
+``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS``
+  These properties will be applied to all SWIG input files and have same semantic as
+  target properties :prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and
+  :prop_tgt:`COMPILE_OPTIONS`.
+
+  .. code-block:: cmake
+
+    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+    set_property(TARGET mymod PROPERTY SWIG_COMPILE_DEFINITIONS MY_DEF1 MY_DEF2)
+    set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb)
+
+``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
+  These properties will populate, respectively, properties :prop_sf:`INCLUDE_DIRECTORIES`,
+  :prop_sf:`COMPILE_DEFINITIONS` and :prop_sf:`COMPILE_FLAGS` of all generated C/C++ files.
+
+``SWIG_DEPENDS``
+  Add dependencies to all SWIG input files.
+
+``SWIG_SUPPORT_FILES``
+  This output property list of wrapper files generated during SWIG compilation.
+
+  .. code-block:: cmake
+
+    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+    get_property(support_files TARGET mymod PROPERTY SWIG_SUPPORT_FILES)
+
 Some variables can be set to specify special behavior of SWIG:
 
 ``CMAKE_SWIG_FLAGS``
@@ -66,34 +129,56 @@
   Specify extra dependencies for the generated module for ``<name>``.
 #]=======================================================================]
 
+
+cmake_policy (VERSION 3.11)
+
 set(SWIG_CXX_EXTENSION "cxx")
 set(SWIG_EXTRA_LIBRARIES "")
 
 set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
 set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
 
+##
+## PRIVATE functions
+##
+function (__SWIG_COMPUTE_TIMESTAMP name language infile workingdir __timestamp)
+  get_filename_component(filename "${infile}" NAME_WE)
+  set(${__timestamp}
+    "${workingdir}/${filename}${language}.stamp" PARENT_SCOPE)
+  # get_filename_component(filename "${infile}" ABSOLUTE)
+  # string(UUID uuid NAMESPACE 9735D882-D2F8-4E1D-88C9-A0A4F1F6ECA4
+  #   NAME ${name}-${language}-${filename} TYPE SHA1)
+  # set(${__timestamp} "${workingdir}/${uuid}.stamp" PARENT_SCOPE)
+endfunction()
+
 #
 # For given swig module initialize variables associated with it
 #
 macro(SWIG_MODULE_INITIALIZE name language)
-  string(TOUPPER "${language}" swig_uppercase_language)
-  string(TOLOWER "${language}" swig_lowercase_language)
-  set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}")
-  set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}")
+  string(TOUPPER "${language}" SWIG_MODULE_${name}_LANGUAGE)
+  string(TOLOWER "${language}" SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG)
 
-  set(SWIG_MODULE_${name}_REAL_NAME "${name}")
-  if (";${CMAKE_SWIG_FLAGS};" MATCHES ";-noproxy;")
+  set(SWIG_MODULE_${name}_NAME "${name}")
+  set(SWIG_MODULE_${name}_EXTRA_FLAGS)
+  if (NOT DEFINED SWIG_MODULE_${name}_NOPROXY)
+    set (SWIG_MODULE_${name}_NOPROXY FALSE)
+  endif()
+  if ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
     set (SWIG_MODULE_${name}_NOPROXY TRUE)
   endif ()
-  if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xUNKNOWN")
+
+  if (SWIG_MODULE_${name}_NOPROXY AND NOT "-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
+    list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-noproxy")
+  endif()
+  if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "UNKNOWN")
     message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
-  elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
+  elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
     # swig will produce a module.py containing an 'import _modulename' statement,
     # which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32),
     # unless the -noproxy flag is used
-    set(SWIG_MODULE_${name}_REAL_NAME "_${name}")
-  elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPERL")
-    set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
+    set(SWIG_MODULE_${name}_NAME "_${name}")
+  elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PERL")
+    list(APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
   endif()
 endmacro()
 
@@ -102,79 +187,108 @@
 # will be generated. This is internal swig macro.
 #
 
-macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
-  set(${outfiles} "")
-  get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename
-    ${infile} SWIG_MODULE_NAME)
-  if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND")
+function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
+  set(files)
+  get_source_file_property(module_basename
+    "${infile}" SWIG_MODULE_NAME)
+  if(NOT swig_module_basename)
 
     # try to get module name from "%module foo" syntax
-    if ( EXISTS ${infile} )
-      file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
+    if ( EXISTS "${infile}" )
+      file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
     endif ()
-    if ( _MODULE_NAME )
-      string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" )
-      set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}")
+    if ( module_basename )
+      string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
 
     else ()
       # try to get module name from "%module (options=...) foo" syntax
-      if ( EXISTS ${infile} )
-        file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
+      if ( EXISTS "${infile}" )
+        file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
       endif ()
-      if ( _MODULE_NAME )
-        string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" )
-        set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}")
+      if ( module_basename )
+        string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
 
       else ()
         # fallback to file basename
-        get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename ${infile} NAME_WE)
+        get_filename_component(module_basename "${infile}" NAME_WE)
       endif ()
     endif ()
 
   endif()
   foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS})
-    set(extra_file "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}${it}")
-    list(APPEND ${outfiles} ${extra_file})
-    # Treat extra outputs as plain files regardless of language.
-    set_property(SOURCE "${extra_file}" PROPERTY LANGUAGE "")
+    set(extra_file "${generatedpath}/${module_basename}${it}")
+    list(APPEND files "${extra_file}")
   endforeach()
-endmacro()
+    # Treat extra outputs as plain files regardless of language.
+  set_source_files_properties(${files} PROPERTIES LANGUAGE "")
+
+  set (${outfiles} ${files} PARENT_SCOPE)
+endfunction()
 
 #
 # Take swig (*.i) file and add proper custom commands for it
 #
-macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
-  set(swig_full_infile ${infile})
+function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
   get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
-  get_source_file_property(swig_source_file_generated ${infile} GENERATED)
-  get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS)
-  get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS)
-  if("${swig_source_file_flags}" STREQUAL "NOTFOUND")
-    set(swig_source_file_flags "")
-  endif()
-  get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
+  get_source_file_property(swig_source_file_cplusplus "${infile}" CPLUSPLUS)
 
   # If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
   if(CMAKE_SWIG_OUTDIR)
-    set(swig_outdir ${CMAKE_SWIG_OUTDIR})
+    set(outdir ${CMAKE_SWIG_OUTDIR})
   else()
-    set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR})
+    set(outdir ${CMAKE_CURRENT_BINARY_DIR})
   endif()
 
   if(SWIG_OUTFILE_DIR)
-    set(swig_outfile_dir ${SWIG_OUTFILE_DIR})
+    set(outfiledir ${SWIG_OUTFILE_DIR})
   else()
-    set(swig_outfile_dir ${swig_outdir})
+    set(outfiledir ${outdir})
   endif()
 
+  if(SWIG_WORKING_DIR)
+    set (workingdir "${SWIG_WORKING_DIR}")
+  else()
+    set(workingdir "${outdir}")
+  endif()
+
+  set (swig_source_file_flags ${CMAKE_SWIG_FLAGS})
+  # handle various swig compile flags properties
+  get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES)
+  if (include_directories)
+    list (APPEND swig_source_file_flags "-I$<JOIN:${include_directories},$<SEMICOLON>-I>")
+  endif()
+  set (property "$<TARGET_PROPERTY:${name},SWIG_INCLUDE_DIRECTORIES>")
+  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
+
+  set (property "$<TARGET_PROPERTY:${name},SWIG_COMPILE_DEFINITIONS>")
+  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:${property},$<SEMICOLON>-D>>")
+  get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS)
+  if (compile_definitions)
+    list (APPEND swig_source_file_flags "-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>")
+  endif()
+
+  list (APPEND swig_source_file_flags "$<TARGET_PROPERTY:${name},SWIG_COMPILE_OPTIONS>")
+  get_source_file_property (compile_options "${infile}" COMPILE_OPTIONS)
+  if (compile_options)
+    list (APPEND swig_source_file_flags ${compile_options})
+  endif()
+
+  # legacy support
+  get_source_file_property (swig_flags "${infile}" SWIG_FLAGS)
+  if (swig_flags)
+    list (APPEND swig_source_file_flags ${swig_flags})
+  endif()
+
+  get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
+
   if (NOT SWIG_MODULE_${name}_NOPROXY)
     SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
       swig_extra_generated_files
-      "${swig_outdir}"
+      "${outdir}"
       "${swig_source_file_fullname}")
   endif()
   set(swig_generated_file_fullname
-    "${swig_outfile_dir}/${swig_source_file_name_we}")
+    "${outfiledir}/${swig_source_file_name_we}")
   # add the language into the name of the file (i.e. TCL_wrap)
   # this allows for the same .i file to be wrapped into different languages
   string(APPEND swig_generated_file_fullname
@@ -188,45 +302,47 @@
       ".c")
   endif()
 
-  #message("Full path to source file: ${swig_source_file_fullname}")
-  #message("Full path to the output file: ${swig_generated_file_fullname}")
-  get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
-  list(REMOVE_DUPLICATES cmake_include_directories)
-  set(swig_include_dirs)
-  foreach(it ${cmake_include_directories})
-    set(swig_include_dirs ${swig_include_dirs} "-I${it}")
-  endforeach()
+  get_directory_property (cmake_include_directories INCLUDE_DIRECTORIES)
+  list (REMOVE_DUPLICATES cmake_include_directories)
+  set (swig_include_dirs)
+  if (cmake_include_directories)
+    set (swig_include_dirs "-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>")
+  endif()
 
   set(swig_special_flags)
   # default is c, so add c++ flag if it is c++
   if(swig_source_file_cplusplus)
-    set(swig_special_flags ${swig_special_flags} "-c++")
+    list (APPEND swig_special_flags "-c++")
   endif()
-  if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xCSHARP")
-    if(NOT ";${swig_source_file_flags};${CMAKE_SWIG_FLAGS};" MATCHES ";-dllimport;")
+
+  set (swig_extra_flags)
+  if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "CSHARP")
+    if(NOT ("-dllimport" IN_LIST swig_source_file_flags OR "-dllimport" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
       # This makes sure that the name used in the generated DllImport
       # matches the library name created by CMake
-      set(SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport;${name}")
+      list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "${name}")
     endif()
   endif()
-  set(swig_extra_flags)
-  if(SWIG_MODULE_${name}_EXTRA_FLAGS)
-    set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
+  list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
+
+  # dependencies
+  set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${name},SWIG_DEPENDS>)
+  get_source_file_property(file_depends "${infile}" DEPENDS)
+  if (file_depends)
+    list (APPEND swig_dependencies ${file_depends})
   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")
-    get_filename_component(swig_generated_timestamp
-      "${swig_generated_file_fullname}" NAME_WE)
-    set(swig_gen_target gen_${name}_${swig_generated_timestamp})
-    set(swig_generated_timestamp
-      "${swig_outdir}/${swig_generated_timestamp}.stamp")
-    set(swig_custom_output ${swig_generated_timestamp})
+    __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
+      "${infile}" "${workingdir}" swig_generated_timestamp)
+    set(swig_custom_output "${swig_generated_timestamp}")
     set(swig_custom_products
       BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
     set(swig_timestamp_command
-      COMMAND ${CMAKE_COMMAND} -E touch ${swig_generated_timestamp})
+      COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
   else()
     set(swig_custom_output
       "${swig_generated_file_fullname}" ${swig_extra_generated_files})
@@ -236,34 +352,41 @@
   add_custom_command(
     OUTPUT ${swig_custom_output}
     ${swig_custom_products}
-    # Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
-    COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
+    # Let's create the ${outdir} at execution time, in case dir contains $(OutDir)
+    COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir}
     ${swig_timestamp_command}
     COMMAND "${SWIG_EXECUTABLE}"
-    ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
-    ${swig_source_file_flags}
-    ${CMAKE_SWIG_FLAGS}
-    -outdir ${swig_outdir}
+    "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
+    "${swig_source_file_flags}"
+    -outdir "${outdir}"
     ${swig_special_flags}
     ${swig_extra_flags}
-    ${swig_include_dirs}
+    "${swig_include_dirs}"
     -o "${swig_generated_file_fullname}"
     "${swig_source_file_fullname}"
     MAIN_DEPENDENCY "${swig_source_file_fullname}"
-    DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS}
+    DEPENDS ${swig_dependencies}
     IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
-    COMMENT "Swig source")
-  if(CMAKE_GENERATOR MATCHES "Make")
-    add_custom_target(${swig_gen_target} DEPENDS ${swig_generated_timestamp})
-  endif()
-  unset(swig_generated_timestamp)
-  unset(swig_custom_output)
-  unset(swig_custom_products)
-  unset(swig_timestamp_command)
+    COMMENT "Swig source"
+    COMMAND_EXPAND_LISTS)
   set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
     PROPERTIES GENERATED 1)
-  set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
-endmacro()
+
+  ## add all properties for generated file to various properties
+  get_property (include_directories SOURCE "${infile}" PROPERTY GENERATED_INCLUDE_DIRECTORIES)
+  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY INCLUDE_DIRECTORIES ${include_directories} $<TARGET_PROPERTY:${name},SWIG_GENERATED_INCLUDE_DIRECTORIES>)
+
+  get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS)
+  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_DEFINITIONS> ${compile_definitions})
+
+  get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS)
+  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_OPTIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_OPTIONS> ${compile_options})
+
+  set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
+
+  # legacy support
+  set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
+endfunction()
 
 #
 # Create Swig module
@@ -277,13 +400,26 @@
 endmacro()
 
 
-macro(SWIG_ADD_LIBRARY name)
-  set(options "")
+function(SWIG_ADD_LIBRARY name)
+  set(options NO_PROXY)
   set(oneValueArgs LANGUAGE
-                   TYPE)
+                   TYPE
+                   OUTPUT_DIR
+                   OUTFILE_DIR)
   set(multiValueArgs SOURCES)
   cmake_parse_arguments(_SAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
+  if (TARGET ${name})
+    # a target with same name is already defined.
+    # call NOW add_library command to raise the most useful error message
+    add_library(${name})
+    return()
+  endif()
+
+  if (_SAM_UNPARSED_ARGUMENTS)
+    message(FATAL_ERROR "SWIG_ADD_LIBRARY: ${_SAM_UNPARSED_ARGUMENTS}: unexpected arguments")
+  endif()
+
   if(NOT DEFINED _SAM_LANGUAGE)
     message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing LANGUAGE argument")
   endif()
@@ -294,50 +430,83 @@
 
   if(NOT DEFINED _SAM_TYPE)
     set(_SAM_TYPE MODULE)
-  elseif("${_SAM_TYPE}" STREQUAL "USE_BUILD_SHARED_LIBS")
+  elseif(_SAM_TYPE STREQUAL "USE_BUILD_SHARED_LIBS")
     unset(_SAM_TYPE)
   endif()
 
+  set (workingdir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${name}.dir")
+  # set special variable to pass extra information to command SWIG_ADD_SOURCE_TO_MODULE
+  # which cannot be changed due to legacy compatibility
+  set (SWIG_WORKING_DIR "${workingdir}")
+
+  set (outputdir "${_SAM_OUTPUT_DIR}")
+  if (NOT _SAM_OUTPUT_DIR)
+    if (CMAKE_SWIG_OUTDIR)
+      set (outputdir "${CMAKE_SWIG_OUTDIR}")
+    else()
+      set (outputdir "${CMAKE_CURRENT_BINARY_DIR}")
+    endif()
+  endif()
+
+  set (outfiledir "${_SAM_OUTFILE_DIR}")
+  if(NOT _SAM_OUTFILE_DIR)
+    if (SWIG_OUTFILE_DIR)
+      set (outfiledir "${SWIG_OUTFILE_DIR}")
+    else()
+      if (_SAM_OUTPUT_DIR OR CMAKE_SWIG_OUTDIR)
+        set (outfiledir "${outputdir}")
+    else()
+        set (outfiledir "${workingdir}")
+      endif()
+    endif()
+  endif()
+  # set again, locally, predefined variables to ensure compatibility
+  # with command SWIG_ADD_SOURCE_TO_MODULE
+  set(CMAKE_SWIG_OUTDIR "${outputdir}")
+  set(SWIG_OUTFILE_DIR "${outfiledir}")
+
+  set (SWIG_MODULE_${name}_NOPROXY ${_SAM_NO_PROXY})
   swig_module_initialize(${name} ${_SAM_LANGUAGE})
 
-  set(swig_dot_i_sources)
-  set(swig_other_sources)
-  foreach(it ${_SAM_SOURCES})
-    if(${it} MATCHES "\\.i$")
-      set(swig_dot_i_sources ${swig_dot_i_sources} "${it}")
-    else()
-      set(swig_other_sources ${swig_other_sources} "${it}")
-    endif()
-  endforeach()
+  set(swig_dot_i_sources ${_SAM_SOURCES})
+  list(FILTER swig_dot_i_sources INCLUDE REGEX "\\.i$")
+  set(swig_other_sources ${_SAM_SOURCES})
+  list(REMOVE_ITEM swig_other_sources ${swig_dot_i_sources})
 
   set(swig_generated_sources)
-  set(swig_generated_targets)
-  foreach(it ${swig_dot_i_sources})
-    SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it})
-    set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}")
-    list(APPEND swig_generated_targets "${swig_gen_target}")
+  set(swig_generated_timestamps)
+  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)
+      list (APPEND swig_generated_timestamps "${swig_timestamp}")
+    endif()
   endforeach()
-  get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
-  set_directory_properties(PROPERTIES
-    ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}")
-  add_library(${SWIG_MODULE_${name}_REAL_NAME}
+  set_property (DIRECTORY APPEND PROPERTY
+    ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
+
+  add_library(${name}
     ${_SAM_TYPE}
     ${swig_generated_sources}
     ${swig_other_sources})
+  set_target_properties(${name} PROPERTIES OUTPUT_NAME "${SWIG_MODULE_${name}_NAME}")
   if(CMAKE_GENERATOR MATCHES "Make")
     # see IMPLICIT_DEPENDS above
-    add_dependencies(${SWIG_MODULE_${name}_REAL_NAME} ${swig_generated_targets})
+    add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
+    add_dependencies(${name} ${name}_swig_compilation)
   endif()
-  if("${_SAM_TYPE}" STREQUAL "MODULE")
-    set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES NO_SONAME ON)
+  if(_SAM_TYPE STREQUAL "MODULE")
+    set_target_properties(${name} PROPERTIES NO_SONAME ON)
   endif()
   string(TOLOWER "${_SAM_LANGUAGE}" swig_lowercase_language)
-  if ("${swig_lowercase_language}" STREQUAL "octave")
-    set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
-    set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".oct")
-  elseif ("${swig_lowercase_language}" STREQUAL "go")
-    set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
-  elseif ("${swig_lowercase_language}" STREQUAL "java")
+  if (swig_lowercase_language STREQUAL "octave")
+    set_target_properties(${name} PROPERTIES PREFIX "")
+    set_target_properties(${name} PROPERTIES SUFFIX ".oct")
+  elseif (swig_lowercase_language STREQUAL "go")
+    set_target_properties(${name} PROPERTIES PREFIX "")
+  elseif (swig_lowercase_language STREQUAL "java")
     if (APPLE)
         # In java you want:
         #      System.loadLibrary("LIBRARY");
@@ -345,15 +514,15 @@
         #   MacOS  : libLIBRARY.jnilib
         #   Windows: LIBRARY.dll
         #   Linux  : libLIBRARY.so
-        set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib")
+        set_target_properties (${name} PROPERTIES SUFFIX ".jnilib")
       endif ()
-  elseif ("${swig_lowercase_language}" STREQUAL "lua")
-    if("${_SAM_TYPE}" STREQUAL "MODULE")
-      set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+  elseif (swig_lowercase_language STREQUAL "lua")
+    if(_SAM_TYPE STREQUAL "MODULE")
+      set_target_properties(${name} PROPERTIES PREFIX "")
     endif()
-  elseif ("${swig_lowercase_language}" STREQUAL "python")
+  elseif (swig_lowercase_language STREQUAL "python")
     # this is only needed for the python case where a _modulename.so is generated
-    set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+    set_target_properties(${name} PROPERTIES PREFIX "")
     # Python extension modules on Windows must have the extension ".pyd"
     # instead of ".dll" as of Python 2.5.  Older python versions do support
     # this suffix.
@@ -363,34 +532,60 @@
     # .pyd is now the only filename extension that will be searched for.
     # </quote>
     if(WIN32 AND NOT CYGWIN)
-      set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd")
+      set_target_properties(${name} PROPERTIES SUFFIX ".pyd")
     endif()
-  elseif ("${swig_lowercase_language}" STREQUAL "r")
-    set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
-  elseif ("${swig_lowercase_language}" STREQUAL "ruby")
+  elseif (swig_lowercase_language STREQUAL "r")
+    set_target_properties(${name} PROPERTIES PREFIX "")
+  elseif (swig_lowercase_language STREQUAL "ruby")
     # In ruby you want:
     #      require 'LIBRARY'
     # then ruby will look for a library whose name is platform dependent, namely
     #   MacOS  : LIBRARY.bundle
     #   Windows: LIBRARY.dll
     #   Linux  : LIBRARY.so
-    set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+    set_target_properties (${name} PROPERTIES PREFIX "")
     if (APPLE)
-      set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".bundle")
+      set_target_properties (${name} PROPERTIES SUFFIX ".bundle")
+    endif ()
+  elseif (swig_lowercase_language STREQUAL "perl")
+    # assume empty prefix because we expect the module to be dynamically loaded
+    set_target_properties (${name} PROPERTIES PREFIX "")
+    if (APPLE)
+      set_target_properties (${name} PROPERTIES SUFFIX ".dylib")
     endif ()
   else()
     # assume empty prefix because we expect the module to be dynamically loaded
-    set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+    set_target_properties (${name} PROPERTIES PREFIX "")
   endif ()
-endmacro()
+  # target property SWIG_SUPPORT_FILES lists proxy support files
+  if (NOT SWIG_MODULE_${name}_NOPROXY)
+    string(TOUPPER "${_SAM_LANGUAGE}" swig_uppercase_language)
+    foreach (swig_it IN LISTS SWIG_${swig_uppercase_language}_EXTRA_FILE_EXTENSIONS)
+      set (swig_support_files ${swig_generated_sources})
+      list (FILTER swig_support_files INCLUDE REGEX ".*${swig_it}$")
+      set_property (TARGET ${name} APPEND PROPERTY SWIG_SUPPORT_FILES ${swig_support_files})
+    endforeach()
+  endif()
+
+  # to ensure legacy behavior, export some variables
+  set (SWIG_MODULE_${name}_LANGUAGE "${SWIG_MODULE_${name}_LANGUAGE}" PARENT_SCOPE)
+  set (SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" PARENT_SCOPE)
+  set (SWIG_MODULE_${name}_REAL_NAME "${name}" PARENT_SCOPE)
+  set (SWIG_MODULE_${name}_NOPROXY "${SWIG_MODULE_${name}_NOPROXY}" PARENT_SCOPE)
+  set (SWIG_MODULE_${name}_EXTRA_FLAGS "${SWIG_MODULE_${name}_EXTRA_FLAGS}" PARENT_SCOPE)
+  # the last one is a bit crazy but it is documented, so...
+  # NOTA: works as expected if only ONE input file is specified
+  set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
+endfunction()
 
 #
 # Like TARGET_LINK_LIBRARIES but for swig modules
 #
-macro(SWIG_LINK_LIBRARIES name)
+function(SWIG_LINK_LIBRARIES name)
+  message(DEPRECATION "SWIG_LINK_LIBRARIES is deprecated. Use TARGET_LINK_LIBRARIES instead.")
   if(SWIG_MODULE_${name}_REAL_NAME)
-    target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
+    target_link_libraries(${name} ${ARGN})
   else()
     message(SEND_ERROR "Cannot find Swig library \"${name}\".")
   endif()
-endmacro()
+endfunction()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 1aa1ccc..27281fe 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 11)
-set(CMake_VERSION_PATCH 20180207)
+set(CMake_VERSION_PATCH 20180216)
 #set(CMake_VERSION_RC 1)
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 6f31a2d..817b5d9 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
 #include "cmGeneratorTarget.h"
 #include "cmLinkItem.h"
 #include "cmLocalGenerator.h"
@@ -101,12 +102,21 @@
         os << "LOCAL_CPP_FEATURES += ";
         os << (property.second) << "\n";
       } else if (property.first == "INTERFACE_LINK_LIBRARIES") {
+        // evaluate any generator expressions with the current
+        // build type of the makefile
+        cmGeneratorExpression ge;
+        cmGeneratorExpressionDAGChecker dagChecker(
+          target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
+        std::unique_ptr<cmCompiledGeneratorExpression> cge =
+          ge.Parse(property.second);
+        std::string evaluated = cge->Evaluate(
+          target->GetLocalGenerator(), config, false, target, &dagChecker);
         // need to look at list in pi->second and see if static or shared
         // FindTargetToLink
         // target->GetLocalGenerator()->FindGeneratorTargetToUse()
         // then add to LOCAL_CPPFLAGS
         std::vector<std::string> libraries;
-        cmSystemTools::ExpandListArgument(property.second, libraries);
+        cmSystemTools::ExpandListArgument(evaluated, libraries);
         std::string staticLibs;
         std::string sharedLibs;
         std::string ldlibs;
@@ -122,12 +132,6 @@
               staticLibs += " " + lib;
             }
           } else {
-            // evaluate any generator expressions with the current
-            // build type of the makefile
-            cmGeneratorExpression ge;
-            std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(lib);
-            std::string evaluated =
-              cge->Evaluate(target->GetLocalGenerator(), config);
             bool relpath = false;
             if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
               relpath = lib.substr(0, 3) == "../";
@@ -135,12 +139,12 @@
             // check for full path or if it already has a -l, or
             // in the case of an install check for relative paths
             // if it is full or a link library then use string directly
-            if (cmSystemTools::FileIsFullPath(evaluated) ||
-                evaluated.substr(0, 2) == "-l" || relpath) {
-              ldlibs += " " + evaluated;
+            if (cmSystemTools::FileIsFullPath(lib) ||
+                lib.substr(0, 2) == "-l" || relpath) {
+              ldlibs += " " + lib;
               // if it is not a path and does not have a -l then add -l
-            } else if (!evaluated.empty()) {
-              ldlibs += " -l" + evaluated;
+            } else if (!lib.empty()) {
+              ldlibs += " -l" + lib;
             }
           }
         }
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 417cdd2..7069386 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -225,8 +225,8 @@
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
 
-  // Add CMake varibles of the same name as the previous environment
-  // varibles CMAKE_*_PATH to be used most of the time with -D
+  // Add CMake variables of the same name as the previous environment
+  // variables CMAKE_*_PATH to be used most of the time with -D
   // command line options
   std::string var = "CMAKE_";
   var += this->CMakePathName;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index b1afdc9..2a38599 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -542,6 +542,7 @@
   makefileStream.SetCopyIfDifferent(true);
   makefileStream << "# Generated by CMake, DO NOT EDIT\n\n";
 
+  makefileStream << "TARGETS:= \n";
   makefileStream << "empty:= \n";
   makefileStream << "space:= $(empty) $(empty)\n";
   makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n";
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 8c889fc..c1af92f 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <utility>
 
+#include "cmCryptoHash.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandGenerator.h"
 #include "cmGeneratedFileStream.h"
@@ -24,6 +25,7 @@
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
+#include "cmsys/FStream.hxx"
 
 cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
                                              cmMakefile* mf)
@@ -286,8 +288,51 @@
   }
 }
 
+std::string cmLocalNinjaGenerator::WriteCommandScript(
+  std::vector<std::string> const& cmdLines, std::string const& customStep,
+  cmGeneratorTarget const* target) const
+{
+  std::string scriptPath;
+  if (target) {
+    scriptPath = target->GetSupportDirectory();
+  } else {
+    scriptPath = this->GetCurrentBinaryDirectory();
+    scriptPath += cmake::GetCMakeFilesDirectory();
+  }
+  cmSystemTools::MakeDirectory(scriptPath);
+  scriptPath += '/';
+  scriptPath += customStep;
+#ifdef _WIN32
+  scriptPath += ".bat";
+#else
+  scriptPath += ".sh";
+#endif
+
+  cmsys::ofstream script(scriptPath.c_str());
+
+#ifndef _WIN32
+  script << "set -e\n\n";
+#endif
+
+  for (auto const& i : cmdLines) {
+    std::string cmd = i;
+    // The command line was built assuming it would be written to
+    // the build.ninja file, so it uses '$$' for '$'.  Remove this
+    // for the raw shell script.
+    cmSystemTools::ReplaceString(cmd, "$$", "$");
+#ifdef _WIN32
+    script << cmd << " || exit /b" << '\n';
+#else
+    script << cmd << '\n';
+#endif
+  }
+
+  return scriptPath;
+}
+
 std::string cmLocalNinjaGenerator::BuildCommandLine(
-  const std::vector<std::string>& cmdLines)
+  std::vector<std::string> const& cmdLines, std::string const& customStep,
+  cmGeneratorTarget const* target) const
 {
   // If we have no commands but we need to build a command anyway, use noop.
   // This happens when building a POST_BUILD value for link targets that
@@ -296,6 +341,35 @@
     return cmGlobalNinjaGenerator::SHELL_NOOP;
   }
 
+  // If this is a custom step then we will have no '$VAR' ninja placeholders.
+  // This means we can deal with long command sequences by writing to a script.
+  // Do this if the command lines are on the scale of the OS limit.
+  if (!customStep.empty()) {
+    size_t cmdLinesTotal = 0;
+    for (std::string const& cmd : cmdLines) {
+      cmdLinesTotal += cmd.length() + 6;
+    }
+    if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
+      std::string const scriptPath =
+        this->WriteCommandScript(cmdLines, customStep, target);
+      std::string cmd
+#ifndef _WIN32
+        = "/bin/sh "
+#endif
+        ;
+      cmd += this->ConvertToOutputFormat(
+        this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath),
+        cmOutputConverter::SHELL);
+
+      // Add an unused argument based on script content so that Ninja
+      // knows when the command lines change.
+      cmd += " ";
+      cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+      cmd += hash.HashFile(scriptPath).substr(0, 16);
+      return cmd;
+    }
+  }
+
   std::ostringstream cmd;
   for (std::vector<std::string>::const_iterator li = cmdLines.begin();
        li != cmdLines.end(); ++li)
@@ -406,10 +480,16 @@
       "Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps,
       cmNinjaDeps(), orderOnlyDeps, cmNinjaVars());
   } else {
+    std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+    // Hash full path to make unique.
+    customStep += '-';
+    cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+    customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+
     this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
-      this->BuildCommandLine(cmdLines), this->ConstructComment(ccg),
-      "Custom command for " + ninjaOutputs[0], cc->GetDepfile(),
-      cc->GetUsesTerminal(),
+      this->BuildCommandLine(cmdLines, customStep),
+      this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
+      cc->GetDepfile(), cc->GetUsesTerminal(),
       /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
       orderOnlyDeps);
   }
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 95d8a61..f772fb0 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -59,7 +59,10 @@
     return this->HomeRelativeOutputPath;
   }
 
-  std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
+  std::string BuildCommandLine(
+    std::vector<std::string> const& cmdLines,
+    std::string const& customStep = std::string(),
+    cmGeneratorTarget const* target = nullptr) const;
 
   void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
   void AppendTargetDepends(
@@ -98,6 +101,10 @@
 
   std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
 
+  std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
+                                 std::string const& customStep,
+                                 cmGeneratorTarget const* target) const;
+
   std::string HomeRelativeOutputPath;
 
   typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*>>
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index b468208..82c6e81 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -3641,6 +3641,20 @@
 
 const char* cmMakefile::GetProperty(const std::string& prop) const
 {
+  // Check for computed properties.
+  static std::string output;
+  if (prop == "TESTS") {
+    std::vector<std::string> keys;
+    // get list of keys
+    std::transform(this->Tests.begin(), this->Tests.end(),
+                   std::back_inserter(keys),
+                   [](decltype(this->Tests)::value_type const& pair) {
+                     return pair.first;
+                   });
+    output = cmJoin(keys, ";");
+    return output.c_str();
+  }
+
   return this->StateSnapshot.GetDirectory().GetProperty(prop);
 }
 
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index ddbc772..f1fb2d2 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -976,8 +976,10 @@
     preLinkCmdLines.push_back("cd " + homeOutDir);
   }
 
-  vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
-  std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines);
+  vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
+                                               this->GeneratorTarget);
+  std::string postBuildCmdLine = localGen.BuildCommandLine(
+    postBuildCmdLines, "post-build", this->GeneratorTarget);
 
   cmNinjaVars symlinkVars;
   bool const symlinkNeeded =
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 7adeb8e..cc6d4b9 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -96,8 +96,8 @@
       this->GetBuildFileStream(),
       "Utility command for " + this->GetTargetName(), outputs, deps);
   } else {
-    std::string command =
-      this->GetLocalGenerator()->BuildCommandLine(commands);
+    std::string command = this->GetLocalGenerator()->BuildCommandLine(
+      commands, "utility", this->GeneratorTarget);
     const char* echoStr =
       this->GetGeneratorTarget()->GetProperty("EchoString");
     std::string desc;
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 41142e5..93c78b5 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -8,6 +8,7 @@
 #include "cmCustomCommandLines.h"
 #include "cmDuration.h"
 #include "cmFilePathChecksum.h"
+#include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmLinkItem.h"
@@ -22,7 +23,6 @@
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
-#include "cm_sys_stat.h"
 #include "cmake.h"
 #include "cmsys/FStream.hxx"
 #include "cmsys/SystemInformation.hxx"
@@ -867,34 +867,6 @@
     dir += cfg;
   }
 
-  auto OpenInfoFile = [](cmsys::ofstream& ofs,
-                         std::string const& fileName) -> bool {
-    // Ensure we have write permission
-    if (cmSystemTools::FileExists(fileName)) {
-      mode_t perm = 0;
-#if defined(_WIN32) && !defined(__CYGWIN__)
-      mode_t mode_write = S_IWRITE;
-#else
-      mode_t mode_write = S_IWUSR;
-#endif
-      cmSystemTools::GetPermissions(fileName, perm);
-      if (!(perm & mode_write)) {
-        cmSystemTools::SetPermissions(fileName, perm | mode_write);
-      }
-    }
-
-    ofs.open(fileName.c_str(),
-             (std::ios::out | std::ios::binary | std::ios::trunc));
-    if (!ofs) {
-      // File open error
-      std::string error = "Internal CMake error when trying to open file: ";
-      error += Quoted(fileName);
-      error += " for writing.";
-      cmSystemTools::Error(error.c_str());
-    }
-    return static_cast<bool>(ofs);
-  };
-
   // Generate autogen target info file
   if (this->MocEnabled || this->UicEnabled) {
     if (this->MocEnabled) {
@@ -911,8 +883,10 @@
       this->Parallel = std::to_string(GetParallelCPUCount());
     }
 
-    cmsys::ofstream ofs;
-    if (OpenInfoFile(ofs, this->AutogenInfoFile)) {
+    cmGeneratedFileStream ofs;
+    ofs.SetCopyIfDifferent(true);
+    ofs.Open(this->AutogenInfoFile.c_str(), false, true);
+    if (ofs) {
       // Utility lambdas
       auto CWrite = [&ofs](const char* key, std::string const& value) {
         ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
@@ -1012,14 +986,18 @@
         CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions);
         CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
       }
+    } else {
+      return;
     }
   }
 
   // Generate auto RCC info files
   if (this->RccEnabled) {
     for (Qrc const& qrc : this->Qrcs) {
-      cmsys::ofstream ofs;
-      if (OpenInfoFile(ofs, qrc.InfoFile)) {
+      cmGeneratedFileStream ofs;
+      ofs.SetCopyIfDifferent(true);
+      ofs.Open(qrc.InfoFile.c_str(), false, true);
+      if (ofs) {
         // Utility lambdas
         auto CWrite = [&ofs](const char* key, std::string const& value) {
           ofs << "set(" << key << " "
@@ -1069,7 +1047,7 @@
         CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
         CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
       } else {
-        break;
+        return;
       }
     }
   }
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index 6be65ee..37cf0f8 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -434,7 +434,7 @@
     JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName,
                                      std::move(jobPre.IncludeString)));
     if (jobPre.self) {
-      // Read depdendencies from this source
+      // Read dependencies from this source
       static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
     }
     if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
@@ -452,7 +452,7 @@
   if (!macroName.empty()) {
     JobHandleT jobHandle(
       new JobMocT(std::string(FileName), std::string(), std::string()));
-    // Read depdendencies from this source
+    // Read dependencies from this source
     static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
     success = wrk.Gen().ParallelJobPushMoc(jobHandle);
   }
@@ -1373,7 +1373,7 @@
       // Compare list sizes
       if (sources.size() != options.size()) {
         std::ostringstream ost;
-        ost << "files/options lists sizes missmatch (" << sources.size() << "/"
+        ost << "files/options lists sizes mismatch (" << sources.size() << "/"
             << options.size() << ")";
         Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str());
         return false;
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 7b19210..a7d8cee 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -24,7 +24,7 @@
     this->TargetImpLib = targetImpLib;
   }
 
-  // Create a struct to hold the varibles passed into
+  // Create a struct to hold the variables passed into
   // ExpandRuleVariables
   struct RuleVariables
   {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index cd11c4b..734ac93 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -509,7 +509,7 @@
 {
   std::string src = s;
 
-  // For backwards compatibility replace varibles in source names.
+  // For backwards compatibility replace variables in source names.
   // This should eventually be removed.
   this->Makefile->ExpandVariablesInString(src);
   if (src != s) {
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index ec31bd6..92d67db 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -84,16 +84,15 @@
 
 cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
   cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
+  : GeneratorTarget(target)
+  , Makefile(target->Target->GetMakefile())
+  , Platform(gg->GetPlatformName())
+  , Name(target->GetName())
+  , GUID(gg->GetGUID(this->Name))
+  , GlobalGenerator(gg)
+  , LocalGenerator((cmLocalVisualStudio7Generator*)target->GetLocalGenerator())
 {
-  this->GlobalGenerator = gg;
-  this->GeneratorTarget = target;
-  this->Makefile = target->Target->GetMakefile();
   this->Makefile->GetConfigurations(this->Configurations);
-  this->LocalGenerator =
-    (cmLocalVisualStudio7Generator*)this->GeneratorTarget->GetLocalGenerator();
-  this->Name = this->GeneratorTarget->GetName();
-  this->GUID = this->GlobalGenerator->GetGUID(this->Name);
-  this->Platform = gg->GetPlatformName();
   this->NsightTegra = gg->IsNsightTegra();
   for (int i = 0; i < 4; ++i) {
     this->NsightTegraVersion[i] = 0;
@@ -602,8 +601,7 @@
       if (!name.empty()) {
         std::string path = i.second.GetValue();
         if (!cmsys::SystemTools::FileIsFullPath(path)) {
-          path = std::string(this->GeneratorTarget->Target->GetMakefile()
-                               ->GetCurrentSourceDirectory()) +
+          path = std::string(this->Makefile->GetCurrentSourceDirectory()) +
             "/" + path;
         }
         ConvertToWindowsSlash(path);
@@ -994,11 +992,8 @@
 void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
   std::string const& config)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
-  const char* mfcFlag =
-    this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
-      "CMAKE_MFC_FLAG");
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+  const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
   if (mfcFlag) {
     std::string const mfcFlagValue = mfcFlag;
 
@@ -1046,8 +1041,7 @@
 void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
   std::string const& config)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
 
   Options& o = *(this->ClOptions[config]);
 
@@ -1100,8 +1094,7 @@
 void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
   std::string const&)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   const char* toolset = gg->GetPlatformToolset();
   std::string ntv = "<NdkToolchainVersion>";
   ntv += toolset ? toolset : "Default";
@@ -1226,7 +1219,7 @@
   for (std::vector<std::string>::const_iterator i =
          this->Configurations.begin();
        i != this->Configurations.end(); ++i) {
-    cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
+    cmCustomCommandGenerator ccg(command, *i, lg);
     std::string comment = lg->ConstructComment(ccg);
     comment = cmVS10EscapeComment(comment);
     std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg));
@@ -1236,7 +1229,7 @@
     for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
          d != ccg.GetDepends().end(); ++d) {
       std::string dep;
-      if (this->LocalGenerator->GetRealDependency(*d, *i, dep)) {
+      if (lg->GetRealDependency(*d, *i, dep)) {
         ConvertToWindowsSlash(dep);
         inputs << ";" << cmVS10EscapeXML(dep);
       }
@@ -1334,6 +1327,7 @@
     pos++;
   }
 }
+
 void cmVisualStudio10TargetGenerator::WriteGroups()
 {
   if (this->ProjectType == csproj) {
@@ -2110,8 +2104,7 @@
       (*this->BuildFileStream) << firstString;
       firstString = ""; // only do firstString once
       hasFlags = true;
-      cmGlobalVisualStudio10Generator* gg =
-        static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+      cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
       cmIDEFlagTable const* flagtable = nullptr;
       const std::string& srclang = source->GetLanguage();
       if (srclang == "C" || srclang == "CXX") {
@@ -2374,8 +2367,7 @@
   // copied from cmLocalVisualStudio7Generator.cxx 805
   // TODO: Integrate code below with cmLocalVisualStudio7Generator.
 
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   std::unique_ptr<Options> pOptions;
   switch (this->ProjectType) {
     case vcxproj:
@@ -2422,15 +2414,11 @@
     std::string baseFlagVar = "CMAKE_";
     baseFlagVar += langForClCompile;
     baseFlagVar += "_FLAGS";
-    flags =
-      this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
-        baseFlagVar);
+    flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
     std::string flagVar =
       baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
     flags += " ";
-    flags +=
-      this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
-        flagVar);
+    flags += this->Makefile->GetRequiredDefinition(flagVar);
     this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
                                             langForClCompile, configName);
   }
@@ -2446,8 +2434,7 @@
   this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
 
   // Get preprocessor definitions for this directory.
-  std::string defineFlags =
-    this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+  std::string defineFlags = this->Makefile->GetDefineFlags();
   if (this->MSTools) {
     if (this->ProjectType == vcxproj) {
       clOptions.FixExceptionHandlingDefault();
@@ -2605,8 +2592,7 @@
 bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
   std::string const& configName)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   auto pOptions = cm::make_unique<Options>(
     this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
   Options& rcOptions = *pOptions;
@@ -2666,8 +2652,7 @@
 bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
   std::string const& configName)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   auto pOptions = cm::make_unique<Options>(
     this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
   Options& cudaOptions = *pOptions;
@@ -2683,8 +2668,7 @@
                                           configName);
 
   // Get preprocessor definitions for this directory.
-  std::string defineFlags =
-    this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+  std::string defineFlags = this->Makefile->GetDefineFlags();
 
   cudaOptions.Parse(flags.c_str());
   cudaOptions.Parse(defineFlags.c_str());
@@ -2804,8 +2788,7 @@
 bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
   std::string const& configName)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   auto pOptions = cm::make_unique<Options>(
     this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
   Options& cudaLinkOptions = *pOptions;
@@ -2873,8 +2856,7 @@
 bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
   std::string const& configName)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   auto pOptions = cm::make_unique<Options>(
     this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
   Options& masmOptions = *pOptions;
@@ -2933,8 +2915,7 @@
 bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
   std::string const& configName)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   auto pOptions = cm::make_unique<Options>(
     this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
   Options& nasmOptions = *pOptions;
@@ -2994,8 +2975,7 @@
     libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
   if (!libflags.empty()) {
     this->WriteString("<Lib>\n", 2);
-    cmGlobalVisualStudio10Generator* gg =
-      static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+    cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
     cmVisualStudioGeneratorOptions libOptions(
       this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
       gg->GetLibFlagTable(), 0, this);
@@ -3185,8 +3165,7 @@
 bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
   std::string const& config)
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   auto pOptions =
     cm::make_unique<Options>(this->LocalGenerator, Options::Linker,
                              gg->GetLinkFlagTable(), nullptr, this);
@@ -3217,12 +3196,10 @@
   linkFlagVarBase += linkType;
   linkFlagVarBase += "_LINKER_FLAGS";
   flags += " ";
-  flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
-    linkFlagVarBase);
+  flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
   std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
   flags += " ";
-  flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
-    linkFlagVar);
+  flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
   const char* targetLinkFlags =
     this->GeneratorTarget->GetProperty("LINK_FLAGS");
   if (targetLinkFlags) {
@@ -3679,8 +3656,7 @@
     }
     // skip fortran targets as they can not be processed by MSBuild
     // the only reference will be in the .sln file
-    if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
-          ->TargetIsFortranOnly(dt)) {
+    if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
       continue;
     }
     this->WriteString("<ProjectReference Include=\"", 2);
@@ -3706,8 +3682,7 @@
     (*this->BuildFileStream) << name << "</Name>\n";
     this->WriteDotNetReferenceCustomTags(name);
     if (csproj == this->ProjectType) {
-      if (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
-             ->TargetCanBeReferenced(dt)) {
+      if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
         this->WriteString(
           "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
       }
@@ -3921,8 +3896,7 @@
 
 void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
 {
-  cmGlobalVisualStudio10Generator* gg =
-    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
   bool isAppContainer = false;
   bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
   bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 33d4fb7..adef127 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -190,19 +190,19 @@
   bool InSourceBuild;
   std::vector<std::string> Configurations;
   std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
-  cmGeneratorTarget* GeneratorTarget;
-  cmMakefile* Makefile;
-  std::string Platform;
-  std::string GUID;
-  std::string Name;
+  cmGeneratorTarget* const GeneratorTarget;
+  cmMakefile* const Makefile;
+  std::string const Platform;
+  std::string const Name;
+  std::string const GUID;
   bool MSTools;
   bool Managed;
   bool NsightTegra;
   int NsightTegraVersion[4];
   bool TargetCompileAsWinRT;
-  cmGlobalVisualStudio10Generator* GlobalGenerator;
+  cmGlobalVisualStudio10Generator* const GlobalGenerator;
   cmGeneratedFileStream* BuildFileStream;
-  cmLocalVisualStudio7Generator* LocalGenerator;
+  cmLocalVisualStudio7Generator* const LocalGenerator;
   std::set<cmSourceFile const*> SourcesVisited;
   std::set<std::string> CSharpCustomCommandNames;
   bool IsMissingFiles;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 08bfebe..62157bb 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -816,6 +816,8 @@
 
   ADD_TEST_MACRO(CustomCommandByproducts CustomCommandByproducts)
 
+  ADD_TEST_MACRO(CommandLength CommandLength)
+
   ADD_TEST_MACRO(EmptyDepends ${CMAKE_CTEST_COMMAND})
 
   add_test(CustomCommandWorkingDirectory  ${CMAKE_CTEST_COMMAND}
diff --git a/Tests/CTestTest/test.cmake.in b/Tests/CTestTest/test.cmake.in
index 589bd44..23166a7 100644
--- a/Tests/CTestTest/test.cmake.in
+++ b/Tests/CTestTest/test.cmake.in
@@ -62,7 +62,7 @@
 set (CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@/Tests/CTestTest")
 
 
-# set any extra environment varibles here
+# set any extra environment variables here
 set (CTEST_ENVIRONMENT
 )
 
diff --git a/Tests/CommandLength/CMakeLists.txt b/Tests/CommandLength/CMakeLists.txt
new file mode 100644
index 0000000..6836051
--- /dev/null
+++ b/Tests/CommandLength/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.10)
+project(CommandLength C)
+
+add_executable(CommandLength test.c)
+add_custom_command(TARGET CommandLength POST_BUILD VERBATIM
+  COMMAND ${CMAKE_COMMAND} -E make_directory log)
+
+set(msg "xxxx $$$$ yyyy")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+foreach(i RANGE 1 1000)
+  add_custom_command(TARGET CommandLength POST_BUILD VERBATIM
+    COMMAND ${CMAKE_COMMAND} -E echo "${i} ${msg}" > log/${i}
+    )
+endforeach()
diff --git a/Tests/CommandLength/test.c b/Tests/CommandLength/test.c
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/CommandLength/test.c
@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}
diff --git a/Tests/Complex/Cache/CMakeCache.txt b/Tests/Complex/Cache/CMakeCache.txt
index 17c55aa..727faa2 100644
--- a/Tests/Complex/Cache/CMakeCache.txt
+++ b/Tests/Complex/Cache/CMakeCache.txt
@@ -5,7 +5,7 @@
 # If you do want to change a value, simply edit, save, and exit the editor.
 # The syntax for the file is as follows:
 # KEY:TYPE=VALUE
-# KEY is the name of a varible in the cache.
+# KEY is the name of a variable in the cache.
 # TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.
 # VALUE is the current value for the KEY.
 
diff --git a/Tests/ComplexOneConfig/Cache/CMakeCache.txt b/Tests/ComplexOneConfig/Cache/CMakeCache.txt
index 17c55aa..727faa2 100644
--- a/Tests/ComplexOneConfig/Cache/CMakeCache.txt
+++ b/Tests/ComplexOneConfig/Cache/CMakeCache.txt
@@ -5,7 +5,7 @@
 # If you do want to change a value, simply edit, save, and exit the editor.
 # The syntax for the file is as follows:
 # KEY:TYPE=VALUE
-# KEY is the name of a varible in the cache.
+# KEY is the name of a variable in the cache.
 # TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.
 # VALUE is the current value for the KEY.
 
diff --git a/Tests/RunCMake/AndroidMK/AndroidMK.cmake b/Tests/RunCMake/AndroidMK/AndroidMK.cmake
index 2596e8c..3fbb2cf 100644
--- a/Tests/RunCMake/AndroidMK/AndroidMK.cmake
+++ b/Tests/RunCMake/AndroidMK/AndroidMK.cmake
@@ -4,7 +4,7 @@
 add_library(car foo.cxx)
 add_library(bar bar.c)
 add_library(dog  foo.cxx)
-target_link_libraries(foo car bar dog debug -lm)
+target_link_libraries(foo PRIVATE car bar dog debug -lm)
 export(TARGETS bar dog car foo  ANDROID_MK
   ${build_BINARY_DIR}/Android.mk)
 install(TARGETS bar dog car foo DESTINATION lib EXPORT myexp)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index d5bd297..31069fa 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -358,6 +358,11 @@
   add_RunCMake_test(FindMatlab)
 endif()
 
+# UseSWIG related tests
+if(CMake_TEST_UseSWIG)
+  add_RunCMake_test(UseSWIG)
+endif()
+
 add_executable(pseudo_emulator pseudo_emulator.c)
 add_executable(pseudo_emulator_custom_command pseudo_emulator_custom_command.c)
 add_RunCMake_test(CrosscompilingEmulator
diff --git a/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake b/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake
new file mode 100644
index 0000000..94d8dd3
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake
@@ -0,0 +1,68 @@
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+unset(SWIG_LANG_TYPE)
+unset(SWIG_LANG_INCLUDE_DIRECTORIES)
+unset(SWIG_LANG_DEFINITIONS)
+unset(SWIG_LANG_OPTIONS)
+unset(SWIG_LANG_LIBRARIES)
+
+if(${language} MATCHES python)
+  find_package(PythonInterp REQUIRED)
+  find_package(PythonLibs REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_PATH})
+  set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES})
+endif()
+if(${language} MATCHES perl)
+  find_package(Perl REQUIRED)
+  find_package(PerlLibs REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH})
+  separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+  set(SWIG_LANG_OPTIONS ${c_flags})
+  set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY})
+endif()
+if(${language} MATCHES tcl)
+  find_package(TCL REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${TCL_INCLUDE_PATH})
+  set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY})
+endif()
+if(${language} MATCHES ruby)
+  find_package(Ruby REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${RUBY_INCLUDE_PATH})
+  set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY})
+endif()
+if(${language} MATCHES php4)
+  find_package(PHP4 REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${PHP4_INCLUDE_PATH})
+  set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY})
+endif()
+if(${language} MATCHES pike)
+  find_package(Pike REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${PIKE_INCLUDE_PATH})
+  set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY})
+endif()
+if(${language} MATCHES lua)
+  find_package(Lua REQUIRED)
+  set(SWIG_LANG_INCLUDE_DIRECTORIES ${LUA_INCLUDE_DIR})
+  set(SWIG_LANG_TYPE TYPE SHARED)
+  set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
+endif()
+
+unset(CMAKE_SWIG_FLAGS)
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set_property(SOURCE example.i PROPERTY CPLUSPLUS ON)
+set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${SWIG_LANG_INCLUDE_DIRECTORIES})
+set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_DEFINITIONS ${SWIG_LANG_DEFINITIONS})
+set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_OPTIONS ${SWIG_LANG_OPTIONS})
+
+
+SWIG_ADD_LIBRARY(example
+                 LANGUAGE "${language}"
+                 ${SWIG_LANG_TYPE}
+                 SOURCES example.i example.cxx)
+TARGET_LINK_LIBRARIES(example PRIVATE ${SWIG_LANG_LIBRARIES})
diff --git a/Tests/RunCMake/UseSWIG/BasicPerl.cmake b/Tests/RunCMake/UseSWIG/BasicPerl.cmake
new file mode 100644
index 0000000..67ad6bc
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/BasicPerl.cmake
@@ -0,0 +1,18 @@
+
+set(language "perl")
+
+include (BasicConfiguration.cmake)
+
+if (WIN32)
+  file (TO_CMAKE_PATH "$ENV{PATH}" perl_path)
+  string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}")
+  set (perl_env "PATH=$<TARGET_FILE_DIR:example>$<SEMICOLON>${perl_path}")
+else()
+  set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:example>")
+endif()
+
+add_custom_target (RunTest
+  COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}"
+  "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:example>"
+  "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl"
+  DEPENDS example)
diff --git a/Tests/RunCMake/UseSWIG/BasicPython.cmake b/Tests/RunCMake/UseSWIG/BasicPython.cmake
new file mode 100644
index 0000000..0d8c824
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/BasicPython.cmake
@@ -0,0 +1,9 @@
+
+set(language "python")
+
+include (BasicConfiguration.cmake)
+
+add_custom_target (RunTest
+  COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example>"
+  "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py"
+  DEPENDS example)
diff --git a/Tests/RunCMake/UseSWIG/CMakeLists.txt b/Tests/RunCMake/UseSWIG/CMakeLists.txt
new file mode 100644
index 0000000..f452db1
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.4)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/SwigTest/CMakeLists.txt b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake
similarity index 70%
rename from Tests/SwigTest/CMakeLists.txt
rename to Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake
index 65f5c93..3ce0790 100644
--- a/Tests/SwigTest/CMakeLists.txt
+++ b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake
@@ -1,54 +1,55 @@
-set(language "python")
 
-cmake_minimum_required (VERSION 2.6)
-
-project(example_${language}_class)
+# Prevent deprecated warnings from new UseSWIG module
+set (CMAKE_WARN_DEPRECATED FALSE)
 
 find_package(SWIG REQUIRED)
 include(${SWIG_USE_FILE})
 
 unset(SWIG_LANG_TYPE)
 if(${language} MATCHES python)
-  find_package(PythonLibs)
+  find_package(PythonInterp REQUIRED)
+  find_package(PythonLibs REQUIRED)
   include_directories(${PYTHON_INCLUDE_PATH})
   set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES})
 endif()
 if(${language} MATCHES perl)
-  find_package(PerlLibs)
+  find_package(Perl REQUIRED)
+  find_package(PerlLibs REQUIRED)
   include_directories(${PERL_INCLUDE_PATH})
-  add_definitions(${PERL_EXTRA_C_FLAGS})
+  separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+  add_compile_options(${c_flags})
   set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY})
 endif()
 if(${language} MATCHES tcl)
-  find_package(TCL)
+  find_package(TCL REQUIRED)
   include_directories(${TCL_INCLUDE_PATH})
   set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY})
 endif()
 if(${language} MATCHES ruby)
-  find_package(Ruby)
+  find_package(Ruby REQUIRED)
   include_directories(${RUBY_INCLUDE_PATH})
   set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY})
 endif()
 if(${language} MATCHES php4)
-  find_package(PHP4)
+  find_package(PHP4 REQUIRED)
   include_directories(${PHP4_INCLUDE_PATH})
   set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY})
 endif()
 if(${language} MATCHES pike)
-  find_package(Pike)
+  find_package(Pike REQUIRED)
   include_directories(${PIKE_INCLUDE_PATH})
   set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY})
 endif()
 if(${language} MATCHES lua)
-  find_package(Lua)
+  find_package(Lua REQUIRED)
   include_directories(${LUA_INCLUDE_DIR})
   set(SWIG_LANG_TYPE TYPE SHARED)
   set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
 endif()
 
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+unset(CMAKE_SWIG_FLAGS)
 
-set(CMAKE_SWIG_FLAGS "")
+include_directories(${CMAKE_CURRENT_LIST_DIR})
 
 set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
 set_source_files_properties(example.i PROPERTIES SWIG_FLAGS "-includeall")
diff --git a/Tests/RunCMake/UseSWIG/LegacyPerl.cmake b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake
new file mode 100644
index 0000000..3428c46
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake
@@ -0,0 +1,18 @@
+
+set(language "perl")
+
+include (LegacyConfiguration.cmake)
+
+if (WIN32)
+  file (TO_CMAKE_PATH "$ENV{PATH}" perl_path)
+  string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}")
+  set (perl_env "PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>$<SEMICOLON>${perl_path}")
+else()
+  set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>")
+endif()
+
+add_custom_target (RunTest
+  COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}"
+  "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>"
+  "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl"
+  DEPENDS ${SWIG_MODULE_example_REAL_NAME})
diff --git a/Tests/RunCMake/UseSWIG/LegacyPython.cmake b/Tests/RunCMake/UseSWIG/LegacyPython.cmake
new file mode 100644
index 0000000..8b47aa2
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/LegacyPython.cmake
@@ -0,0 +1,9 @@
+
+set(language "python")
+
+include (LegacyConfiguration.cmake)
+
+add_custom_target (RunTest
+  COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>"
+  "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py"
+  DEPENDS ${SWIG_MODULE_example_REAL_NAME})
diff --git a/Tests/RunCMake/UseSWIG/MultipleModules.cmake b/Tests/RunCMake/UseSWIG/MultipleModules.cmake
new file mode 100644
index 0000000..e3d579f
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/MultipleModules.cmake
@@ -0,0 +1,30 @@
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(PythonLibs REQUIRED)
+find_package(PerlLibs REQUIRED)
+
+unset(CMAKE_SWIG_FLAGS)
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set_property(SOURCE example.i PROPERTY CPLUSPLUS ON)
+set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_PATH})
+
+swig_add_library(example1
+                 LANGUAGE python
+                 SOURCES example.i example.cxx)
+target_link_libraries(example1 PRIVATE ${PYTHON_LIBRARIES})
+
+# re-use sample interface file for another plugin
+set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH})
+separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_OPTIONS ${c_flags})
+
+swig_add_library(example2
+                 LANGUAGE perl
+                 SOURCES example.i example.cxx)
+target_link_libraries(example2 PRIVATE ${PERL_LIBRARY})
diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
new file mode 100644
index 0000000..c63ff2e
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
@@ -0,0 +1,23 @@
+include(RunCMake)
+
+function(run_SWIG test)
+  cmake_parse_arguments(_SWIG_TEST "" "TARGET" "" ${ARGN})
+  if (_SWIG_TEST_TARGET)
+    list (INSERT _SWIG_TEST_TARGET 0 --target)
+  endif()
+
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  run_cmake(${test})
+  run_cmake_command(${test}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} ${_SWIG_TEST_TARGET})
+endfunction()
+
+run_SWIG(LegacyPython TARGET RunTest)
+run_SWIG(LegacyPerl TARGET RunTest)
+
+run_SWIG(BasicPython TARGET RunTest)
+run_SWIG(BasicPerl TARGET RunTest)
+
+run_SWIG(MultipleModules)
diff --git a/Tests/SwigTest/example.cxx b/Tests/RunCMake/UseSWIG/example.cxx
similarity index 100%
rename from Tests/SwigTest/example.cxx
rename to Tests/RunCMake/UseSWIG/example.cxx
diff --git a/Tests/SwigTest/example.h b/Tests/RunCMake/UseSWIG/example.h
similarity index 100%
rename from Tests/SwigTest/example.h
rename to Tests/RunCMake/UseSWIG/example.h
diff --git a/Tests/SwigTest/example.i b/Tests/RunCMake/UseSWIG/example.i
similarity index 98%
rename from Tests/SwigTest/example.i
rename to Tests/RunCMake/UseSWIG/example.i
index 75700b3..fbdf724 100644
--- a/Tests/SwigTest/example.i
+++ b/Tests/RunCMake/UseSWIG/example.i
@@ -7,4 +7,3 @@
 
 /* Let's just grab the original header file here */
 %include "example.h"
-
diff --git a/Tests/SwigTest/runme.php4 b/Tests/RunCMake/UseSWIG/runme.php4
similarity index 100%
rename from Tests/SwigTest/runme.php4
rename to Tests/RunCMake/UseSWIG/runme.php4
diff --git a/Tests/SwigTest/runme.pike b/Tests/RunCMake/UseSWIG/runme.pike
old mode 100755
new mode 100644
similarity index 100%
rename from Tests/SwigTest/runme.pike
rename to Tests/RunCMake/UseSWIG/runme.pike
diff --git a/Tests/SwigTest/runme.pl b/Tests/RunCMake/UseSWIG/runme.pl
similarity index 99%
rename from Tests/SwigTest/runme.pl
rename to Tests/RunCMake/UseSWIG/runme.pl
index 5bfb3d8..965e063 100644
--- a/Tests/SwigTest/runme.pl
+++ b/Tests/RunCMake/UseSWIG/runme.pl
@@ -54,4 +54,3 @@
 
 print $examplec::Shape_nshapes," shapes remain\n";
 print "Goodbye\n";
-
diff --git a/Tests/RunCMake/UseSWIG/runme.py b/Tests/RunCMake/UseSWIG/runme.py
new file mode 100644
index 0000000..af5e07d
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/runme.py
@@ -0,0 +1,52 @@
+# file: runme.py
+
+# This file illustrates the shadow-class C++ interface generated
+# by SWIG.
+
+from __future__ import print_function
+
+import example
+
+# ----- Object creation -----
+
+print ("Creating some objects:")
+c = example.Circle(10)
+print ("    Created circle", c)
+s = example.Square(10)
+print ("    Created square", s)
+
+# ----- Access a static member -----
+
+print ("\nA total of", example.cvar.Shape_nshapes,"shapes were created")
+
+# ----- Member data access -----
+
+# Set the location of the object
+
+c.x = 20
+c.y = 30
+
+s.x = -10
+s.y = 5
+
+print ("\nHere is their current position:")
+print ("    Circle = (%f, %f)" % (c.x,c.y))
+print ("    Square = (%f, %f)" % (s.x,s.y))
+
+# ----- Call some methods -----
+
+print ("\nHere are some properties of the shapes:")
+for o in [c,s]:
+      print ("   ", o)
+      print ("        area      = ", o.area())
+      print ("        perimeter = ", o.perimeter())
+
+print ("\nGuess I'll clean up now")
+
+# Note: this invokes the virtual destructor
+del c
+del s
+
+s = 3
+print (example.cvar.Shape_nshapes,"shapes remain")
+print ("Goodbye")
diff --git a/Tests/SwigTest/runme.rb b/Tests/RunCMake/UseSWIG/runme.rb
similarity index 100%
rename from Tests/SwigTest/runme.rb
rename to Tests/RunCMake/UseSWIG/runme.rb
diff --git a/Tests/SwigTest/runme.tcl b/Tests/RunCMake/UseSWIG/runme.tcl
similarity index 99%
rename from Tests/SwigTest/runme.tcl
rename to Tests/RunCMake/UseSWIG/runme.tcl
index c7f4725..6055cf6 100644
--- a/Tests/SwigTest/runme.tcl
+++ b/Tests/RunCMake/UseSWIG/runme.tcl
@@ -47,4 +47,3 @@
 
 puts "$Shape_nshapes shapes remain"
 puts "Goodbye"
-
diff --git a/Tests/SwigTest/runme2.tcl b/Tests/RunCMake/UseSWIG/runme2.tcl
similarity index 99%
rename from Tests/SwigTest/runme2.tcl
rename to Tests/RunCMake/UseSWIG/runme2.tcl
index 88ec2f6..d0b5c21 100644
--- a/Tests/SwigTest/runme2.tcl
+++ b/Tests/RunCMake/UseSWIG/runme2.tcl
@@ -67,4 +67,3 @@
 
 puts "$Shape_nshapes shapes remain"
 puts "Goodbye"
-
diff --git a/Tests/RunCMake/get_property/directory_properties-stderr.txt b/Tests/RunCMake/get_property/directory_properties-stderr.txt
index 6d5bcdb..89f5618 100644
--- a/Tests/RunCMake/get_property/directory_properties-stderr.txt
+++ b/Tests/RunCMake/get_property/directory_properties-stderr.txt
@@ -19,4 +19,12 @@
 get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<--
 get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<--
 get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--
-get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--$
+get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--
+get_directory_property: --><--
+get_property: --><--
+get_directory_property: -->test1;test2<--
+get_property: -->test1;test2<--
+get_directory_property: -->test1;test2;test3<--
+get_property: -->test1;test2;test3<--
+get_directory_property: -->Sub/test1;Sub/test2<--
+get_property: -->Sub/test1;Sub/test2<--$
diff --git a/Tests/RunCMake/get_property/directory_properties.cmake b/Tests/RunCMake/get_property/directory_properties.cmake
index 4e68738..9b978fd 100644
--- a/Tests/RunCMake/get_property/directory_properties.cmake
+++ b/Tests/RunCMake/get_property/directory_properties.cmake
@@ -28,3 +28,12 @@
 check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SOURCE_DIR)
 check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" BINARY_DIR)
 check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" SOURCE_DIR)
+
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+add_test(NAME test1 COMMAND "${CMAKE_COMMAND}" -E echo "test1")
+add_test(NAME test2 COMMAND "${CMAKE_COMMAND}" -E echo "test2")
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+add_test(NAME test3 COMMAND "${CMAKE_COMMAND}" -E echo "test3")
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" TESTS)
diff --git a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
index 7318b97..95106ad 100644
--- a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
+++ b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
@@ -4,3 +4,6 @@
 add_custom_target(CustomSub)
 add_library(InterfaceSub INTERFACE)
 add_library(my::InterfaceSub ALIAS InterfaceSub)
+
+add_test(Sub/test1 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test1")
+add_test(Sub/test2 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test2")
diff --git a/Tests/SwigTest/runme.py b/Tests/SwigTest/runme.py
deleted file mode 100644
index ed3909e..0000000
--- a/Tests/SwigTest/runme.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# file: runme.py
-
-# This file illustrates the shadow-class C++ interface generated
-# by SWIG.
-
-import example
-
-# ----- Object creation -----
-
-print "Creating some objects:"
-c = example.Circle(10)
-print "    Created circle", c
-s = example.Square(10)
-print "    Created square", s
-
-# ----- Access a static member -----
-
-print "\nA total of", example.cvar.Shape_nshapes,"shapes were created"
-
-# ----- Member data access -----
-
-# Set the location of the object
-
-c.x = 20
-c.y = 30
-
-s.x = -10
-s.y = 5
-
-print "\nHere is their current position:"
-print "    Circle = (%f, %f)" % (c.x,c.y)
-print "    Square = (%f, %f)" % (s.x,s.y)
-
-# ----- Call some methods -----
-
-print "\nHere are some properties of the shapes:"
-for o in [c,s]:
-      print "   ", o
-      print "        area      = ", o.area()
-      print "        perimeter = ", o.perimeter()
-
-print "\nGuess I'll clean up now"
-
-# Note: this invokes the virtual destructor
-del c
-del s
-
-s = 3
-print example.cvar.Shape_nshapes,"shapes remain"
-print "Goodbye"
-