UseSWIG.cmake 33.8 KB
Newer Older
1 2 3
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

4 5 6 7
#[=======================================================================[.rst:
UseSWIG
-------

8 9 10 11
This file provides support for ``SWIG``. It is assumed that :module:`FindSWIG`
module has already been loaded.

Defines the following command for use with ``SWIG``:
12

13
.. command:: swig_add_library
14

15
  Define swig module with given name and specified language::
16

17 18 19
    swig_add_library(<name>
                     [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>]
                     LANGUAGE <language>
20 21 22
                     [NO_PROXY]
                     [OUTPUT_DIR <directory>]
                     [OUTFILE_DIR <directory>]
23
                     SOURCES <file>...
24
                    )
25

26 27 28 29
  Targets created with the ``swig_add_library`` command have the same
  capabilities as targets created with the :command:`add_library` command, so
  those targets can be used with any command expecting a target (e.g.
  :command:`target_link_libraries`).
30

31 32
  .. note::

33 34 35 36
    This command creates a target with the specified ``<name>`` when
    policy :policy:`CMP0078` is set to ``NEW``.  Otherwise, the legacy
    behavior will choose a different target name and store it in the
    ``SWIG_MODULE_<name>_REAL_NAME`` variable.
37

38 39 40 41 42
  .. note::

    For multi-config generators, this module does not support
    configuration-specific files generated by ``SWIG``. All build
    configurations must result in the same generated source file.
43

44
  ``TYPE``
45 46 47 48 49
    ``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the
    :command:`add_library` command. If ``USE_BUILD_SHARED_LIBS`` is specified,
    the library type will be ``STATIC`` or ``SHARED`` based on whether the
    current value of the :variable:`BUILD_SHARED_LIBS` variable is ``ON``. If
    no type is specified, ``MODULE`` will be used.
50

51 52
  ``LANGUAGE``
    Specify the target language.
53

54 55 56 57
  ``NO_PROXY``
    Prevent the generation of the wrapper layer (swig ``-noproxy`` option).

  ``OUTPUT_DIR``
58 59 60 61 62 63 64 65 66 67
    Specify where to write the language specific files (swig ``-outdir``
    option). If not given, the ``CMAKE_SWIG_OUTDIR`` variable will be used.
    If neither is specified, the default depends on the value of the
    ``UseSWIG_MODULE_VERSION`` variable as follows:

    * If ``UseSWIG_MODULE_VERSION`` is 1 or is undefined, output is written to
      the :variable:`CMAKE_CURRENT_BINARY_DIR` directory.
    * If ``UseSWIG_MODULE_VERSION`` is 2, a dedicated directory will be used.
      The path of this directory can be retrieved from the
      ``SWIG_SUPPORT_FILES_DIRECTORY`` target property.
68 69

  ``OUTFILE_DIR``
70 71 72 73
    Specify an output directory name where the generated source file will be
    placed (swig -o option). If not specified, the ``SWIG_OUTFILE_DIR`` variable
    will be used. If neither is specified, ``OUTPUT_DIR`` or
    ``CMAKE_SWIG_OUTDIR`` is used instead.
74 75

  ``SOURCES``
76 77
    List of sources for the library. Files with extension ``.i`` will be
    identified as sources for the ``SWIG`` tool. Other files will be handled in
78 79
    the standard way. This behavior can be overriden by specifying the variable
    ``SWIG_SOURCE_FILE_EXTENSIONS``.
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
  .. note::

    If ``UseSWIG_MODULE_VERSION`` is set to 2, it is **strongly** recommended
    to use a dedicated directory unique to the target when either the
    ``OUTPUT_DIR`` option or the ``CMAKE_SWIG_OUTDIR`` variable are specified.
    The output directory contents are erased as part of the target build, so
    to prevent interference between targets or losing other important files,
    each target should have its own dedicated output directory.

.. command:: swig_link_libraries

  Link libraries to swig module::

    swig_link_libraries(<name> <item>...)

  This command has same capabilities as :command:`target_link_libraries`
  command.

  .. note::
100

101 102 103
    If variable ``UseSWIG_TARGET_NAME_PREFERENCE`` is set to ``STANDARD``, this
    command is deprecated and :command:`target_link_libraries` command must be
    used instead.
104 105 106 107

Source file 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 the required settings.
108

109 110
``CPLUSPLUS``
  Call SWIG in c++ mode.  For example:
111

112
  .. code-block:: cmake
113

114 115
    set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON)
    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
116

117 118
``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS``
  Add custom flags to SWIG compiler and have same semantic as properties
119 120
  :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
  :prop_sf:`COMPILE_OPTIONS`.
121

122 123 124 125
``USE_TARGET_INCLUDE_DIRECTORIES``
  If set to ``TRUE``, contents of target property
  :prop_tgt:`INCLUDE_DIRECTORIES` will be forwarded to ``SWIG`` compiler.
  If set to ``FALSE`` target property :prop_tgt:`INCLUDE_DIRECTORIES` will be
126
  ignored. If not set, target property ``SWIG_USE_TARGET_INCLUDE_DIRECTORIES``
127 128
  will be considered.

129 130 131 132
``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.
133

134 135
``DEPENDS``
  Specify additional dependencies to the source file.
136

137 138 139 140
``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
  or different from the module file basename.  For example:
141

142
  .. code-block:: cmake
143

144 145
    set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname)

146 147 148 149 150
  .. note::

    If policy :policy:`CMP0086` is set to ``NEW``, ``-module <module_name>``
    is passed to ``SWIG`` compiler.

151 152
Target library properties can be set to apply same configuration to all SWIG
input files.
153 154

``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS``
155 156 157
  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`.
158 159 160

  .. code-block:: cmake

161
    set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
162 163 164 165
    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)

166 167 168 169 170 171 172
``SWIG_USE_TARGET_INCLUDE_DIRECTORIES``
  If set to ``TRUE``, contents of target property
  :prop_tgt:`INCLUDE_DIRECTORIES` will be forwarded to ``SWIG`` compiler.
  If set to ``FALSE`` or not defined, target property
  :prop_tgt:`INCLUDE_DIRECTORIES` will be ignored. This behavior can be
  overridden by specifying source property ``USE_TARGET_INCLUDE_DIRECTORIES``.

173
``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
174 175 176
  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.
177 178 179 180

``SWIG_DEPENDS``
  Add dependencies to all SWIG input files.

181 182 183
The following target properties are output properties and can be used to get
information about support files generated by ``SWIG`` interface compilation.

184 185 186 187 188
``SWIG_SUPPORT_FILES``
  This output property list of wrapper files generated during SWIG compilation.

  .. code-block:: cmake

189
    set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
190 191 192
    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
    get_property(support_files TARGET mymod PROPERTY SWIG_SUPPORT_FILES)

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
  .. note::

    Only most principal support files are listed. In case some advanced
    features of ``SWIG`` are used (for example ``%template``), associated
    support files may not be listed. Prefer to use the
    ``SWIG_SUPPORT_FILES_DIRECTORY`` property to handle support files.

``SWIG_SUPPORT_FILES_DIRECTORY``
  This output property specifies the directory where support files will be
  generated.

Some variables can be set to customize the behavior of ``swig_add_library``
as well as ``SWIG``:

``UseSWIG_MODULE_VERSION``
  Specify different behaviors for ``UseSWIG`` module.

  * Set to 1 or undefined: Legacy behavior is applied.
  * Set to 2: A new strategy is applied regarding support files: the output
    directory of support files is erased before ``SWIG`` interface compilation.
213 214 215 216 217 218 219 220

``CMAKE_SWIG_FLAGS``
  Add flags to all swig calls.

``CMAKE_SWIG_OUTDIR``
  Specify where to write the language specific files (swig ``-outdir`` option).

``SWIG_OUTFILE_DIR``
221 222
  Specify an output directory name where the generated source file will be
  placed.  If not specified, ``CMAKE_SWIG_OUTDIR`` is used.
223 224 225

``SWIG_MODULE_<name>_EXTRA_DEPS``
  Specify extra dependencies for the generated module for ``<name>``.
226 227 228 229 230 231 232 233 234

``SWIG_SOURCE_FILE_EXTENSIONS``
  Specify a list of source file extensions to override the default
  behavior of considering only ``.i`` files as sources for the ``SWIG``
  tool. For example:

  .. code-block:: cmake

    set(SWIG_SOURCE_FILE_EXTENSIONS ".i" ".swg")
235
#]=======================================================================]
236

237
cmake_policy(GET CMP0078 target_name_policy)
238 239
cmake_policy(GET CMP0086 module_name_policy)

240
cmake_policy (VERSION 3.12)
241 242 243 244
if (target_name_policy)
  # respect user choice regarding CMP0078 policy
  cmake_policy(SET CMP0078 ${target_name_policy})
endif()
245 246 247 248
if (module_name_policy)
  # respect user choice regarding CMP0086 policy
  cmake_policy(SET CMP0086 ${module_name_policy})
endif()
249
unset(target_name_policy)
250
unset(module_name_policy)
251

252 253
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
254

255 256
set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
257
set(SWIG_CSHARP_EXTRA_FILE_EXTENSIONS ".cs" "PINVOKE.cs")
258

259 260
set(SWIG_MANAGE_SUPPORT_FILES_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/UseSWIG/ManageSupportFiles.cmake")

261 262 263 264 265 266 267 268 269 270 271 272 273
##
## 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()

274 275 276
#
# For given swig module initialize variables associated with it
#
277
macro(SWIG_MODULE_INITIALIZE name language)
278 279
  string(TOUPPER "${language}" SWIG_MODULE_${name}_LANGUAGE)
  string(TOLOWER "${language}" SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG)
280

281 282 283 284
  if (NOT DEFINED SWIG_MODULE_${name}_NOPROXY)
    set (SWIG_MODULE_${name}_NOPROXY FALSE)
  endif()
  if ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
285 286
    set (SWIG_MODULE_${name}_NOPROXY TRUE)
  endif ()
287

288 289
  if (SWIG_MODULE_${name}_NOPROXY AND
      NOT ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS OR "-noproxy" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
290 291 292
    list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-noproxy")
  endif()
  if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "UNKNOWN")
293
    message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
294 295
  elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PERL" AND
         NOT "-shadow" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS)
296
    list(APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
297
  endif()
298
endmacro()
299 300 301

#
# For a given language, input file, and output file, determine extra files that
302
# will be generated. This is internal swig macro.
303 304
#

305 306 307 308
function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
  set(files)
  get_source_file_property(module_basename
    "${infile}" SWIG_MODULE_NAME)
309
  if(NOT module_basename)
310 311

    # try to get module name from "%module foo" syntax
312 313
    if ( EXISTS "${infile}" )
      file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
314
    endif ()
315 316
    if ( module_basename )
      string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
317 318 319

    else ()
      # try to get module name from "%module (options=...) foo" syntax
320 321
      if ( EXISTS "${infile}" )
        file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
322
      endif ()
323 324
      if ( module_basename )
        string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
325 326 327

      else ()
        # fallback to file basename
328
        get_filename_component(module_basename "${infile}" NAME_WE)
329 330 331
      endif ()
    endif ()

332
  endif()
333
  foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS})
334
    set(extra_file "${generatedpath}/${module_basename}${it}")
335
    if (extra_file MATCHES "\\.cs$" AND CMAKE_CSharp_COMPILER_LOADED)
336 337 338 339 340
      set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "CSharp")
    else()
      # Treat extra outputs as plain files regardless of language.
      set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "")
    endif()
341
    list(APPEND files "${extra_file}")
342
  endforeach()
343 344 345

  set (${outfiles} ${files} PARENT_SCOPE)
endfunction()
346 347 348 349

#
# Take swig (*.i) file and add proper custom commands for it
#
350
function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
351
  get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
352
  get_source_file_property(swig_source_file_cplusplus "${infile}" CPLUSPLUS)
353

354
  # If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
355
  if(CMAKE_SWIG_OUTDIR)
356
    set(outdir ${CMAKE_SWIG_OUTDIR})
357
  else()
358
    set(outdir ${CMAKE_CURRENT_BINARY_DIR})
359
  endif()
360 361

  if(SWIG_OUTFILE_DIR)
362
    set(outfiledir ${SWIG_OUTFILE_DIR})
363
  else()
364
    set(outfiledir ${outdir})
365 366
  endif()

367 368 369 370 371 372
  if(SWIG_WORKING_DIR)
    set (workingdir "${SWIG_WORKING_DIR}")
  else()
    set(workingdir "${outdir}")
  endif()

373 374 375 376 377 378
  if(SWIG_TARGET_NAME)
    set(target_name ${SWIG_TARGET_NAME})
  else()
    set(target_name ${name})
  endif()

379 380 381 382
  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)
383
    list (APPEND swig_source_file_flags "$<$<BOOL:${include_directories}>:-I$<JOIN:${include_directories},$<SEMICOLON>-I>>")
384
  endif()
385 386
  set (property "$<TARGET_PROPERTY:${target_name},SWIG_INCLUDE_DIRECTORIES>")
  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-I>>")
387
  set (property "$<TARGET_PROPERTY:${target_name},INCLUDE_DIRECTORIES>")
388 389 390 391 392
  get_source_file_property(use_target_include_dirs "${infile}" USE_TARGET_INCLUDE_DIRECTORIES)
  if (use_target_include_dirs)
    list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
  elseif(use_target_include_dirs STREQUAL "NOTFOUND")
    # not defined at source level, rely on target level
393
    list (APPEND swig_source_file_flags "$<$<AND:$<BOOL:$<TARGET_PROPERTY:${target_name},SWIG_USE_TARGET_INCLUDE_DIRECTORIES>>,$<BOOL:${property}>>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
394
  endif()
395

396 397
  set (property "$<TARGET_PROPERTY:${target_name},SWIG_COMPILE_DEFINITIONS>")
  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-D>>")
398 399
  get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS)
  if (compile_definitions)
400
    list (APPEND swig_source_file_flags "$<$<BOOL:${compile_definitions}>:-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>>")
401 402
  endif()

403
  list (APPEND swig_source_file_flags "$<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_COMPILE_OPTIONS>>")
404 405 406 407 408 409 410 411 412 413 414 415 416
  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)

417 418 419
  if (NOT SWIG_MODULE_${name}_NOPROXY)
    SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
      swig_extra_generated_files
420
      "${outdir}"
421 422
      "${swig_source_file_fullname}")
  endif()
423
  set(swig_generated_file_fullname
424
    "${outfiledir}/${swig_source_file_name_we}")
Bill Hoffman's avatar
Bill Hoffman committed
425 426
  # 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
427 428
  string(APPEND swig_generated_file_fullname
    "${SWIG_MODULE_${name}_LANGUAGE}_wrap")
429

430
  if(swig_source_file_cplusplus)
431 432
    string(APPEND swig_generated_file_fullname
      ".${SWIG_CXX_EXTENSION}")
433
  else()
434 435
    string(APPEND swig_generated_file_fullname
      ".c")
436
  endif()
437

438 439 440 441
  get_directory_property (cmake_include_directories INCLUDE_DIRECTORIES)
  list (REMOVE_DUPLICATES cmake_include_directories)
  set (swig_include_dirs)
  if (cmake_include_directories)
442
    set (swig_include_dirs "$<$<BOOL:${cmake_include_directories}>:-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>>")
443
  endif()
444

445
  set(swig_special_flags)
Bill Hoffman's avatar
Bill Hoffman committed
446
  # default is c, so add c++ flag if it is c++
447
  if(swig_source_file_cplusplus)
448
    list (APPEND swig_special_flags "-c++")
449
  endif()
450

451 452 453 454 455 456 457 458 459 460 461 462 463
  cmake_policy(GET CMP0086 module_name_policy)
  if (module_name_policy STREQUAL "NEW")
    get_source_file_property(module_name "${infile}" SWIG_MODULE_NAME)
    if (module_name)
      list (APPEND swig_special_flags "-module" "${module_name}")
    endif()
  else()
    if (NOT module_name_policy)
      cmake_policy(GET_WARNING CMP0086 _cmp0086_warning)
      message(AUTHOR_WARNING "${_cmp0086_warning}\n")
    endif()
  endif()

464 465 466
  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))
467 468
      # This makes sure that the name used in the generated DllImport
      # matches the library name created by CMake
469 470 471 472 473 474 475 476
      list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "$<TARGET_FILE_PREFIX:${target_name}>$<TARGET_FILE_BASE_NAME:${target_name}>")
    endif()
  endif()
  if (SWIG_MODULE_${name}_LANGUAGE STREQUAL "PYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
    if(NOT ("-interface" IN_LIST swig_source_file_flags OR "-interface" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
      # This makes sure that the name used in the proxy code
      # matches the library name created by CMake
      list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-interface" "$<TARGET_FILE_PREFIX:${target_name}>$<TARGET_FILE_BASE_NAME:${target_name}>")
477 478
    endif()
  endif()
479 480 481
  list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})

  # dependencies
482
  set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${target_name},SWIG_DEPENDS>)
483 484 485
  get_source_file_property(file_depends "${infile}" DEPENDS)
  if (file_depends)
    list (APPEND swig_dependencies ${file_depends})
486
  endif()
487

488
  if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
489 490
    # as part of custom command, start by removing old generated files
    # to ensure obsolete files do not stay
491 492 493
    set (swig_file_outdir "${workingdir}/${swig_source_file_name_we}.files")
    set (swig_cleanup_command COMMAND "${CMAKE_COMMAND}" "-DSUPPORT_FILES_WORKING_DIRECTORY=${swig_file_outdir}" "-DSUPPORT_FILES_OUTPUT_DIRECTORY=${outdir}" -DACTION=CLEAN -P "${SWIG_MANAGE_SUPPORT_FILES_SCRIPT}")
    set (swig_copy_command COMMAND "${CMAKE_COMMAND}" "-DSUPPORT_FILES_WORKING_DIRECTORY=${swig_file_outdir}" "-DSUPPORT_FILES_OUTPUT_DIRECTORY=${outdir}" -DACTION=COPY -P "${SWIG_MANAGE_SUPPORT_FILES_SCRIPT}")
494
  else()
495
    set (swig_file_outdir "${outdir}")
496
    unset (swig_cleanup_command)
497
    unset (swig_copy_command)
498 499
  endif()

500 501 502 503
  # 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")
504 505 506
    __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
      "${infile}" "${workingdir}" swig_generated_timestamp)
    set(swig_custom_output "${swig_generated_timestamp}")
507 508 509
    set(swig_custom_products
      BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
    set(swig_timestamp_command
510
      COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
511 512 513 514 515 516
  else()
    set(swig_custom_output
      "${swig_generated_file_fullname}" ${swig_extra_generated_files})
    set(swig_custom_products)
    set(swig_timestamp_command)
  endif()
517
  add_custom_command(
518 519
    OUTPUT ${swig_custom_output}
    ${swig_custom_products}
520
    ${swig_cleanup_command}
521 522
    # Let's create the ${outdir} at execution time, in case dir contains $(OutDir)
    COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir}
523
    ${swig_timestamp_command}
524
    COMMAND "${CMAKE_COMMAND}" -E env "SWIG_LIB=${SWIG_DIR}" "${SWIG_EXECUTABLE}"
525 526
    "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
    "${swig_source_file_flags}"
527
    -outdir "${swig_file_outdir}"
528 529
    ${swig_special_flags}
    ${swig_extra_flags}
530
    "${swig_include_dirs}"
531 532
    -o "${swig_generated_file_fullname}"
    "${swig_source_file_fullname}"
533
    ${swig_copy_command}
534
    MAIN_DEPENDENCY "${swig_source_file_fullname}"
535
    DEPENDS ${swig_dependencies}
536
    IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
537
    COMMENT "Swig compile ${infile} for ${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
538
    COMMAND_EXPAND_LISTS)
539
  set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
540
    PROPERTIES GENERATED 1)
541 542 543

  ## add all properties for generated file to various properties
  get_property (include_directories SOURCE "${infile}" PROPERTY GENERATED_INCLUDE_DIRECTORIES)
544
  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY INCLUDE_DIRECTORIES ${include_directories} $<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_GENERATED_INCLUDE_DIRECTORIES>>)
545 546

  get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS)
547
  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_GENERATED_COMPILE_DEFINITIONS>> ${compile_definitions})
548 549

  get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS)
550
  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_OPTIONS $<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_GENERATED_COMPILE_OPTIONS>> ${compile_options})
551

552 553 554 555
  if (SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG MATCHES "php")
    set_property (SOURCE "${swig_generated_file_fullname}" APPEND PROPERTY INCLUDE_DIRECTORIES "${outdir}")
  endif()

556 557 558 559 560
  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()
561 562 563 564

#
# Create Swig module
#
565
macro(SWIG_ADD_MODULE name language)
566 567 568 569 570 571 572 573
  message(DEPRECATION "SWIG_ADD_MODULE is deprecated. Use SWIG_ADD_LIBRARY instead.")
  swig_add_library(${name}
                   LANGUAGE ${language}
                   TYPE MODULE
                   SOURCES ${ARGN})
endmacro()


574 575
function(SWIG_ADD_LIBRARY name)
  set(options NO_PROXY)
576
  set(oneValueArgs LANGUAGE
577 578 579
                   TYPE
                   OUTPUT_DIR
                   OUTFILE_DIR)
580 581 582
  set(multiValueArgs SOURCES)
  cmake_parse_arguments(_SAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

583 584 585 586
  if (_SAM_UNPARSED_ARGUMENTS)
    message(FATAL_ERROR "SWIG_ADD_LIBRARY: ${_SAM_UNPARSED_ARGUMENTS}: unexpected arguments")
  endif()

587 588 589 590 591 592 593 594 595 596
  if(NOT DEFINED _SAM_LANGUAGE)
    message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing LANGUAGE argument")
  endif()

  if(NOT DEFINED _SAM_SOURCES)
    message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing SOURCES argument")
  endif()

  if(NOT DEFINED _SAM_TYPE)
    set(_SAM_TYPE MODULE)
597
  elseif(_SAM_TYPE STREQUAL "USE_BUILD_SHARED_LIBS")
598
    unset(_SAM_TYPE)
599 600
  endif()

601 602 603 604 605
  cmake_policy(GET CMP0078 target_name_policy)
  if (target_name_policy STREQUAL "NEW")
    set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
  else()
    if (NOT target_name_policy)
606 607
      cmake_policy(GET_WARNING CMP0078 _cmp0078_warning)
      message(AUTHOR_WARNING "${_cmp0078_warning}\n")
608 609 610 611 612 613
    endif()
    if (NOT DEFINED UseSWIG_TARGET_NAME_PREFERENCE)
      set (UseSWIG_TARGET_NAME_PREFERENCE LEGACY)
    elseif (NOT UseSWIG_TARGET_NAME_PREFERENCE MATCHES "^(LEGACY|STANDARD)$")
      message (FATAL_ERROR "UseSWIG_TARGET_NAME_PREFERENCE: ${UseSWIG_TARGET_NAME_PREFERENCE}: invalid value. 'LEGACY' or 'STANDARD' is expected.")
    endif()
614 615
  endif()

616 617 618 619 620 621
  if (NOT DEFINED UseSWIG_MODULE_VERSION)
    set (UseSWIG_MODULE_VERSION 1)
  elseif (NOT UseSWIG_MODULE_VERSION MATCHES "^(1|2)$")
    message (FATAL_ERROR "UseSWIG_MODULE_VERSION: ${UseSWIG_MODULE_VERSION}: invalid value. 1 or 2 is expected.")
  endif()

622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
  set (SWIG_MODULE_${name}_NOPROXY ${_SAM_NO_PROXY})
  swig_module_initialize(${name} ${_SAM_LANGUAGE})

  # compute real target name.
  if (UseSWIG_TARGET_NAME_PREFERENCE STREQUAL "LEGACY" AND
      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(target_name "_${name}")
  else()
    set(target_name "${name}")
  endif()

  if (TARGET ${target_name})
    # a target with same name is already defined.
    # call NOW add_library command to raise the most useful error message
    add_library(${target_name})
    return()
  endif()

  set (workingdir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${target_name}.dir")
644 645 646
  # 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}")
647
  set (SWIG_TARGET_NAME "${target_name}")
648

649 650 651 652
  set (outputdir "${_SAM_OUTPUT_DIR}")
  if (NOT _SAM_OUTPUT_DIR)
    if (CMAKE_SWIG_OUTDIR)
      set (outputdir "${CMAKE_SWIG_OUTDIR}")
653
    else()
654
      if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
655 656 657 658
        set (outputdir "${workingdir}/${_SAM_LANGUAGE}.files")
      else()
        set (outputdir "${CMAKE_CURRENT_BINARY_DIR}")
      endif()
659
    endif()
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
  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}")

679 680 681 682 683 684 685 686 687 688 689 690
  # See if the user has specified source extensions for swig files?
  if (NOT DEFINED SWIG_SOURCE_FILE_EXTENSIONS)
    # Assume the default (*.i) file extension for Swig source files
    set(SWIG_SOURCE_FILE_EXTENSIONS ".i")
  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)
  string (PREPEND swig_source_ext_regex "(")
  string (APPEND swig_source_ext_regex ")$")

691
  set(swig_dot_i_sources ${_SAM_SOURCES})
692
  list(FILTER swig_dot_i_sources INCLUDE REGEX ${swig_source_ext_regex})
693 694 695
  if (NOT swig_dot_i_sources)
    message(FATAL_ERROR "SWIG_ADD_LIBRARY: no SWIG interface files specified")
  endif()
696 697
  set(swig_other_sources ${_SAM_SOURCES})
  list(REMOVE_ITEM swig_other_sources ${swig_dot_i_sources})
698 699

  set(swig_generated_sources)
700 701 702 703 704 705 706 707 708
  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()
709
  endforeach()
710
  set_property (DIRECTORY APPEND PROPERTY
711
    ADDITIONAL_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
712
  if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
713
    set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${outputdir}")
714
  endif()
715

716
  add_library(${target_name}
717
    ${_SAM_TYPE}
718 719
    ${swig_generated_sources}
    ${swig_other_sources})
720 721
  if(CMAKE_GENERATOR MATCHES "Make")
    # see IMPLICIT_DEPENDS above
722
    add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
723
    add_dependencies(${target_name} ${name}_swig_compilation)
724
  endif()
725
  if(_SAM_TYPE STREQUAL "MODULE")
726
    set_target_properties(${target_name} PROPERTIES NO_SONAME ON)
727
  endif()
728
  string(TOLOWER "${_SAM_LANGUAGE}" swig_lowercase_language)
729
  if (swig_lowercase_language STREQUAL "octave")
730 731
    set_target_properties(${target_name} PROPERTIES PREFIX "")
    set_target_properties(${target_name} PROPERTIES SUFFIX ".oct")
732
  elseif (swig_lowercase_language STREQUAL "go")
733
    set_target_properties(${target_name} PROPERTIES PREFIX "")
734
  elseif (swig_lowercase_language STREQUAL "java")
735 736 737 738 739 740
    # In java you want:
    #      System.loadLibrary("LIBRARY");
    # then JNI will look for a library whose name is platform dependent, namely
    #   MacOS  : libLIBRARY.jnilib
    #   Windows: LIBRARY.dll
    #   Linux  : libLIBRARY.so
741
    if (APPLE)
742
      set_target_properties (${target_name} PROPERTIES SUFFIX ".jnilib")
743 744
    endif()
    if ((WIN32 AND MINGW) OR CYGWIN OR CMAKE_SYSTEM_NAME STREQUAL MSYS)
745
      set_target_properties(${target_name} PROPERTIES PREFIX "")
746
    endif()
747 748
  elseif (swig_lowercase_language STREQUAL "lua")
    if(_SAM_TYPE STREQUAL "MODULE")
749
      set_target_properties(${target_name} PROPERTIES PREFIX "")
750
    endif()
751
  elseif (swig_lowercase_language STREQUAL "python")
752
    if (UseSWIG_TARGET_NAME_PREFERENCE STREQUAL "STANDARD" AND NOT SWIG_MODULE_${name}_NOPROXY)
753 754 755
      # 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
756 757 758
      set_target_properties(${target_name} PROPERTIES PREFIX "_")
    else()
      set_target_properties(${target_name} PROPERTIES PREFIX "")
759
    endif()
760 761 762 763 764 765 766 767
    # 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.
    # http://docs.python.org/whatsnew/ports.html#SECTION0001510000000000000000
    # <quote>
    # Windows: .dll is no longer supported as a filename extension for extension modules.
    # .pyd is now the only filename extension that will be searched for.
    # </quote>
768
    if(WIN32 AND NOT CYGWIN)
769
      set_target_properties(${target_name} PROPERTIES SUFFIX ".pyd")
770
    endif()
771
  elseif (swig_lowercase_language STREQUAL "r")
772
    set_target_properties(${target_name} PROPERTIES PREFIX "")
773
  elseif (swig_lowercase_language STREQUAL "ruby")
774 775 776 777 778 779
    # 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
780
    set_target_properties (${target_name} PROPERTIES PREFIX "")
781
    if (APPLE)
782
      set_target_properties (${target_name} PROPERTIES SUFFIX ".bundle")
783
    endif ()
784
  elseif (swig_lowercase_language STREQUAL "perl")
785
    # assume empty prefix because we expect the module to be dynamically loaded
786
    set_target_properties (${target_name} PROPERTIES PREFIX "")
787
    if (APPLE)
788
      set_target_properties (${target_name} PROPERTIES SUFFIX ".dylib")
789
    endif ()
790 791
  else()
    # assume empty prefix because we expect the module to be dynamically loaded
792
    set_target_properties (${target_name} PROPERTIES PREFIX "")
793
  endif ()
794 795

  # target property SWIG_SUPPORT_FILES_DIRECTORY specify output directory of support files
796
  set_property (TARGET ${target_name} PROPERTY SWIG_SUPPORT_FILES_DIRECTORY "${outputdir}")
797
  # target property SWIG_SUPPORT_FILES lists principal proxy support files
798 799
  if (NOT SWIG_MODULE_${name}_NOPROXY)
    string(TOUPPER "${_SAM_LANGUAGE}" swig_uppercase_language)
800
    set(swig_all_support_files)
801 802 803
    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}$")
804
      list(APPEND swig_all_support_files ${swig_support_files})
805
    endforeach()
806 807 808
    if (swig_all_support_files)
      list(REMOVE_DUPLICATES swig_all_support_files)
    endif()
809
    set_property (TARGET ${target_name} PROPERTY SWIG_SUPPORT_FILES ${swig_all_support_files})
810 811 812 813 814
  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)
815
  set (SWIG_MODULE_${name}_REAL_NAME "${target_name}" PARENT_SCOPE)
816 817 818 819 820 821
  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()
822 823 824 825

#
# Like TARGET_LINK_LIBRARIES but for swig modules
#
826
function(SWIG_LINK_LIBRARIES name)
827 828
  if (UseSWIG_TARGET_NAME_PREFERENCE STREQUAL "STANDARD")
    message(DEPRECATION "SWIG_LINK_LIBRARIES is deprecated. Use TARGET_LINK_LIBRARIES instead.")
829
    target_link_libraries(${name} ${ARGN})
830
  else()
831 832 833 834 835
    if(SWIG_MODULE_${name}_REAL_NAME)
      target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
    else()
      message(SEND_ERROR "Cannot find Swig library \"${name}\".")
    endif()
836
  endif()
837
endfunction()