1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5UseSWIG
6-------
7
8This file provides support for ``SWIG``. It is assumed that :module:`FindSWIG`
9module has already been loaded.
10
11Defines 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    swig_add_library(<name>
18                     [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>]
19                     LANGUAGE <language>
20                     [NO_PROXY]
21                     [OUTPUT_DIR <directory>]
22                     [OUTFILE_DIR <directory>]
23                     SOURCES <file>...
24                    )
25
26  Targets created with the ``swig_add_library`` command have the same
27  capabilities as targets created with the :command:`add_library` command, so
28  those targets can be used with any command expecting a target (e.g.
29  :command:`target_link_libraries`).
30
31  .. note::
32
33    For multi-config generators, this module does not support
34    configuration-specific files generated by ``SWIG``. All build
35    configurations must result in the same generated source file.
36
37  ``TYPE``
38    ``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the
39    :command:`add_library` command. If ``USE_BUILD_SHARED_LIBS`` is specified,
40    the library type will be ``STATIC`` or ``SHARED`` based on whether the
41    current value of the :variable:`BUILD_SHARED_LIBS` variable is ``ON``. If
42    no type is specified, ``MODULE`` will be used.
43
44  ``LANGUAGE``
45    Specify the target language.
46
47  ``NO_PROXY``
48    Prevent the generation of the wrapper layer (swig ``-noproxy`` option).
49
50  ``OUTPUT_DIR``
51    Specify where to write the language specific files (swig ``-outdir``
52    option). If not given, the ``CMAKE_SWIG_OUTDIR`` variable will be used.
53    If neither is specified, the default depends on the value of the
54    ``UseSWIG_MODULE_VERSION`` variable as follows:
55
56    * If ``UseSWIG_MODULE_VERSION`` is 1 or is undefined, output is written to
57      the :variable:`CMAKE_CURRENT_BINARY_DIR` directory.
58    * If ``UseSWIG_MODULE_VERSION`` is 2, a dedicated directory will be used.
59      The path of this directory can be retrieved from the
60      ``SWIG_SUPPORT_FILES_DIRECTORY`` target property.
61
62  ``OUTFILE_DIR``
63    Specify an output directory name where the generated source file will be
64    placed (swig -o option). If not specified, the ``SWIG_OUTFILE_DIR`` variable
65    will be used. If neither is specified, ``OUTPUT_DIR`` or
66    ``CMAKE_SWIG_OUTDIR`` is used instead.
67
68  ``SOURCES``
69    List of sources for the library. Files with extension ``.i`` will be
70    identified as sources for the ``SWIG`` tool. Other files will be handled in
71    the standard way.
72
73.. note::
74
75  If ``UseSWIG_MODULE_VERSION`` is set to 2, it is **strongly** recommended
76  to use a dedicated directory unique to the target when either the
77  ``OUTPUT_DIR`` option or the ``CMAKE_SWIG_OUTDIR`` variable are specified.
78  The output directory contents are erased as part of the target build, so
79  to prevent interference between targets or losing other important files, each
80  target should have its own dedicated output directory.
81
82Source file properties on module files **must** be set before the invocation
83of the ``swig_add_library`` command to specify special behavior of SWIG and
84ensure generated files will receive the required settings.
85
86``CPLUSPLUS``
87  Call SWIG in c++ mode.  For example:
88
89  .. code-block:: cmake
90
91    set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON)
92    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
93
94``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS``
95  Add custom flags to SWIG compiler and have same semantic as properties
96  :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
97  :prop_sf:`COMPILE_OPTIONS`.
98
99``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS``
100  Add custom flags to the C/C++ generated source. They will fill, respectively,
101  properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
102  :prop_sf:`COMPILE_OPTIONS` of generated C/C++ file.
103
104``DEPENDS``
105  Specify additional dependencies to the source file.
106
107``SWIG_MODULE_NAME``
108  Specify the actual import name of the module in the target language.
109  This is required if it cannot be scanned automatically from source
110  or different from the module file basename.  For example:
111
112  .. code-block:: cmake
113
114    set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname)
115
116Target library properties can be set to apply same configuration to all SWIG
117input files.
118
119``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS``
120  These properties will be applied to all SWIG input files and have same
121  semantic as target properties :prop_tgt:`INCLUDE_DIRECTORIES`,
122  :prop_tgt:`COMPILE_DEFINITIONS` and :prop_tgt:`COMPILE_OPTIONS`.
123
124  .. code-block:: cmake
125
126    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
127    set_property(TARGET mymod PROPERTY SWIG_COMPILE_DEFINITIONS MY_DEF1 MY_DEF2)
128    set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb)
129
130``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
131  These properties will populate, respectively, properties
132  :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
133  :prop_sf:`COMPILE_FLAGS` of all generated C/C++ files.
134
135``SWIG_DEPENDS``
136  Add dependencies to all SWIG input files.
137
138The following target properties are output properties and can be used to get
139information about support files generated by ``SWIG`` interface compilation.
140
141``SWIG_SUPPORT_FILES``
142  This output property list of wrapper files generated during SWIG compilation.
143
144  .. code-block:: cmake
145
146    swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
147    get_property(support_files TARGET mymod PROPERTY SWIG_SUPPORT_FILES)
148
149  .. note::
150
151    Only most principal support files are listed. In case some advanced
152    features of ``SWIG`` are used (for example ``%template``), associated
153    support files may not be listed. Prefer to use the
154    ``SWIG_SUPPORT_FILES_DIRECTORY`` property to handle support files.
155
156``SWIG_SUPPORT_FILES_DIRECTORY``
157  This output property specifies the directory where support files will be
158  generated.
159
160Some variables can be set to customize the behavior of ``swig_add_library``
161as well as ``SWIG``:
162
163``UseSWIG_MODULE_VERSION``
164  Specify different behaviors for ``UseSWIG`` module.
165
166  * Set to 1 or undefined: Legacy behavior is applied.
167  * Set to 2: A new strategy is applied regarding support files: the output
168    directory of support files is erased before ``SWIG`` interface compilation.
169
170``CMAKE_SWIG_FLAGS``
171  Add flags to all swig calls.
172
173``CMAKE_SWIG_OUTDIR``
174  Specify where to write the language specific files (swig ``-outdir`` option).
175
176``SWIG_OUTFILE_DIR``
177  Specify an output directory name where the generated source file will be
178  placed.  If not specified, ``CMAKE_SWIG_OUTDIR`` is used.
179
180``SWIG_MODULE_<name>_EXTRA_DEPS``
181  Specify extra dependencies for the generated module for ``<name>``.
182#]=======================================================================]
183
184
185cmake_policy (VERSION 3.8)
186
187set(SWIG_CXX_EXTENSION "cxx")
188set(SWIG_EXTRA_LIBRARIES "")
189
190set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
191set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
192
193##
194## PRIVATE functions
195##
196function (__SWIG_COMPUTE_TIMESTAMP name language infile workingdir __timestamp)
197  get_filename_component(filename "${infile}" NAME_WE)
198  set(${__timestamp}
199    "${workingdir}/${filename}${language}.stamp" PARENT_SCOPE)
200  # get_filename_component(filename "${infile}" ABSOLUTE)
201  # string(UUID uuid NAMESPACE 9735D882-D2F8-4E1D-88C9-A0A4F1F6ECA4
202  #   NAME ${name}-${language}-${filename} TYPE SHA1)
203  # set(${__timestamp} "${workingdir}/${uuid}.stamp" PARENT_SCOPE)
204endfunction()
205
206#
207# For given swig module initialize variables associated with it
208#
209macro(SWIG_MODULE_INITIALIZE name language)
210  string(TOUPPER "${language}" SWIG_MODULE_${name}_LANGUAGE)
211  string(TOLOWER "${language}" SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG)
212
213  set(SWIG_MODULE_${name}_EXTRA_FLAGS)
214  if (NOT DEFINED SWIG_MODULE_${name}_NOPROXY)
215    set (SWIG_MODULE_${name}_NOPROXY FALSE)
216  endif()
217  if ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
218    set (SWIG_MODULE_${name}_NOPROXY TRUE)
219  endif ()
220
221  if (SWIG_MODULE_${name}_NOPROXY AND NOT "-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
222    list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-noproxy")
223  endif()
224  if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "UNKNOWN")
225    message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
226  elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PERL")
227    list(APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
228  endif()
229endmacro()
230
231#
232# For a given language, input file, and output file, determine extra files that
233# will be generated. This is internal swig macro.
234#
235
236function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
237  set(files)
238  get_source_file_property(module_basename
239    "${infile}" SWIG_MODULE_NAME)
240  if(NOT swig_module_basename)
241
242    # try to get module name from "%module foo" syntax
243    if ( EXISTS "${infile}" )
244      file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
245    endif ()
246    if ( module_basename )
247      string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
248
249    else ()
250      # try to get module name from "%module (options=...) foo" syntax
251      if ( EXISTS "${infile}" )
252        file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
253      endif ()
254      if ( module_basename )
255        string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
256
257      else ()
258        # fallback to file basename
259        get_filename_component(module_basename "${infile}" NAME_WE)
260      endif ()
261    endif ()
262
263  endif()
264  foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS})
265    set(extra_file "${generatedpath}/${module_basename}${it}")
266    list(APPEND files "${extra_file}")
267  endforeach()
268    # Treat extra outputs as plain files regardless of language.
269  set_source_files_properties(${files} PROPERTIES LANGUAGE "")
270
271  set (${outfiles} ${files} PARENT_SCOPE)
272endfunction()
273
274#
275# Take swig (*.i) file and add proper custom commands for it
276#
277function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
278  get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
279  get_source_file_property(swig_source_file_cplusplus "${infile}" CPLUSPLUS)
280
281  # If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
282  if(CMAKE_SWIG_OUTDIR)
283    set(outdir ${CMAKE_SWIG_OUTDIR})
284  else()
285    set(outdir ${CMAKE_CURRENT_BINARY_DIR})
286  endif()
287
288  if(SWIG_OUTFILE_DIR)
289    set(outfiledir ${SWIG_OUTFILE_DIR})
290  else()
291    set(outfiledir ${outdir})
292  endif()
293
294  if(SWIG_WORKING_DIR)
295    set (workingdir "${SWIG_WORKING_DIR}")
296  else()
297    set(workingdir "${outdir}")
298  endif()
299
300  set (swig_source_file_flags ${CMAKE_SWIG_FLAGS})
301  # handle various swig compile flags properties
302  get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES)
303  if (include_directories)
304    list (APPEND swig_source_file_flags "$<$<BOOL:${include_directories}>:-I$<JOIN:${include_directories},$<SEMICOLON>-I>>")
305  endif()
306  set (property "$<TARGET_PROPERTY:${name},SWIG_INCLUDE_DIRECTORIES>")
307  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
308
309  set (property "$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>")
310  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
311
312  set (property "$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>")
313	get_source_file_property(use_target_include_dirs "${infile}" USE_TARGET_INCLUDE_DIRECTORIES)
314	if (use_target_include_dirs)
315	list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
316  elseif(use_target_include_dirs STREQUAL "NOTFOUND")
317	# not defined at source level, rely on target level
318	list (APPEND swig_source_file_flags "$<$<AND:$<BOOL:$<TARGET_PROPERTY:${name},SWIG_USE_TARGET_INCLUDE_DIRECTORIES>>,$<BOOL:${property}>>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
319  endif()
320
321  set (property "$<TARGET_PROPERTY:${name},SWIG_COMPILE_DEFINITIONS>")
322  list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:${property},$<SEMICOLON>-D>>")
323  get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS)
324  if (compile_definitions)
325    list (APPEND swig_source_file_flags "$<$<BOOL:${compile_definitions}>:-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>>")
326  endif()
327
328  list (APPEND swig_source_file_flags "$<TARGET_PROPERTY:${name},SWIG_COMPILE_OPTIONS>")
329  get_source_file_property (compile_options "${infile}" COMPILE_OPTIONS)
330  if (compile_options)
331    list (APPEND swig_source_file_flags ${compile_options})
332  endif()
333
334  # legacy support
335  get_source_file_property (swig_flags "${infile}" SWIG_FLAGS)
336  if (swig_flags)
337    list (APPEND swig_source_file_flags ${swig_flags})
338  endif()
339
340  get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
341
342  if (NOT SWIG_MODULE_${name}_NOPROXY)
343    SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
344      swig_extra_generated_files
345      "${outdir}"
346      "${swig_source_file_fullname}")
347  endif()
348  set(swig_generated_file_fullname
349    "${outfiledir}/${swig_source_file_name_we}")
350  # add the language into the name of the file (i.e. TCL_wrap)
351  # this allows for the same .i file to be wrapped into different languages
352  string(APPEND swig_generated_file_fullname
353    "${SWIG_MODULE_${name}_LANGUAGE}_wrap")
354
355  if(swig_source_file_cplusplus)
356    string(APPEND swig_generated_file_fullname
357      ".${SWIG_CXX_EXTENSION}")
358  else()
359    string(APPEND swig_generated_file_fullname
360      ".c")
361  endif()
362
363  get_directory_property (cmake_include_directories INCLUDE_DIRECTORIES)
364  list (REMOVE_DUPLICATES cmake_include_directories)
365  set (swig_include_dirs)
366  if (cmake_include_directories)
367    set (swig_include_dirs "$<$<BOOL:${cmake_include_directories}>:-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>>")
368  endif()
369
370  set(swig_special_flags)
371  # default is c, so add c++ flag if it is c++
372  if(swig_source_file_cplusplus)
373    list (APPEND swig_special_flags "-c++")
374  endif()
375
376  set (swig_extra_flags)
377  if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "CSHARP")
378    if(NOT ("-dllimport" IN_LIST swig_source_file_flags OR "-dllimport" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
379      # This makes sure that the name used in the generated DllImport
380      # matches the library name created by CMake
381      list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "${name}")
382    endif()
383  endif()
384  list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
385
386  # dependencies
387  set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${name},SWIG_DEPENDS>)
388  get_source_file_property(file_depends "${infile}" DEPENDS)
389  if (file_depends)
390    list (APPEND swig_dependencies ${file_depends})
391  endif()
392
393  if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
394    # as part of custom command, start by removing old generated files
395    # to ensure obsolete files do not stay
396    set (swig_cleanup_command COMMAND "${CMAKE_COMMAND}" -E remove_directory "${outdir}")
397  else()
398    unset (swig_cleanup_command)
399  endif()
400
401  # IMPLICIT_DEPENDS below can not handle situations where a dependent file is
402  # removed. We need an extra step with timestamp and custom target, see #16830
403  # As this is needed only for Makefile generator do it conditionally
404  if(CMAKE_GENERATOR MATCHES "Make")
405    __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
406      "${infile}" "${workingdir}" swig_generated_timestamp)
407    set(swig_custom_output "${swig_generated_timestamp}")
408    set(swig_custom_products
409      BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
410    set(swig_timestamp_command
411      COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
412  else()
413    set(swig_custom_output
414      "${swig_generated_file_fullname}" ${swig_extra_generated_files})
415    set(swig_custom_products)
416    set(swig_timestamp_command)
417  endif()
418  add_custom_command(
419    OUTPUT ${swig_custom_output}
420    ${swig_custom_products}
421    ${swig_cleanup_command}
422    # Let's create the ${outdir} at execution time, in case dir contains $(OutDir)
423    COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir}
424    ${swig_timestamp_command}
425    COMMAND "${CMAKE_COMMAND}" -E env "SWIG_LIB=${SWIG_DIR}" "${SWIG_EXECUTABLE}"
426    "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
427    "${swig_source_file_flags}"
428    -outdir "${outdir}"
429    ${swig_special_flags}
430    ${swig_extra_flags}
431    "${swig_include_dirs}"
432    -o "${swig_generated_file_fullname}"
433    "${swig_source_file_fullname}"
434    MAIN_DEPENDENCY "${swig_source_file_fullname}"
435    DEPENDS ${swig_dependencies}
436    IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
437    COMMENT "Swig source ${infile}"
438    COMMAND_EXPAND_LISTS)
439  set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
440    PROPERTIES GENERATED 1)
441
442  ## add all properties for generated file to various properties
443  get_property (include_directories SOURCE "${infile}" PROPERTY GENERATED_INCLUDE_DIRECTORIES)
444  set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY INCLUDE_DIRECTORIES ${include_directories} $<TARGET_PROPERTY:${name},SWIG_GENERATED_INCLUDE_DIRECTORIES>)
445
446  # get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS)
447  # set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_DEFINITIONS> ${compile_definitions})
448
449  # get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS)
450  # set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_OPTIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_OPTIONS> ${compile_options})
451
452  set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
453
454  # legacy support
455  set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
456endfunction()
457
458#
459# Create Swig module
460#
461macro(SWIG_ADD_MODULE name language)
462  message(DEPRECATION "SWIG_ADD_MODULE is deprecated. Use SWIG_ADD_LIBRARY instead.")
463  swig_add_library(${name}
464                   LANGUAGE ${language}
465                   TYPE MODULE
466                   SOURCES ${ARGN})
467endmacro()
468
469
470function(SWIG_ADD_LIBRARY name)
471  set(options NO_PROXY)
472  set(oneValueArgs LANGUAGE
473                   TYPE
474                   OUTPUT_DIR
475                   OUTFILE_DIR)
476  set(multiValueArgs SOURCES)
477  cmake_parse_arguments(_SAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
478
479  if (TARGET ${name})
480    # a target with same name is already defined.
481    # call NOW add_library command to raise the most useful error message
482    add_library(${name})
483    return()
484  endif()
485
486  if (_SAM_UNPARSED_ARGUMENTS)
487    message(FATAL_ERROR "SWIG_ADD_LIBRARY: ${_SAM_UNPARSED_ARGUMENTS}: unexpected arguments")
488  endif()
489
490  if(NOT DEFINED _SAM_LANGUAGE)
491    message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing LANGUAGE argument")
492  endif()
493
494  if(NOT DEFINED _SAM_SOURCES)
495    message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing SOURCES argument")
496  endif()
497
498  if(NOT DEFINED _SAM_TYPE)
499    set(_SAM_TYPE MODULE)
500  elseif(_SAM_TYPE STREQUAL "USE_BUILD_SHARED_LIBS")
501    unset(_SAM_TYPE)
502  endif()
503
504  if (NOT DEFINED UseSWIG_MODULE_VERSION)
505    set (UseSWIG_MODULE_VERSION 1)
506  elseif (NOT UseSWIG_MODULE_VERSION MATCHES "^(1|2)$")
507    message (FATAL_ERROR "UseSWIG_MODULE_VERSION: ${UseSWIG_MODULE_VERSION}: invalid value. 1 or 2 is expected.")
508  endif()
509
510  set (workingdir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${name}.dir")
511  # set special variable to pass extra information to command SWIG_ADD_SOURCE_TO_MODULE
512  # which cannot be changed due to legacy compatibility
513  set (SWIG_WORKING_DIR "${workingdir}")
514
515  set (outputdir "${_SAM_OUTPUT_DIR}")
516  if (NOT _SAM_OUTPUT_DIR)
517    if (CMAKE_SWIG_OUTDIR)
518      set (outputdir "${CMAKE_SWIG_OUTDIR}")
519    else()
520      if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
521        set (outputdir "${workingdir}/${_SAM_LANGUAGE}.files")
522      else()
523        set (outputdir "${CMAKE_CURRENT_BINARY_DIR}")
524      endif()
525    endif()
526  endif()
527
528  set (outfiledir "${_SAM_OUTFILE_DIR}")
529  if(NOT _SAM_OUTFILE_DIR)
530    if (SWIG_OUTFILE_DIR)
531      set (outfiledir "${SWIG_OUTFILE_DIR}")
532    else()
533      if (_SAM_OUTPUT_DIR OR CMAKE_SWIG_OUTDIR)
534        set (outfiledir "${outputdir}")
535    else()
536        set (outfiledir "${workingdir}")
537      endif()
538    endif()
539  endif()
540  # set again, locally, predefined variables to ensure compatibility
541  # with command SWIG_ADD_SOURCE_TO_MODULE
542  set(CMAKE_SWIG_OUTDIR "${outputdir}")
543  set(SWIG_OUTFILE_DIR "${outfiledir}")
544
545  set (SWIG_MODULE_${name}_NOPROXY ${_SAM_NO_PROXY})
546  swig_module_initialize(${name} ${_SAM_LANGUAGE})
547
548  set(swig_dot_i_sources ${_SAM_SOURCES})
549  list(FILTER swig_dot_i_sources INCLUDE REGEX "\\.i$")
550  if (NOT swig_dot_i_sources)
551    message(FATAL_ERROR "SWIG_ADD_LIBRARY: no SWIG interface files specified")
552  endif()
553  set(swig_other_sources ${_SAM_SOURCES})
554  list(REMOVE_ITEM swig_other_sources ${swig_dot_i_sources})
555
556  set(swig_generated_sources)
557  set(swig_generated_timestamps)
558  foreach(swig_it IN LISTS swig_dot_i_sources)
559    SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}")
560    list (APPEND swig_generated_sources "${swig_generated_source}")
561    if(CMAKE_GENERATOR MATCHES "Make")
562      __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}"
563        "${workingdir}" swig_timestamp)
564      list (APPEND swig_generated_timestamps "${swig_timestamp}")
565    endif()
566  endforeach()
567  set_property (DIRECTORY APPEND PROPERTY
568    ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
569  if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
570    set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${outputdir}")
571  endif()
572
573  add_library(${name}
574    ${_SAM_TYPE}
575    ${swig_generated_sources}
576    ${swig_other_sources})
577  if(CMAKE_GENERATOR MATCHES "Make")
578    # see IMPLICIT_DEPENDS above
579    add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
580    add_dependencies(${name} ${name}_swig_compilation)
581  endif()
582  if(_SAM_TYPE STREQUAL "MODULE")
583    set_target_properties(${name} PROPERTIES NO_SONAME ON)
584  endif()
585  string(TOLOWER "${_SAM_LANGUAGE}" swig_lowercase_language)
586  if (swig_lowercase_language STREQUAL "octave")
587    set_target_properties(${name} PROPERTIES PREFIX "")
588    set_target_properties(${name} PROPERTIES SUFFIX ".oct")
589  elseif (swig_lowercase_language STREQUAL "go")
590    set_target_properties(${name} PROPERTIES PREFIX "")
591  elseif (swig_lowercase_language STREQUAL "java")
592    # In java you want:
593    #      System.loadLibrary("LIBRARY");
594    # then JNI will look for a library whose name is platform dependent, namely
595    #   MacOS  : libLIBRARY.jnilib
596    #   Windows: LIBRARY.dll
597    #   Linux  : libLIBRARY.so
598    if (APPLE)
599      set_target_properties (${name} PROPERTIES SUFFIX ".jnilib")
600    endif()
601    if ((WIN32 AND MINGW) OR CYGWIN OR CMAKE_SYSTEM_NAME STREQUAL MSYS)
602      set_target_properties(${name} PROPERTIES PREFIX "")
603    endif()
604  elseif (swig_lowercase_language STREQUAL "lua")
605    if(_SAM_TYPE STREQUAL "MODULE")
606      set_target_properties(${name} PROPERTIES PREFIX "")
607    endif()
608  elseif (swig_lowercase_language STREQUAL "python")
609    if (SWIG_MODULE_${name}_NOPROXY)
610      set_target_properties(${name} PROPERTIES PREFIX "")
611    else()
612      # swig will produce a module.py containing an 'import _modulename' statement,
613      # which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32),
614      # unless the -noproxy flag is used
615      set_target_properties(${name} PROPERTIES PREFIX "_")
616    endif()
617    # Python extension modules on Windows must have the extension ".pyd"
618    # instead of ".dll" as of Python 2.5.  Older python versions do support
619    # this suffix.
620    # http://docs.python.org/whatsnew/ports.html#SECTION0001510000000000000000
621    # <quote>
622    # Windows: .dll is no longer supported as a filename extension for extension modules.
623    # .pyd is now the only filename extension that will be searched for.
624    # </quote>
625    if(WIN32 AND NOT CYGWIN)
626      set_target_properties(${name} PROPERTIES SUFFIX ".pyd")
627    endif()
628  elseif (swig_lowercase_language STREQUAL "r")
629    set_target_properties(${name} PROPERTIES PREFIX "")
630  elseif (swig_lowercase_language STREQUAL "ruby")
631    # In ruby you want:
632    #      require 'LIBRARY'
633    # then ruby will look for a library whose name is platform dependent, namely
634    #   MacOS  : LIBRARY.bundle
635    #   Windows: LIBRARY.dll
636    #   Linux  : LIBRARY.so
637    set_target_properties (${name} PROPERTIES PREFIX "")
638    if (APPLE)
639      set_target_properties (${name} PROPERTIES SUFFIX ".bundle")
640    endif ()
641  elseif (swig_lowercase_language STREQUAL "perl")
642    # assume empty prefix because we expect the module to be dynamically loaded
643    set_target_properties (${name} PROPERTIES PREFIX "")
644    if (APPLE)
645      set_target_properties (${name} PROPERTIES SUFFIX ".dylib")
646    endif ()
647  else()
648    # assume empty prefix because we expect the module to be dynamically loaded
649    set_target_properties (${name} PROPERTIES PREFIX "")
650  endif ()
651
652  # target property SWIG_SUPPORT_FILES_DIRECTORY specify output directory of support files
653  set_property (TARGET ${name} PROPERTY SWIG_SUPPORT_FILES_DIRECTORY "${outputdir}")
654  # target property SWIG_SUPPORT_FILES lists principal proxy support files
655  if (NOT SWIG_MODULE_${name}_NOPROXY)
656    string(TOUPPER "${_SAM_LANGUAGE}" swig_uppercase_language)
657    set(swig_all_support_files)
658    foreach (swig_it IN LISTS SWIG_${swig_uppercase_language}_EXTRA_FILE_EXTENSIONS)
659      set (swig_support_files ${swig_generated_sources})
660      list (FILTER swig_support_files INCLUDE REGEX ".*${swig_it}$")
661      list(APPEND swig_all_support_files ${swig_support_files})
662    endforeach()
663    if (swig_all_support_files)
664      list(REMOVE_DUPLICATES swig_all_support_files)
665    endif()
666    set_property (TARGET ${name} PROPERTY SWIG_SUPPORT_FILES ${swig_all_support_files})
667  endif()
668
669  # to ensure legacy behavior, export some variables
670  set (SWIG_MODULE_${name}_LANGUAGE "${SWIG_MODULE_${name}_LANGUAGE}" PARENT_SCOPE)
671  set (SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" PARENT_SCOPE)
672  set (SWIG_MODULE_${name}_REAL_NAME "${name}" PARENT_SCOPE)
673  set (SWIG_MODULE_${name}_NOPROXY "${SWIG_MODULE_${name}_NOPROXY}" PARENT_SCOPE)
674  set (SWIG_MODULE_${name}_EXTRA_FLAGS "${SWIG_MODULE_${name}_EXTRA_FLAGS}" PARENT_SCOPE)
675  # the last one is a bit crazy but it is documented, so...
676  # NOTA: works as expected if only ONE input file is specified
677  set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
678endfunction()
679
680#
681# Like TARGET_LINK_LIBRARIES but for swig modules
682#
683function(SWIG_LINK_LIBRARIES name)
684  message(DEPRECATION "SWIG_LINK_LIBRARIES is deprecated. Use TARGET_LINK_LIBRARIES instead.")
685  if(SWIG_MODULE_${name}_REAL_NAME)
686    target_link_libraries(${name} ${ARGN})
687  else()
688    message(SEND_ERROR "Cannot find Swig library \"${name}\".")
689  endif()
690endfunction()
691