Skip to content

Commit c2a138a

Browse files
authored
Merge pull request #20 from swig-fortran/useswig-new
Backport upcoming FindSWIG/UseSWIG
2 parents 0d1b919 + 85cf9c6 commit c2a138a

29 files changed

+816
-583
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/build/
22
/build-*/
3+
/install/
4+
/install-*/
35
# Prerequisites
46
*.d
57

CMakeLists.txt

+18-14
Original file line numberDiff line numberDiff line change
@@ -75,26 +75,30 @@ endif()
7575
#---------------------------------------------------------------------------#
7676

7777
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
78+
if (CMAKE_VERSION VERSION_LESS 3.18)
79+
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/backport-cmake-318")
80+
endif()
7881

7982
if (FLIBCPP_USE_SWIG)
80-
find_package(SWIG)
81-
endif()
83+
find_package(SWIG COMPONENTS fortran REQUIRED)
8284

83-
if (FLIBCPP_USE_SWIG AND SWIG_FOUND)
84-
# SWIG is requested and available; make sure it's the Fortran fork.
85-
include(CheckSWIGFortran)
86-
if (CMAKE_VERSION VERSION_LESS 3.99)
87-
# TODO: This is until Fortran support gets added to the upstream cmake script
88-
include(UseSWIGFortran)
89-
else()
85+
if (CMAKE_VERSION VERSION_LESS 3.12)
86+
message(FATAL_ERROR "CMake 3.12 or higher is required to regenerate the "
87+
"Fortran bindings using SWIG. Set FLIBCPP_USE_SWIG to OFF "
88+
"and reconfigure.")
89+
endif()
90+
91+
if (CMAKE_VERSION GREATER_EQUAL 3.13)
9092
cmake_policy(SET CMP0078 "NEW")
93+
else()
94+
set(FLIBCPP_CMP0078 "NEW")
95+
endif()
96+
if (CMAKE_VERSION GREATER_EQUAL 3.14)
9197
cmake_policy(SET CMP0086 "NEW")
92-
include(UseSWIG)
98+
else()
99+
set(FLIBCPP_CMP0086 "NEW")
93100
endif()
94-
set(FLIBCPP_SWIG_EXECUTABLE "${SWIG_EXECUTABLE}")
95-
set(FLIBCPP_SWIG_DIR "${SWIG_DIR}")
96-
else()
97-
set(FLIBCPP_USE_SWIG FALSE)
101+
include(UseSWIG)
98102
endif()
99103

100104
# Enable testing based on BUILD_TESTING flag

cmake/CheckSWIGFortran.cmake

-23
This file was deleted.
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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:
5+
FindSWIG
6+
--------
7+
8+
Find the Simplified Wrapper and Interface Generator (SWIG_) executable.
9+
10+
11+
This module finds an installed SWIG and determines its version. If a
12+
``COMPONENTS`` or ``OPTIONAL_COMPONENTS`` argument is given to ``find_package``,
13+
it will also determine supported target languages. The module sents the
14+
following variables:
15+
16+
``SWIG_FOUND``
17+
Whether SWIG and any required components were found on the system.
18+
``SWIG_EXECUTABLE``
19+
Path to the SWIG executable.
20+
``SWIG_DIR``
21+
Path to the installed SWIG ``Lib`` directory (result of ``swig -swiglib``).
22+
``SWIG_VERSION``
23+
SWIG executable version (result of ``swig -version``).
24+
``SWIG_<lang>_FOUND``
25+
If ``COMPONENTS`` or ``OPTIONAL_COMPONENTS`` are requested, each available
26+
target language ``<lang>`` (lowercase) will be set to TRUE.
27+
28+
Any ``COMPONENTS`` given to ``find_package`` should be the names of supported
29+
target languages as provided to the LANGUAGE argument of ``swig_add_library``,
30+
such as ``python`` or ``perl5``. Language names *must* be lowercase.
31+
32+
All information is collected from the ``SWIG_EXECUTABLE``, so the version
33+
to be found can be changed from the command line by means of setting
34+
``SWIG_EXECUTABLE``.
35+
36+
Example usage requiring SWIG 4.0 or higher and Python language support, with
37+
optional Fortran support:
38+
39+
.. code-block:: cmake
40+
41+
find_package(SWIG 4.0 COMPONENTS python OPTIONAL_COMPONENTS fortran)
42+
if(SWIG_FOUND)
43+
message("SWIG found: ${SWIG_EXECUTABLE}")
44+
if(NOT SWIG_fortran_FOUND)
45+
message(WARNING "SWIG Fortran bindings cannot be generated")
46+
endif()
47+
endif()
48+
49+
.. _`SWIG`: http://swig.org
50+
51+
#]=======================================================================]
52+
53+
find_program(SWIG_EXECUTABLE NAMES swig4.0 swig3.0 swig2.0 swig)
54+
55+
if(SWIG_EXECUTABLE)
56+
execute_process(COMMAND ${SWIG_EXECUTABLE} -swiglib
57+
OUTPUT_VARIABLE SWIG_swiglib_output
58+
ERROR_VARIABLE SWIG_swiglib_error
59+
RESULT_VARIABLE SWIG_swiglib_result)
60+
61+
if(SWIG_swiglib_result)
62+
if(SWIG_FIND_REQUIRED)
63+
message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}")
64+
else()
65+
message(STATUS "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}")
66+
endif()
67+
else()
68+
string(REGEX REPLACE "[\n\r]+" ";" SWIG_swiglib_output ${SWIG_swiglib_output})
69+
find_path(SWIG_DIR swig.swg PATHS ${SWIG_swiglib_output} NO_CMAKE_FIND_ROOT_PATH)
70+
if(SWIG_DIR)
71+
set(SWIG_USE_FILE ${CMAKE_CURRENT_LIST_DIR}/UseSWIG.cmake)
72+
execute_process(COMMAND ${SWIG_EXECUTABLE} -version
73+
OUTPUT_VARIABLE SWIG_version_output
74+
ERROR_VARIABLE SWIG_version_output
75+
RESULT_VARIABLE SWIG_version_result)
76+
if(SWIG_version_result)
77+
message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -version\" failed with output:\n${SWIG_version_output}")
78+
else()
79+
string(REGEX REPLACE ".*SWIG Version[^0-9.]*\([0-9.]+\).*" "\\1"
80+
SWIG_version_output "${SWIG_version_output}")
81+
set(SWIG_VERSION ${SWIG_version_output} CACHE STRING "Swig version" FORCE)
82+
endif()
83+
endif()
84+
endif()
85+
86+
if(SWIG_FIND_COMPONENTS)
87+
execute_process(COMMAND ${SWIG_EXECUTABLE} -help
88+
OUTPUT_VARIABLE SWIG_swighelp_output
89+
ERROR_VARIABLE SWIG_swighelp_error
90+
RESULT_VARIABLE SWIG_swighelp_result)
91+
if(SWIG_swighelp_result)
92+
message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -help\" failed with output:\n${SWIG_swiglib_error}")
93+
else()
94+
string(REPLACE "\n" ";" SWIG_swighelp_output "${SWIG_swighelp_output}")
95+
foreach(SWIG_line IN LISTS SWIG_swighelp_output)
96+
if(SWIG_line MATCHES "-([A-Za-z0-9_]+) +- *Generate.*wrappers")
97+
set(SWIG_${CMAKE_MATCH_1}_FOUND TRUE)
98+
endif()
99+
endforeach()
100+
endif()
101+
endif()
102+
endif()
103+
104+
include(FindPackageHandleStandardArgs)
105+
find_package_handle_standard_args(
106+
SWIG HANDLE_COMPONENTS
107+
REQUIRED_VARS SWIG_EXECUTABLE SWIG_DIR
108+
VERSION_VAR SWIG_VERSION)
109+
110+
mark_as_advanced(SWIG_DIR SWIG_VERSION SWIG_EXECUTABLE)

cmake/UseSWIGFortran.cmake cmake/backport-cmake-318/UseSWIG.cmake

+68-10
Original file line numberDiff line numberDiff line change
@@ -234,15 +234,31 @@ as well as ``SWIG``:
234234
set(SWIG_SOURCE_FILE_EXTENSIONS ".i" ".swg")
235235
#]=======================================================================]
236236

237+
if (CMAKE_VERSION GREATER_EQUAL 3.13)
238+
cmake_policy(GET CMP0078 target_name_policy)
239+
endif()
240+
if (CMAKE_VERSION GREATER_EQUAL 3.14)
241+
cmake_policy(GET CMP0086 module_name_policy)
242+
endif()
243+
237244
cmake_policy (VERSION 3.12)
245+
if (target_name_policy)
246+
# respect user choice regarding CMP0078 policy
247+
cmake_policy(SET CMP0078 ${target_name_policy})
248+
endif()
249+
if (module_name_policy)
250+
# respect user choice regarding CMP0086 policy
251+
cmake_policy(SET CMP0086 ${module_name_policy})
252+
endif()
253+
unset(target_name_policy)
254+
unset(module_name_policy)
238255

239256
set(SWIG_CXX_EXTENSION "cxx")
240257
set(SWIG_EXTRA_LIBRARIES "")
241258

242259
set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
243260
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
244261
set(SWIG_CSHARP_EXTRA_FILE_EXTENSIONS ".cs" "PINVOKE.cs")
245-
set(SWIG_FORTRAN_EXTRA_FILE_EXTENSIONS ".f90")
246262

247263
set(SWIG_MANAGE_SUPPORT_FILES_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/UseSWIG/ManageSupportFiles.cmake")
248264

@@ -322,15 +338,30 @@ function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
322338
set(extra_file "${generatedpath}/${module_basename}${it}")
323339
if (extra_file MATCHES "\\.cs$" AND CMAKE_CSharp_COMPILER_LOADED)
324340
set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "CSharp")
325-
elseif (extra_file MATCHES "\\.f90$" AND CMAKE_Fortran_COMPILER_LOADED)
326-
set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "Fortran")
327341
else()
328342
# Treat extra outputs as plain files regardless of language.
329343
set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "")
330344
endif()
331345
list(APPEND files "${extra_file}")
332346
endforeach()
333347

348+
if (language STREQUAL "FORTRAN" AND CMAKE_Fortran_COMPILER_LOADED)
349+
# Process possible user-supplied extension in flags (obtained via parent
350+
# scope variable) to determine the source file name.
351+
list(FIND SWIG_COMPILATION_FLAGS "-fext" fext_idx)
352+
if (fext_idx EQUAL -1)
353+
# Default Fortran generated extension
354+
set(fext "f90")
355+
else()
356+
# Get extension from user-provided flag
357+
math(EXPR fext_idx "${fext_idx} + 1")
358+
list(GET SWIG_COMPILATION_FLAGS "${fext_idx}" fext)
359+
endif()
360+
set(extra_file "${generatedpath}/${module_basename}.${fext}")
361+
set_source_files_properties("${extra_file}" PROPERTIES LANGUAGE "Fortran")
362+
list(APPEND files "${extra_file}")
363+
endif()
364+
334365
set (${outfiles} ${files} PARENT_SCOPE)
335366
endfunction()
336367

@@ -405,6 +436,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
405436
get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
406437

407438
if (NOT SWIG_MODULE_${name}_NOPROXY)
439+
set(SWIG_COMPILATION_FLAGS ${swig_source_file_flags})
408440
SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
409441
swig_extra_generated_files
410442
"${outdir}"
@@ -438,20 +470,39 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
438470
list (APPEND swig_special_flags "-c++")
439471
endif()
440472

441-
set(module_name_policy "NEW")
473+
474+
if (CMAKE_VERSION GREATER_EQUAL 3.14)
475+
cmake_policy(GET CMP0086 module_name_policy)
476+
elseif(FLIBCPP_CMP0086)
477+
set(module_name_policy ${FLIBCPP_CMP0086})
478+
else()
479+
set(module_name_policy OLD)
480+
endif()
442481
if (module_name_policy STREQUAL "NEW")
443482
get_source_file_property(module_name "${infile}" SWIG_MODULE_NAME)
444483
if (module_name)
445484
list (APPEND swig_special_flags "-module" "${module_name}")
446485
endif()
486+
else()
487+
if (NOT module_name_policy)
488+
cmake_policy(GET_WARNING CMP0086 _cmp0086_warning)
489+
message(AUTHOR_WARNING "${_cmp0086_warning}\n")
490+
endif()
447491
endif()
448492

449493
set (swig_extra_flags)
450494
if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "CSHARP")
451495
if(NOT ("-dllimport" IN_LIST swig_source_file_flags OR "-dllimport" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
452496
# This makes sure that the name used in the generated DllImport
453497
# matches the library name created by CMake
454-
list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "${name}")
498+
list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "$<TARGET_FILE_PREFIX:${target_name}>$<TARGET_FILE_BASE_NAME:${target_name}>")
499+
endif()
500+
endif()
501+
if (SWIG_MODULE_${name}_LANGUAGE STREQUAL "PYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
502+
if(NOT ("-interface" IN_LIST swig_source_file_flags OR "-interface" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
503+
# This makes sure that the name used in the proxy code
504+
# matches the library name created by CMake
505+
list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-interface" "$<TARGET_FILE_PREFIX:${target_name}>$<TARGET_FILE_BASE_NAME:${target_name}>")
455506
endif()
456507
endif()
457508
list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
@@ -576,11 +627,18 @@ function(SWIG_ADD_LIBRARY name)
576627
unset(_SAM_TYPE)
577628
endif()
578629

579-
set(target_name_policy "NEW")
630+
if (CMAKE_VERSION GREATER_EQUAL 3.13)
631+
cmake_policy(GET CMP0078 target_name_policy)
632+
elseif(FLIBCPP_CMP0078)
633+
set(target_name_policy ${FLIBCPP_CMP0078})
634+
else()
635+
set(target_name_policy OLD)
636+
endif()
580637
if (target_name_policy STREQUAL "NEW")
581638
set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
582639
else()
583640
if (NOT target_name_policy)
641+
cmake_policy(GET_WARNING CMP0078 _cmp0078_warning)
584642
message(AUTHOR_WARNING "${_cmp0078_warning}\n")
585643
endif()
586644
if (NOT DEFINED UseSWIG_TARGET_NAME_PREFERENCE)
@@ -685,9 +743,9 @@ function(SWIG_ADD_LIBRARY name)
685743
endif()
686744
endforeach()
687745
set_property (DIRECTORY APPEND PROPERTY
688-
ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
746+
ADDITIONAL_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
689747
if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
690-
set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${outputdir}")
748+
set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${outputdir}")
691749
endif()
692750

693751
add_library(${target_name}
@@ -706,8 +764,6 @@ function(SWIG_ADD_LIBRARY name)
706764
if (swig_lowercase_language STREQUAL "octave")
707765
set_target_properties(${target_name} PROPERTIES PREFIX "")
708766
set_target_properties(${target_name} PROPERTIES SUFFIX ".oct")
709-
elseif (swig_lowercase_language STREQUAL "fortran")
710-
# XXX
711767
elseif (swig_lowercase_language STREQUAL "go")
712768
set_target_properties(${target_name} PROPERTIES PREFIX "")
713769
elseif (swig_lowercase_language STREQUAL "java")
@@ -766,6 +822,8 @@ function(SWIG_ADD_LIBRARY name)
766822
if (APPLE)
767823
set_target_properties (${target_name} PROPERTIES SUFFIX ".dylib")
768824
endif ()
825+
elseif (swig_lowercase_language STREQUAL "fortran")
826+
# Do *not* override the target's library prefix
769827
else()
770828
# assume empty prefix because we expect the module to be dynamically loaded
771829
set_target_properties (${target_name} PROPERTIES PREFIX "")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
5+
if (ACTION STREQUAL "CLEAN")
6+
# Collect current list of generated files
7+
file (GLOB files LIST_DIRECTORIES FALSE RELATIVE "${SUPPORT_FILES_WORKING_DIRECTORY}" "${SUPPORT_FILES_WORKING_DIRECTORY}/*")
8+
9+
if (files)
10+
# clean-up the output directory
11+
## compute full paths
12+
list (TRANSFORM files PREPEND "${SUPPORT_FILES_OUTPUT_DIRECTORY}/")
13+
## remove generated files from the output directory
14+
file (REMOVE ${files})
15+
16+
# clean-up working directory
17+
file (REMOVE_RECURSE "${SUPPORT_FILES_WORKING_DIRECTORY}")
18+
endif()
19+
20+
file (MAKE_DIRECTORY "${SUPPORT_FILES_WORKING_DIRECTORY}")
21+
endif()
22+
23+
if (ACTION STREQUAL "COPY")
24+
# Collect current list of generated files
25+
file (GLOB files LIST_DIRECTORIES FALSE "${SUPPORT_FILES_WORKING_DIRECTORY}/*")
26+
27+
if (files)
28+
# copy files to the output directory
29+
file (COPY ${files} DESTINATION "${SUPPORT_FILES_OUTPUT_DIRECTORY}")
30+
endif()
31+
endif()

0 commit comments

Comments
 (0)