Skip to content

Commit

Permalink
Merge pull request #1717 from madebr/swig
Browse files Browse the repository at this point in the history
  • Loading branch information
uilianries authored Jun 22, 2020
2 parents 52a4ff4 + 1e43ca8 commit a69c690
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 0 deletions.
10 changes: 10 additions & 0 deletions recipes/swig/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
sources:
"4.0.1":
url: "https://github.com/swig/swig/archive/rel-4.0.1.tar.gz"
sha256: "2eaf6fb89d071d1be280bf995c63360b3729860c0da64948123b5d7e4cfb6cb7"
patches:
"4.0.1":
- base_path: "source_subfolder"
patch_file: "patches/0001-swig-linux-library-path.patch"
- base_path: "source_subfolder"
patch_file: "patches/0002-do-not-define-SWIG_LIB_WIN_UNIX.patch"
125 changes: 125 additions & 0 deletions recipes/swig/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
from conans import ConanFile, tools, AutoToolsBuildEnvironment
from contextlib import contextmanager
import os


class SwigConan(ConanFile):
name = "swig"
description = "SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages."
url = "https://github.com/conan-io/conan-center-index"
homepage = "http://www.swig.org"
license = "GPL-3.0-or-later"
topics = ("conan", "swig", "python", "java", "wrapper")
exports_sources = "patches/**"
settings = "os", "arch", "compiler", "build_type"

_autotools = None

@property
def _source_subfolder(self):
return "source_subfolder"

def configure(self):
del self.settings.compiler.libcxx
del self.settings.compiler.cppstd

def build_requirements(self):
if tools.os_info.is_windows and not tools.get_env("CONAN_BASH_PATH") \
and tools.os_info.detect_windows_subsystem() != "msys2":
self.build_requires("msys2/20190524")
if tools.os_info.is_windows:
self.build_requires("winflexbison/2.5.22")
else:
self.build_requires("bison/3.5.3")
self.build_requires("automake/1.16.2")

def requirements(self):
self.requires("pcre/8.41")

def source(self):
tools.get(**self.conan_data["sources"][self.version])
os.rename("swig-rel-{}".format(self.version), self._source_subfolder)

@contextmanager
def _build_context(self):
if self.settings.compiler == "Visual Studio":
with tools.vcvars(self.settings):
env = {
"CC": "{} cl -nologo".format(tools.unix_path(self.deps_user_info["automake"].compile)),
"CXX": "{} cl -nologo".format(tools.unix_path(self.deps_user_info["automake"].compile)),
"AR": "{} link".format(self.deps_user_info["automake"].ar_lib),
"LD": "link",
}
with tools.environment_append(env):
yield
else:
yield

def _configure_autotools(self):
if self._autotools:
return self._autotools

self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
deps_libpaths = self._autotools.library_paths
deps_libs = self._autotools.libs
deps_defines = self._autotools.defines
if self.settings.os == "Windows" and self.settings.compiler != "Visual Studio":
self._autotools.link_flags.append("-static")

libargs = list("-L\"{}\"".format(p) for p in deps_libpaths) + list("-l\"{}\"".format(l) for l in deps_libs)
args = [
"PCRE_LIBS={}".format(" ".join(libargs)),
"PCRE_CPPFLAGS={}".format(" ".join("-D{}".format(define) for define in deps_defines)),
"--host={}".format(self.settings.arch),
"--with-swiglibdir={}".format(self._swiglibdir),
]
if self.settings.compiler == "Visual Studio":
self.output.warn("Visual Studio compiler cannot create ccache-swig. Disabling ccache-swig.")
args.append("--disable-ccache")
self._autotools.flags.append("-FS")

self._autotools.libs = []
self._autotools.library_paths = []

self._autotools.configure(args=args, configure_dir=self._source_subfolder)
return self._autotools

def _patch_sources(self):
for patch in self.conan_data["patches"][self.version]:
tools.patch(**patch)

def build(self):
self._patch_sources()
with tools.chdir(os.path.join(self._source_subfolder)):
self.run("./autogen.sh", win_bash=tools.os_info.is_windows)
with self._build_context():
autotools = self._configure_autotools()
autotools.make()

def package(self):
self.copy(pattern="LICENSE*", dst="licenses", src=self._source_subfolder)
self.copy(pattern="COPYRIGHT", dst="licenses", src=self._source_subfolder)
with self._build_context():
autotools = self._configure_autotools()
autotools.install()

if self.settings.compiler != "Visual Studio":
with tools.chdir(os.path.join(self.package_folder, "bin")):
strip = tools.get_env("STRIP") or tools.which("strip")
ext = ".exe" if tools.os_info.is_windows else ""
if strip:
self.run("{} swig{}".format(strip, ext), win_bash=tools.os_info.is_windows)
self.run("{} ccache-swig{}".format(strip, ext), win_bash=tools.os_info.is_windows)

@property
def _swiglibdir(self):
return os.path.join(self.package_folder, "bin", "swiglib").replace("\\", "/")

def package_info(self):
# FIXME: Don't set cmake_find_package name because conan cmake generators do not define SWIG_EXECUTABLE
# self.cpp_info.names["cmake_find_package"] = "SWIG"
# self.cpp_info.names["cmake_find_package_multi"] = "SWIG"

bindir = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(bindir))
self.env_info.PATH.append(bindir)
43 changes: 43 additions & 0 deletions recipes/swig/all/patches/0001-swig-linux-library-path.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
--- Source/Modules/main.cxx
+++ Source/Modules/main.cxx
@@ -879,6 +879,23 @@
}
}

+#if defined(HAVE_UNISTD_H)
+#include <libgen.h>
+#include <unistd.h>
+
+static String *get_exe_path(void) {
+ char buffer[PATH_MAX];
+ ssize_t nb = readlink("/proc/self/exe", buffer, PATH_MAX);
+ if (nb != -1) {
+ buffer[nb] = '\0';
+ dirname(buffer);
+ strcat(buffer, "/swiglib");
+ return NewStringWithSize(buffer, strlen(buffer));
+ }
+ return NewString(SWIG_LIB);
+}
+#endif
+
int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) {
char *c;

@@ -938,13 +953,15 @@
char buf[MAX_PATH];
char *p;
if (!(GetModuleFileName(0, buf, MAX_PATH) == 0 || (p = strrchr(buf, '\\')) == 0)) {
*(p + 1) = '\0';
- SwigLib = NewStringf("%sLib", buf); // Native windows installation path
+ SwigLib = NewStringf("%sswiglib", buf); // Native windows installation path
} else {
SwigLib = NewStringf(""); // Unexpected error
}
if (Len(SWIG_LIB_WIN_UNIX) > 0)
SwigLibWinUnix = NewString(SWIG_LIB_WIN_UNIX); // Unix installation path using a drive letter (for msys/mingw)
+#elif defined(HAVE_UNISTD_H)
+ SwigLib = get_exe_path();
#else
SwigLib = NewString(SWIG_LIB);
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- configure.ac
+++ configure.ac
@@ -2728,7 +2728,7 @@
*-*-cygwin*) SWIG_LIB_WIN_UNIX=`cygpath --mixed "$SWIG_LIB"`;;
*) SWIG_LIB_WIN_UNIX="";;
esac
-AC_DEFINE_UNQUOTED(SWIG_LIB_WIN_UNIX, ["$SWIG_LIB_WIN_UNIX"], [Directory for SWIG system-independent libraries (Unix install on native Windows)])
+AC_DEFINE_UNQUOTED(SWIG_LIB_WIN_UNIX, [""], [Directory for SWIG system-independent libraries (Unix install on native Windows)])

SWIG_LIB_PREINST=$ABS_SRCDIR/Lib
AC_SUBST(SWIG_LIB_PREINST)
16 changes: 16 additions & 0 deletions recipes/swig/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 2.8.12)
project(PackageTest C)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

find_package(SWIG REQUIRED)
include(UseSWIG)

swig_add_library(${PROJECT_NAME}
TYPE MODULE
LANGUAGE python
SOURCES
test.i
test_package.c
)
31 changes: 31 additions & 0 deletions recipes/swig/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from conans import CMake, ConanFile, tools
from conans.errors import ConanException
import os


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"

# # FIXME: cpython is not available on CCI (yet)
# def build(self):
# cmake = CMake(self)
# cmake.configure(args=["--trace", "--trace-expand"])
# cmake.build()
#
# def build_requirements(self):
# self.build_requires("cpython/3.8.3")
#
# def requirements(self):
# self.requires("cpython/3.8.3")

def test(self):
if not tools.cross_building(self.settings):
# # FIXME: cpython is not available on CCI (yet)
# with tools.chdir("lib"):
# self.run("python -c \"import sys; import _PackageTest; gcd = _PackageTest.gcd(12, 16); print('gcd =', gcd); sys.exit(0 if gcd == 4 else 1)\"", run_environment=True)
# self.run("python -c \"import sys; import _PackageTest; foo = _PackageTest.cvar.foo; print('foo =', foo); sys.exit(0 if foo == 3.14159265359 else 1)\"", run_environment=True)
testdir = os.path.dirname(os.path.realpath(__file__))
self.run("swig -python -outcurrentdir %s" % os.path.join(testdir, "test.i"))
if not os.path.isfile("example.py"):
raise ConanException("example.py is not created by swig")
7 changes: 7 additions & 0 deletions recipes/swig/all/test_package/test.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* File : example.i */
%module example

%inline %{
extern int gcd(int u, int v);
extern double foo;
%}
30 changes: 30 additions & 0 deletions recipes/swig/all/test_package/test_package.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Source: https://en.wikipedia.org/wiki/Binary_GCD_algorithm#Recursive_version_in_C
int gcd(int u, int v) {
// simple cases (termination)
if (u == v)
return u;

if (u == 0)
return v;

if (v == 0)
return u;

// look for factors of 2
if (~u & 1) // u is even
if (v & 1) // v is odd
return gcd(u >> 1, v);
else // both u and v are even
return gcd(u >> 1, v >> 1) << 1;

if (~v & 1) // u is odd, v is even
return gcd(u, v >> 1);

// reduce larger argument
if (u > v)
return gcd((u - v) >> 1, v);

return gcd((v - u) >> 1, u);
}

double foo = 3.14159265359;
3 changes: 3 additions & 0 deletions recipes/swig/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
versions:
"4.0.1":
folder: "all"

0 comments on commit a69c690

Please sign in to comment.