From d6048bd153979c268a2943b26fd71be7c5f11251 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 29 Jan 2018 09:46:51 +0100 Subject: UseSWIG: Re-work test framework --- Modules/UseSWIG.cmake | 6 ++ Tests/RunCMake/CMakeLists.txt | 5 ++ Tests/RunCMake/UseSWIG/CMakeLists.txt | 3 + Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake | 57 +++++++++++++++++++ Tests/RunCMake/UseSWIG/LegacyPerl.cmake | 18 ++++++ Tests/RunCMake/UseSWIG/LegacyPython.cmake | 9 +++ Tests/RunCMake/UseSWIG/RunCMakeTest.cmake | 13 +++++ Tests/RunCMake/UseSWIG/example.cxx | 33 +++++++++++ Tests/RunCMake/UseSWIG/example.h | 37 +++++++++++++ Tests/RunCMake/UseSWIG/example.i | 9 +++ Tests/RunCMake/UseSWIG/runme.php4 | 58 ++++++++++++++++++++ Tests/RunCMake/UseSWIG/runme.pike | 53 ++++++++++++++++++ Tests/RunCMake/UseSWIG/runme.pl | 56 +++++++++++++++++++ Tests/RunCMake/UseSWIG/runme.py | 52 ++++++++++++++++++ Tests/RunCMake/UseSWIG/runme.rb | 49 +++++++++++++++++ Tests/RunCMake/UseSWIG/runme.tcl | 49 +++++++++++++++++ Tests/RunCMake/UseSWIG/runme2.tcl | 69 +++++++++++++++++++++++ Tests/SwigTest/CMakeLists.txt | 59 -------------------- Tests/SwigTest/example.cxx | 33 ----------- Tests/SwigTest/example.h | 37 ------------- Tests/SwigTest/example.i | 10 ---- Tests/SwigTest/runme.php4 | 58 -------------------- Tests/SwigTest/runme.pike | 53 ------------------ Tests/SwigTest/runme.pl | 57 ------------------- Tests/SwigTest/runme.py | 51 ----------------- Tests/SwigTest/runme.rb | 49 ----------------- Tests/SwigTest/runme.tcl | 50 ----------------- Tests/SwigTest/runme2.tcl | 70 ------------------------ 28 files changed, 576 insertions(+), 527 deletions(-) create mode 100644 Tests/RunCMake/UseSWIG/CMakeLists.txt create mode 100644 Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake create mode 100644 Tests/RunCMake/UseSWIG/LegacyPerl.cmake create mode 100644 Tests/RunCMake/UseSWIG/LegacyPython.cmake create mode 100644 Tests/RunCMake/UseSWIG/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/UseSWIG/example.cxx create mode 100644 Tests/RunCMake/UseSWIG/example.h create mode 100644 Tests/RunCMake/UseSWIG/example.i create mode 100644 Tests/RunCMake/UseSWIG/runme.php4 create mode 100644 Tests/RunCMake/UseSWIG/runme.pike create mode 100644 Tests/RunCMake/UseSWIG/runme.pl create mode 100644 Tests/RunCMake/UseSWIG/runme.py create mode 100644 Tests/RunCMake/UseSWIG/runme.rb create mode 100644 Tests/RunCMake/UseSWIG/runme.tcl create mode 100644 Tests/RunCMake/UseSWIG/runme2.tcl delete mode 100644 Tests/SwigTest/CMakeLists.txt delete mode 100644 Tests/SwigTest/example.cxx delete mode 100644 Tests/SwigTest/example.h delete mode 100644 Tests/SwigTest/example.i delete mode 100644 Tests/SwigTest/runme.php4 delete mode 100755 Tests/SwigTest/runme.pike delete mode 100644 Tests/SwigTest/runme.pl delete mode 100644 Tests/SwigTest/runme.py delete mode 100644 Tests/SwigTest/runme.rb delete mode 100644 Tests/SwigTest/runme.tcl delete mode 100644 Tests/SwigTest/runme2.tcl diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 959893f..cc30669 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -378,6 +378,12 @@ macro(SWIG_ADD_LIBRARY name) if (APPLE) set_target_properties (${SWIG_MODULE_${name}_REAL_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 (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") + if (APPLE) + set_target_properties (${SWIG_MODULE_${name}_REAL_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 "") 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 @@ if(CMake_TEST_FindMatlab) 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/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/RunCMake/UseSWIG/LegacyConfiguration.cmake b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake new file mode 100644 index 0000000..3f400bf --- /dev/null +++ b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake @@ -0,0 +1,57 @@ + +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +unset(SWIG_LANG_TYPE) +if(${language} MATCHES python) + 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(Perl REQUIRED) + find_package(PerlLibs REQUIRED) + include_directories(${PERL_INCLUDE_PATH}) + 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 REQUIRED) + include_directories(${TCL_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY}) +endif() +if(${language} MATCHES ruby) + find_package(Ruby REQUIRED) + include_directories(${RUBY_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY}) +endif() +if(${language} MATCHES php4) + find_package(PHP4 REQUIRED) + include_directories(${PHP4_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY}) +endif() +if(${language} MATCHES pike) + find_package(Pike REQUIRED) + include_directories(${PIKE_INCLUDE_PATH}) + set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY}) +endif() +if(${language} MATCHES lua) + find_package(Lua REQUIRED) + include_directories(${LUA_INCLUDE_DIR}) + set(SWIG_LANG_TYPE TYPE SHARED) + set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES}) +endif() + +unset(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") +SWIG_ADD_LIBRARY(example + LANGUAGE "${language}" + ${SWIG_LANG_TYPE} + SOURCES example.i example.cxx) +SWIG_LINK_LIBRARIES(example ${SWIG_LANG_LIBRARIES}) diff --git a/Tests/RunCMake/UseSWIG/LegacyPerl.cmake b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake new file mode 100644 index 0000000..cfa8c53 --- /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 ";" "$" perl_path "${perl_path}") + set (perl_env "PATH=$$${perl_path}") +else() + set (perl_env "LD_LIBRARY_PATH=$") +endif() + +add_custom_target (RunPerl + COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" + "${PERL_EXECUTABLE}" "-I$" + "${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..f3d9e2b --- /dev/null +++ b/Tests/RunCMake/UseSWIG/LegacyPython.cmake @@ -0,0 +1,9 @@ + +set(language "python") + +include (LegacyConfiguration.cmake) + +add_custom_target (RunPython + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$" + "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py" + DEPENDS ${SWIG_MODULE_example_REAL_NAME}) diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake new file mode 100644 index 0000000..cbeba66 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake @@ -0,0 +1,13 @@ +include(RunCMake) + +function(run_SWIG group language) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${group}${language}-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${group}${language}) + run_cmake_command(${group}${language}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --target Run${language}) +endfunction() + +run_SWIG(Legacy Python) +run_SWIG(Legacy Perl) diff --git a/Tests/RunCMake/UseSWIG/example.cxx b/Tests/RunCMake/UseSWIG/example.cxx new file mode 100644 index 0000000..961d6dd --- /dev/null +++ b/Tests/RunCMake/UseSWIG/example.cxx @@ -0,0 +1,33 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) +{ + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) +{ + return M_PI * radius * radius; +} + +double Circle::perimeter(void) +{ + return 2 * M_PI * radius; +} + +double Square::area(void) +{ + return width * width; +} + +double Square::perimeter(void) +{ + return 4 * width; +} diff --git a/Tests/RunCMake/UseSWIG/example.h b/Tests/RunCMake/UseSWIG/example.h new file mode 100644 index 0000000..366deb0 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/example.h @@ -0,0 +1,37 @@ +/* File : example.h */ + +class Shape +{ +public: + Shape() { nshapes++; } + virtual ~Shape() { nshapes--; }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape +{ +private: + double radius; + +public: + Circle(double r) + : radius(r){}; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape +{ +private: + double width; + +public: + Square(double w) + : width(w){}; + virtual double area(void); + virtual double perimeter(void); +}; diff --git a/Tests/RunCMake/UseSWIG/example.i b/Tests/RunCMake/UseSWIG/example.i new file mode 100644 index 0000000..fbdf724 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/example.i @@ -0,0 +1,9 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" diff --git a/Tests/RunCMake/UseSWIG/runme.php4 b/Tests/RunCMake/UseSWIG/runme.php4 new file mode 100644 index 0000000..653ced2 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme.php4 @@ -0,0 +1,58 @@ + diff --git a/Tests/RunCMake/UseSWIG/runme.pike b/Tests/RunCMake/UseSWIG/runme.pike new file mode 100644 index 0000000..ec28dd7 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme.pike @@ -0,0 +1,53 @@ +import .example; + +int main() +{ + // ----- Object creation ----- + + write("Creating some objects:\n"); + Circle c = Circle(10.0); + write(" Created circle.\n"); + Square s = Square(10.0); + write(" Created square.\n"); + + // ----- Access a static member ----- + + write("\nA total of " + Shape_nshapes_get() + " shapes were created\n"); + + // ----- Member data access ----- + + // Set the location of the object + + c->x_set(20.0); + c->y_set(30.0); + + s->x_set(-10.0); + s->y_set(5.0); + + write("\nHere is their current position:\n"); + write(" Circle = (%f, %f)\n", c->x_get(), c->y_get()); + write(" Square = (%f, %f)\n", s->x_get(), s->y_get()); + + // ----- Call some methods ----- + + write("\nHere are some properties of the shapes:\n"); + write(" The circle:\n"); + write(" area = %f.\n", c->area()); + write(" perimeter = %f.\n", c->perimeter()); + write(" The square:\n"); + write(" area = %f.\n", s->area()); + write(" perimeter = %f.\n", s->perimeter()); + + write("\nGuess I'll clean up now\n"); + + /* See if we can force 's' to be garbage-collected */ + s = 0; + + /* Now we should be down to only 1 shape */ + write("%d shapes remain\n", Shape_nshapes_get()); + + /* Done */ + write("Goodbye\n"); + + return 0; +} diff --git a/Tests/RunCMake/UseSWIG/runme.pl b/Tests/RunCMake/UseSWIG/runme.pl new file mode 100644 index 0000000..965e063 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme.pl @@ -0,0 +1,56 @@ +# file: runme.pl + +# This file illustrates the low-level C++ interface +# created by SWIG. In this case, all of our C++ classes +# get converted into function calls. + +use example; + +# ----- Object creation ----- + +print "Creating some objects:\n"; +$c = examplec::new_Circle(10); +print " Created circle $c\n"; +$s = examplec::new_Square(10); +print " Created square $s\n"; + +# ----- Access a static member ----- + +print "\nA total of $examplec::Shape_nshapes shapes were created\n"; + +# ----- Member data access ----- + +# Set the location of the object. +# Note: methods in the base class Shape are used since +# x and y are defined there. + +examplec::Shape_x_set($c, 20); +examplec::Shape_y_set($c, 30); +examplec::Shape_x_set($s,-10); +examplec::Shape_y_set($s,5); + +print "\nHere is their current position:\n"; +print " Circle = (",examplec::Shape_x_get($c),",", examplec::Shape_y_get($c),")\n"; +print " Square = (",examplec::Shape_x_get($s),",", examplec::Shape_y_get($s),")\n"; + +# ----- Call some methods ----- + +print "\nHere are some properties of the shapes:\n"; +foreach $o ($c,$s) { + print " $o\n"; + print " area = ", examplec::Shape_area($o), "\n"; + print " perimeter = ", examplec::Shape_perimeter($o), "\n"; + } +# Notice how the Shape_area() and Shape_perimeter() functions really +# invoke the appropriate virtual method on each object. + +# ----- Delete everything ----- + +print "\nGuess I'll clean up now\n"; + +# Note: this invokes the virtual destructor +examplec::delete_Shape($c); +examplec::delete_Shape($s); + +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/RunCMake/UseSWIG/runme.rb b/Tests/RunCMake/UseSWIG/runme.rb new file mode 100644 index 0000000..de73bcd --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme.rb @@ -0,0 +1,49 @@ +# file: runme.rb + +# This file illustrates the C++ interface created by SWIG. +# All of our C++ classes get converted into Ruby classes. + +require 'example' + +# ----- Object creation ----- + +print "Creating some objects:\n" +c = Example::Circle.new(10) +print " Created circle #{c}\n" +s = Example::Square.new(10) +print " Created square #{s}\n" + +# ----- Access a static member ----- + +print "\nA total of #{Example::Shape.nshapes} shapes were created\n" + +# ----- Member data access ----- + +# Set the location of the object + +# Notice how we can do this using functions specific to +# the 'Circle' class. +c.x = 20 +c.y = 30 + +# Now use the same functions in the base class +s.x = -10 +s.y = 5 + +print "\nHere is their current position:\n" +print " Circle = (", c.x, ",", c.y, ")\n" +print " Square = (", s.x, ",", s.y, ")\n" + +# ----- Call some methods ----- + +print "\nHere are some properties of the shapes:\n" +for o in [c, s] + print " #{o}\n" + print " area = ", o.area, "\n" + print " perimeter = ", o.perimeter, "\n" +end +# Notice how the Shape#area() and Shape#perimeter() functions really +# invoke the appropriate virtual method on each object. + +print "\n", Example::Shape.nshapes," shapes remain\n" +print "Goodbye\n" diff --git a/Tests/RunCMake/UseSWIG/runme.tcl b/Tests/RunCMake/UseSWIG/runme.tcl new file mode 100644 index 0000000..6055cf6 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme.tcl @@ -0,0 +1,49 @@ +# file: runme.tcl + +# This file illustrates the high level C++ interface. +# In this case C++ classes work kind of like Tk widgets + +catch { load ./example[info sharedlibextension] example} + +# ----- Object creation ----- + +puts "Creating some objects:" +Circle c 10 +puts " Created circle [c cget -this]" +Square s 10 +puts " Created square [s cget -this]" + +# ----- Access a static member ----- + +puts "\nA total of $Shape_nshapes shapes were created" + +# ----- Member data access ----- + +# Set the location of the object + +c configure -x 20 -y 30 +s configure -x -10 -y 5 + +puts "\nHere is their current position:" +puts " Circle = ([c cget -x], [c cget -y])" +puts " Square = ([s cget -x], [s cget -y])" + +# ----- Call some methods ----- + +puts "\nHere are some properties of the shapes:" +foreach o "c s" { + puts " [$o cget -this]" + puts " area = [$o area]" + puts " perimeter = [$o perimeter]" +} + +# ----- Delete everything ----- + +puts "\nGuess I'll clean up now" + +# Note: this invokes the virtual destructor +rename c "" +rename s "" + +puts "$Shape_nshapes shapes remain" +puts "Goodbye" diff --git a/Tests/RunCMake/UseSWIG/runme2.tcl b/Tests/RunCMake/UseSWIG/runme2.tcl new file mode 100644 index 0000000..d0b5c21 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/runme2.tcl @@ -0,0 +1,69 @@ +# file: runme2.tcl + +# This file illustrates the low-level C++ interface +# created by SWIG. In this case, all of our C++ classes +# get converted into function calls. + +catch { load ./example[info sharedlibextension] example} + +# ----- Object creation ----- + +puts "Creating some objects:" +set c [new_Circle 10] +puts " Created circle $c" +set s [new_Square 10] +puts " Created square $s" + +# ----- Access a static member ----- + +puts "\nA total of $Shape_nshapes shapes were created" + +# ----- Member data access ----- + +# Set the location of the object +# Note: the base class must be used since that's where x and y +# were declared. + +Shape_x_set $c 20 +Shape_y_set $c 30 +Shape_x_set $s -10 +Shape_y_set $s 5 + +puts "\nHere is their current position:" +puts " Circle = ([Shape_x_get $c], [Shape_y_get $c])" +puts " Square = ([Shape_x_get $s], [Shape_y_get $s])" + +# ----- Call some methods ----- + +puts "\nHere are some properties of the shapes:" +foreach o "$c $s" { + puts " $o" + puts " area = [Shape_area $o]" + puts " perimeter = [Shape_perimeter $o]" +} +# Notice how the Shape_area() and Shape_perimeter() functions really +# invoke the appropriate virtual method on each object. + +# ----- Try to cause a type error ----- + +puts "\nI'm going to try and break the type system" + +if { [catch { + # Bad script! + Square_area $c # Try to invoke Square method on a Circle + puts " Bad bad SWIG!" + +}]} { + puts " Well, it didn't work. Good SWIG." +} + +# ----- Delete everything ----- + +puts "\nGuess I'll clean up now" + +# Note: this invokes the virtual destructor +delete_Shape $c +delete_Shape $s + +puts "$Shape_nshapes shapes remain" +puts "Goodbye" diff --git a/Tests/SwigTest/CMakeLists.txt b/Tests/SwigTest/CMakeLists.txt deleted file mode 100644 index 65f5c93..0000000 --- a/Tests/SwigTest/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -set(language "python") - -cmake_minimum_required (VERSION 2.6) - -project(example_${language}_class) - -find_package(SWIG REQUIRED) -include(${SWIG_USE_FILE}) - -unset(SWIG_LANG_TYPE) -if(${language} MATCHES python) - find_package(PythonLibs) - include_directories(${PYTHON_INCLUDE_PATH}) - set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES}) -endif() -if(${language} MATCHES perl) - find_package(PerlLibs) - include_directories(${PERL_INCLUDE_PATH}) - add_definitions(${PERL_EXTRA_C_FLAGS}) - set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY}) -endif() -if(${language} MATCHES tcl) - find_package(TCL) - include_directories(${TCL_INCLUDE_PATH}) - set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY}) -endif() -if(${language} MATCHES ruby) - find_package(Ruby) - include_directories(${RUBY_INCLUDE_PATH}) - set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY}) -endif() -if(${language} MATCHES php4) - find_package(PHP4) - include_directories(${PHP4_INCLUDE_PATH}) - set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY}) -endif() -if(${language} MATCHES pike) - find_package(Pike) - include_directories(${PIKE_INCLUDE_PATH}) - set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY}) -endif() -if(${language} MATCHES lua) - find_package(Lua) - include_directories(${LUA_INCLUDE_DIR}) - set(SWIG_LANG_TYPE TYPE SHARED) - set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES}) -endif() - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -set(CMAKE_SWIG_FLAGS "") - -set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON) -set_source_files_properties(example.i PROPERTIES SWIG_FLAGS "-includeall") -SWIG_ADD_LIBRARY(example - LANGUAGE "${language}" - ${SWIG_LANG_TYPE} - SOURCES example.i example.cxx) -SWIG_LINK_LIBRARIES(example ${SWIG_LANG_LIBRARIES}) diff --git a/Tests/SwigTest/example.cxx b/Tests/SwigTest/example.cxx deleted file mode 100644 index 961d6dd..0000000 --- a/Tests/SwigTest/example.cxx +++ /dev/null @@ -1,33 +0,0 @@ -/* File : example.c */ - -#include "example.h" -#define M_PI 3.14159265358979323846 - -/* Move the shape to a new location */ -void Shape::move(double dx, double dy) -{ - x += dx; - y += dy; -} - -int Shape::nshapes = 0; - -double Circle::area(void) -{ - return M_PI * radius * radius; -} - -double Circle::perimeter(void) -{ - return 2 * M_PI * radius; -} - -double Square::area(void) -{ - return width * width; -} - -double Square::perimeter(void) -{ - return 4 * width; -} diff --git a/Tests/SwigTest/example.h b/Tests/SwigTest/example.h deleted file mode 100644 index 366deb0..0000000 --- a/Tests/SwigTest/example.h +++ /dev/null @@ -1,37 +0,0 @@ -/* File : example.h */ - -class Shape -{ -public: - Shape() { nshapes++; } - virtual ~Shape() { nshapes--; }; - double x, y; - void move(double dx, double dy); - virtual double area(void) = 0; - virtual double perimeter(void) = 0; - static int nshapes; -}; - -class Circle : public Shape -{ -private: - double radius; - -public: - Circle(double r) - : radius(r){}; - virtual double area(void); - virtual double perimeter(void); -}; - -class Square : public Shape -{ -private: - double width; - -public: - Square(double w) - : width(w){}; - virtual double area(void); - virtual double perimeter(void); -}; diff --git a/Tests/SwigTest/example.i b/Tests/SwigTest/example.i deleted file mode 100644 index 75700b3..0000000 --- a/Tests/SwigTest/example.i +++ /dev/null @@ -1,10 +0,0 @@ -/* File : example.i */ -%module example - -%{ -#include "example.h" -%} - -/* Let's just grab the original header file here */ -%include "example.h" - diff --git a/Tests/SwigTest/runme.php4 b/Tests/SwigTest/runme.php4 deleted file mode 100644 index 653ced2..0000000 --- a/Tests/SwigTest/runme.php4 +++ /dev/null @@ -1,58 +0,0 @@ - diff --git a/Tests/SwigTest/runme.pike b/Tests/SwigTest/runme.pike deleted file mode 100755 index ec28dd7..0000000 --- a/Tests/SwigTest/runme.pike +++ /dev/null @@ -1,53 +0,0 @@ -import .example; - -int main() -{ - // ----- Object creation ----- - - write("Creating some objects:\n"); - Circle c = Circle(10.0); - write(" Created circle.\n"); - Square s = Square(10.0); - write(" Created square.\n"); - - // ----- Access a static member ----- - - write("\nA total of " + Shape_nshapes_get() + " shapes were created\n"); - - // ----- Member data access ----- - - // Set the location of the object - - c->x_set(20.0); - c->y_set(30.0); - - s->x_set(-10.0); - s->y_set(5.0); - - write("\nHere is their current position:\n"); - write(" Circle = (%f, %f)\n", c->x_get(), c->y_get()); - write(" Square = (%f, %f)\n", s->x_get(), s->y_get()); - - // ----- Call some methods ----- - - write("\nHere are some properties of the shapes:\n"); - write(" The circle:\n"); - write(" area = %f.\n", c->area()); - write(" perimeter = %f.\n", c->perimeter()); - write(" The square:\n"); - write(" area = %f.\n", s->area()); - write(" perimeter = %f.\n", s->perimeter()); - - write("\nGuess I'll clean up now\n"); - - /* See if we can force 's' to be garbage-collected */ - s = 0; - - /* Now we should be down to only 1 shape */ - write("%d shapes remain\n", Shape_nshapes_get()); - - /* Done */ - write("Goodbye\n"); - - return 0; -} diff --git a/Tests/SwigTest/runme.pl b/Tests/SwigTest/runme.pl deleted file mode 100644 index 5bfb3d8..0000000 --- a/Tests/SwigTest/runme.pl +++ /dev/null @@ -1,57 +0,0 @@ -# file: runme.pl - -# This file illustrates the low-level C++ interface -# created by SWIG. In this case, all of our C++ classes -# get converted into function calls. - -use example; - -# ----- Object creation ----- - -print "Creating some objects:\n"; -$c = examplec::new_Circle(10); -print " Created circle $c\n"; -$s = examplec::new_Square(10); -print " Created square $s\n"; - -# ----- Access a static member ----- - -print "\nA total of $examplec::Shape_nshapes shapes were created\n"; - -# ----- Member data access ----- - -# Set the location of the object. -# Note: methods in the base class Shape are used since -# x and y are defined there. - -examplec::Shape_x_set($c, 20); -examplec::Shape_y_set($c, 30); -examplec::Shape_x_set($s,-10); -examplec::Shape_y_set($s,5); - -print "\nHere is their current position:\n"; -print " Circle = (",examplec::Shape_x_get($c),",", examplec::Shape_y_get($c),")\n"; -print " Square = (",examplec::Shape_x_get($s),",", examplec::Shape_y_get($s),")\n"; - -# ----- Call some methods ----- - -print "\nHere are some properties of the shapes:\n"; -foreach $o ($c,$s) { - print " $o\n"; - print " area = ", examplec::Shape_area($o), "\n"; - print " perimeter = ", examplec::Shape_perimeter($o), "\n"; - } -# Notice how the Shape_area() and Shape_perimeter() functions really -# invoke the appropriate virtual method on each object. - -# ----- Delete everything ----- - -print "\nGuess I'll clean up now\n"; - -# Note: this invokes the virtual destructor -examplec::delete_Shape($c); -examplec::delete_Shape($s); - -print $examplec::Shape_nshapes," shapes remain\n"; -print "Goodbye\n"; - 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" - diff --git a/Tests/SwigTest/runme.rb b/Tests/SwigTest/runme.rb deleted file mode 100644 index de73bcd..0000000 --- a/Tests/SwigTest/runme.rb +++ /dev/null @@ -1,49 +0,0 @@ -# file: runme.rb - -# This file illustrates the C++ interface created by SWIG. -# All of our C++ classes get converted into Ruby classes. - -require 'example' - -# ----- Object creation ----- - -print "Creating some objects:\n" -c = Example::Circle.new(10) -print " Created circle #{c}\n" -s = Example::Square.new(10) -print " Created square #{s}\n" - -# ----- Access a static member ----- - -print "\nA total of #{Example::Shape.nshapes} shapes were created\n" - -# ----- Member data access ----- - -# Set the location of the object - -# Notice how we can do this using functions specific to -# the 'Circle' class. -c.x = 20 -c.y = 30 - -# Now use the same functions in the base class -s.x = -10 -s.y = 5 - -print "\nHere is their current position:\n" -print " Circle = (", c.x, ",", c.y, ")\n" -print " Square = (", s.x, ",", s.y, ")\n" - -# ----- Call some methods ----- - -print "\nHere are some properties of the shapes:\n" -for o in [c, s] - print " #{o}\n" - print " area = ", o.area, "\n" - print " perimeter = ", o.perimeter, "\n" -end -# Notice how the Shape#area() and Shape#perimeter() functions really -# invoke the appropriate virtual method on each object. - -print "\n", Example::Shape.nshapes," shapes remain\n" -print "Goodbye\n" diff --git a/Tests/SwigTest/runme.tcl b/Tests/SwigTest/runme.tcl deleted file mode 100644 index c7f4725..0000000 --- a/Tests/SwigTest/runme.tcl +++ /dev/null @@ -1,50 +0,0 @@ -# file: runme.tcl - -# This file illustrates the high level C++ interface. -# In this case C++ classes work kind of like Tk widgets - -catch { load ./example[info sharedlibextension] example} - -# ----- Object creation ----- - -puts "Creating some objects:" -Circle c 10 -puts " Created circle [c cget -this]" -Square s 10 -puts " Created square [s cget -this]" - -# ----- Access a static member ----- - -puts "\nA total of $Shape_nshapes shapes were created" - -# ----- Member data access ----- - -# Set the location of the object - -c configure -x 20 -y 30 -s configure -x -10 -y 5 - -puts "\nHere is their current position:" -puts " Circle = ([c cget -x], [c cget -y])" -puts " Square = ([s cget -x], [s cget -y])" - -# ----- Call some methods ----- - -puts "\nHere are some properties of the shapes:" -foreach o "c s" { - puts " [$o cget -this]" - puts " area = [$o area]" - puts " perimeter = [$o perimeter]" -} - -# ----- Delete everything ----- - -puts "\nGuess I'll clean up now" - -# Note: this invokes the virtual destructor -rename c "" -rename s "" - -puts "$Shape_nshapes shapes remain" -puts "Goodbye" - diff --git a/Tests/SwigTest/runme2.tcl b/Tests/SwigTest/runme2.tcl deleted file mode 100644 index 88ec2f6..0000000 --- a/Tests/SwigTest/runme2.tcl +++ /dev/null @@ -1,70 +0,0 @@ -# file: runme2.tcl - -# This file illustrates the low-level C++ interface -# created by SWIG. In this case, all of our C++ classes -# get converted into function calls. - -catch { load ./example[info sharedlibextension] example} - -# ----- Object creation ----- - -puts "Creating some objects:" -set c [new_Circle 10] -puts " Created circle $c" -set s [new_Square 10] -puts " Created square $s" - -# ----- Access a static member ----- - -puts "\nA total of $Shape_nshapes shapes were created" - -# ----- Member data access ----- - -# Set the location of the object -# Note: the base class must be used since that's where x and y -# were declared. - -Shape_x_set $c 20 -Shape_y_set $c 30 -Shape_x_set $s -10 -Shape_y_set $s 5 - -puts "\nHere is their current position:" -puts " Circle = ([Shape_x_get $c], [Shape_y_get $c])" -puts " Square = ([Shape_x_get $s], [Shape_y_get $s])" - -# ----- Call some methods ----- - -puts "\nHere are some properties of the shapes:" -foreach o "$c $s" { - puts " $o" - puts " area = [Shape_area $o]" - puts " perimeter = [Shape_perimeter $o]" -} -# Notice how the Shape_area() and Shape_perimeter() functions really -# invoke the appropriate virtual method on each object. - -# ----- Try to cause a type error ----- - -puts "\nI'm going to try and break the type system" - -if { [catch { - # Bad script! - Square_area $c # Try to invoke Square method on a Circle - puts " Bad bad SWIG!" - -}]} { - puts " Well, it didn't work. Good SWIG." -} - -# ----- Delete everything ----- - -puts "\nGuess I'll clean up now" - -# Note: this invokes the virtual destructor -delete_Shape $c -delete_Shape $s - -puts "$Shape_nshapes shapes remain" -puts "Goodbye" - -- cgit v0.12 From 0bef9eb410566aa10536331d086d4a3ee265a526 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 29 Jan 2018 10:40:25 +0100 Subject: UseSWIG: modernize module --- Help/release/dev/UseSWIG-modernize-module.rst | 6 + Modules/UseSWIG.cmake | 485 ++++++++++++++++------- Tests/RunCMake/UseSWIG/BasicConfiguration.cmake | 68 ++++ Tests/RunCMake/UseSWIG/BasicPerl.cmake | 18 + Tests/RunCMake/UseSWIG/BasicPython.cmake | 9 + Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake | 3 + Tests/RunCMake/UseSWIG/LegacyPerl.cmake | 2 +- Tests/RunCMake/UseSWIG/LegacyPython.cmake | 2 +- Tests/RunCMake/UseSWIG/MultipleModules.cmake | 30 ++ Tests/RunCMake/UseSWIG/RunCMakeTest.cmake | 22 +- 10 files changed, 489 insertions(+), 156 deletions(-) create mode 100644 Help/release/dev/UseSWIG-modernize-module.rst create mode 100644 Tests/RunCMake/UseSWIG/BasicConfiguration.cmake create mode 100644 Tests/RunCMake/UseSWIG/BasicPerl.cmake create mode 100644 Tests/RunCMake/UseSWIG/BasicPython.cmake create mode 100644 Tests/RunCMake/UseSWIG/MultipleModules.cmake 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/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index cc30669..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 @@ Defines the following macros for use with SWIG: swig_add_library( [TYPE ] LANGUAGE + [NO_PROXY] + [OUTPUT_DIR ] + [OUTFILE_DIR ] SOURCES ... - ) + ) - The variable ``SWIG_MODULE__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( [ 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 @@ of the ``swig_add_library`` macro to specify special behavior of SWIG: 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 @@ of the ``swig_add_library`` macro to specify special behavior of SWIG: 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 @@ Some variables can be set to specify special behavior of SWIG: Specify extra dependencies for the generated module for ````. #]=======================================================================] + +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 @@ endmacro() # 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$-I>") + endif() + set (property "$") + list (APPEND swig_source_file_flags "$<$:-I$-I>>") + + set (property "$") + list (APPEND swig_source_file_flags "$<$:-D$-D>>") + get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS) + if (compile_definitions) + list (APPEND swig_source_file_flags "-D$-D>") + endif() + + list (APPEND swig_source_file_flags "$") + 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 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) ".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$-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} $) + 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 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) 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} $) + + get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS) + set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $ ${compile_definitions}) + + get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS) + set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY 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 @@ macro(SWIG_ADD_MODULE name language) 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 @@ macro(SWIG_ADD_LIBRARY name) 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() - swig_module_initialize(${name} ${_SAM_LANGUAGE}) + 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(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}") + set (outputdir "${_SAM_OUTPUT_DIR}") + if (NOT _SAM_OUTPUT_DIR) + if (CMAKE_SWIG_OUTDIR) + set (outputdir "${CMAKE_SWIG_OUTDIR}") else() - set(swig_other_sources ${swig_other_sources} "${it}") + set (outputdir "${CMAKE_CURRENT_BINARY_DIR}") endif() - endforeach() + 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 ${_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 @@ macro(SWIG_ADD_LIBRARY name) # 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,40 +532,60 @@ macro(SWIG_ADD_LIBRARY name) # .pyd is now the only filename extension that will be searched for. # 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") + elseif (swig_lowercase_language STREQUAL "perl") # 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 "") if (APPLE) - set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".dylib") + 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/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 ";" "$" perl_path "${perl_path}") + set (perl_env "PATH=$$${perl_path}") +else() + set (perl_env "LD_LIBRARY_PATH=$") +endif() + +add_custom_target (RunTest + COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" + "${PERL_EXECUTABLE}" "-I$" + "${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=$" + "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py" + DEPENDS example) diff --git a/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake index 3f400bf..3ce0790 100644 --- a/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake +++ b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake @@ -1,4 +1,7 @@ +# Prevent deprecated warnings from new UseSWIG module +set (CMAKE_WARN_DEPRECATED FALSE) + find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) diff --git a/Tests/RunCMake/UseSWIG/LegacyPerl.cmake b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake index cfa8c53..3428c46 100644 --- a/Tests/RunCMake/UseSWIG/LegacyPerl.cmake +++ b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake @@ -11,7 +11,7 @@ else() set (perl_env "LD_LIBRARY_PATH=$") endif() -add_custom_target (RunPerl +add_custom_target (RunTest COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" "${PERL_EXECUTABLE}" "-I$" "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl" diff --git a/Tests/RunCMake/UseSWIG/LegacyPython.cmake b/Tests/RunCMake/UseSWIG/LegacyPython.cmake index f3d9e2b..8b47aa2 100644 --- a/Tests/RunCMake/UseSWIG/LegacyPython.cmake +++ b/Tests/RunCMake/UseSWIG/LegacyPython.cmake @@ -3,7 +3,7 @@ set(language "python") include (LegacyConfiguration.cmake) -add_custom_target (RunPython +add_custom_target (RunTest COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$" "${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 index cbeba66..c63ff2e 100644 --- a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake +++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake @@ -1,13 +1,23 @@ include(RunCMake) -function(run_SWIG group language) - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${group}${language}-build) +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(${group}${language}) - run_cmake_command(${group}${language}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --target Run${language}) + run_cmake(${test}) + run_cmake_command(${test}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} ${_SWIG_TEST_TARGET}) endfunction() -run_SWIG(Legacy Python) -run_SWIG(Legacy Perl) +run_SWIG(LegacyPython TARGET RunTest) +run_SWIG(LegacyPerl TARGET RunTest) + +run_SWIG(BasicPython TARGET RunTest) +run_SWIG(BasicPerl TARGET RunTest) + +run_SWIG(MultipleModules) -- cgit v0.12