Skip to content

Commit

Permalink
gmp: enable building static libraries on MSVC
Browse files Browse the repository at this point in the history
  • Loading branch information
madebr committed Dec 10, 2020
1 parent 2c139be commit 8704c0b
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 33 deletions.
23 changes: 21 additions & 2 deletions recipes/gmp/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
sources:
"6.2.1":
url: "https://gmplib.org/download/gmp/gmp-6.2.1.tar.bz2"
sha256: "eae9326beb4158c386e39a356818031bd28f3124cf915f8c5b1dc4c7a36b4d7c"
"6.2.0":
url: "https://gmplib.org/download/gmp/gmp-6.2.0.tar.bz2"
sha256: "f51c99cb114deb21a60075ffb494c1a210eb9d7cb729ed042ddb7de9534451ea"
"6.1.2":
url: "https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2"
sha256: "5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2"
patches:
"6.2.1":
- patch_file: "patches/0001-msvc-dumpbin-yasm-wrapper.patch"
base_path: ""
- patch_file: "patches/6.2.x-0001-fix-MSVC-next-prime-error.patch"
base_path: "source_subfolder"
"6.2.0":
url: "https://gmplib.org/download/gmp/gmp-6.2.0.tar.bz2"
sha256: "f51c99cb114deb21a60075ffb494c1a210eb9d7cb729ed042ddb7de9534451ea"
- patch_file: "patches/0001-msvc-dumpbin-yasm-wrapper.patch"
base_path: ""
- patch_file: "patches/6.2.x-0001-fix-MSVC-next-prime-error.patch"
base_path: "source_subfolder"
"6.1.2":
- patch_file: "patches/0001-msvc-dumpbin-yasm-wrapper.patch"
base_path: ""
- patch_file: "patches/6.1.x-0001-fix-MSVC-next-prime-error.patch"
base_path: "source_subfolder"
97 changes: 68 additions & 29 deletions recipes/gmp/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os
import stat
from conans import ConanFile, AutoToolsBuildEnvironment, tools
from conans.errors import ConanInvalidConfiguration
from contextlib import contextmanager
import os
import stat
import textwrap


class GmpConan(ConanFile):
Expand All @@ -15,17 +17,21 @@ class GmpConan(ConanFile):
options = {"shared": [True, False], "fPIC": [True, False], "disable_assembly": [True, False],
"run_checks": [True, False], "enable_cxx" : [True, False]}
default_options = {"shared": False, "fPIC": True, "disable_assembly": True, "run_checks": False, "enable_cxx" : True}
exports_sources = "patches/*"

_source_subfolder = "source_subfolder"
_autotools = None

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

def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC

def configure(self):
if self.settings.compiler == "Visual Studio":
raise ConanInvalidConfiguration("The gmp package cannot be built on Visual Studio.")
if self.settings.compiler == "Visual Studio" and self.options.shared:
raise ConanInvalidConfiguration("Cannot build a shared library using Visual Studio: some error occurs at link time")
if self.options.shared:
del self.options.fPIC
if not self.options.enable_cxx:
Expand All @@ -36,46 +42,79 @@ def package_id(self):
del self.info.options.run_checks # run_checks doesn't affect package's ID

def build_requirements(self):
if tools.os_info.is_windows and self.settings.compiler != "Visual Studio" and \
"CONAN_BASH_PATH" not in os.environ and tools.os_info.detect_windows_subsystem() != "msys2":
if tools.os_info.is_windows and not tools.get_env("CONAN_BASH_PATH"):
self.build_requires("msys2/20200517")
if self.settings.compiler == "Visual Studio":
self.build_requires("yasm/1.3.0")
self.build_requires("automake/1.16.3")

def source(self):
tools.get(**self.conan_data["sources"][self.version])
os.rename("gmp-" + self.version, self._source_subfolder)

def _configure_autotools(self):
if not self._autotools:
self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
if self.settings.os == "Macos":
configure_file = "configure"
tools.replace_in_file(configure_file, r"-install_name \$rpath/", "-install_name ")
configure_stats = os.stat(configure_file)
os.chmod(configure_file, configure_stats.st_mode | stat.S_IEXEC)
configure_args = []
if self.options.disable_assembly:
configure_args.append("--disable-assembly")
if self.options.shared:
configure_args.extend(["--enable-shared", "--disable-static"])
else:
configure_args.extend(["--disable-shared", "--enable-static"])
if self.options.enable_cxx:
configure_args.append("--enable-cxx")
self._autotools.configure(args=configure_args)
if self._autotools:
return self._autotools
self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
if tools.is_apple_os(self.settings.os):
configure_file = os.path.join(self._source_subfolder, "configure")
tools.replace_in_file(configure_file, r"-install_name \$rpath/", "-install_name ")
configure_stats = os.stat(configure_file)
os.chmod(configure_file, configure_stats.st_mode | stat.S_IEXEC)
yes_no = lambda v: "yes" if v else "no"
configure_args = [
"--enable-assembly={}".format(yes_no(not self.options.disable_assembly)),
"--enable-cxx={}".format(yes_no(self.options.enable_cxx)),
"--enable-shared={}".format(yes_no(self.options.shared)),
"--enable-static={}".format(yes_no(not self.options.shared)),
"--srcdir={}".format(os.path.join(self.source_folder, self._source_subfolder).replace("\\", "/")),
]
if self.settings.compiler == "Visual Studio":
configure_args.extend([
"ac_cv_c_restrict=restrict",
"gmp_cv_asm_label_suffix=:",
"lt_cv_sys_global_symbol_pipe=cat", # added to get further in shared MSVC build, but it gets stuck later
])
self._autotools.flags.append("-FS")
# self._autotools.cxx_flags.append("-EHsc")
self._autotools.configure(args=configure_args, configure_dir=self._source_subfolder)
return self._autotools

@contextmanager
def _build_context(self):
if self.settings.compiler == "Visual Studio":
with tools.vcvars(self.settings):
yasm_machine = {
"x86": "x86",
"x86_64": "amd64",
}[str(self.settings.arch)]
env = {
"CC": "cl -nologo",
"CCAS": "{} -a x86 -m {} -p gas -r raw -f win32 -g null -X gnu".format(os.path.join(self.build_folder, "yasm_wrapper.sh").replace("\\", "/"), yasm_machine),
"CXX": "cl -nologo",
"AR": "{} lib".format(self.deps_user_info["automake"].ar_lib.replace("\\", "/")),
"LD": "link -nologo",
"NM": "python {}/{}".format(self.build_folder.replace("\\", "/"), "dumpbin_nm.py"),
}
with tools.environment_append(env):
yield
else:
yield

def build(self):
with tools.chdir(self._source_subfolder):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
tools.patch(**patch)
with self._build_context():
autotools = self._configure_autotools()
autotools.make()
# INFO: According to the gmp readme file, make check should not be omitted, but it causes timeouts on the CI server.
if self.options.run_checks:
autotools.make(args=["check"])
# INFO: According to the gmp readme file, make check should not be omitted, but it causes timeouts on the CI server.
if self.options.run_checks:
autotools.make(args=["check"])

def package(self):
self.copy("COPYINGv2", dst="licenses", src=self._source_subfolder)
self.copy("COPYING.LESSERv3", dst="licenses", src=self._source_subfolder)
with tools.chdir(self._source_subfolder):
with self._build_context():
autotools = self._configure_autotools()
autotools.install()

Expand Down
71 changes: 71 additions & 0 deletions recipes/gmp/all/patches/0001-msvc-dumpbin-yasm-wrapper.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
--- /dev/null
+++ dumpbin_nm.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+
+import re
+import subprocess
+import sys
+#print(open(sys.argv[1], "rb").read())
+#output = subprocess.check_output(["dumpbin", "-nologo", "-symbols"] + sys.argv[1:], stderr=subprocess.STDOUT, text=True, shell=True)
+output = subprocess.check_output("dumpbin -nologo -symbols {}".format(sys.argv[1]), stderr=subprocess.STDOUT, text=True, shell=True)
+for line in output.splitlines():
+ d = re.split("[ |]+", line.strip())
+ if len(d) == 6:
+ try:
+ int(d[0])
+ except ValueError:
+ continue
+
+ section = d[-1]
+ if section == ".file":
+ continue
+ elif section == ".data":
+ stype = "d"
+ elif section == ".text":
+ stype = "t"
+ else:
+ stype = "D"
+ offset = d[1]
+ print("{} {} {}".format(offset, stype, section))
--- /dev/null
+++ yasm_wrapper.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+asmopts=()
+setoutput=
+calculated_output=
+source=
+while test $# -gt 0; do
+ case "$1" in
+ *.s | *.S | *.asm | *.ASM)
+ calculated_output=$(echo -n "$1" | sed -e 's/\.asm$/.obj/g' | sed -e 's/\.ASM/.obj/g' | sed -e 's/\.s/.obj/g' | sed -e 's/\.S/.obj/g')
+ source="$1"
+ ;;
+ -o)
+ asmopts+=("$1")
+ shift
+ setoutput="$1"
+ asmopts+=("$1")
+ ;;
+ -O*)
+ ;;
+ -MT | -MD | -MTd | -MDd)
+ ;;
+ -D*)
+ asmopts+=("$1")
+ ;;
+ *)
+ asmopts+=("$1")
+ ;;
+ esac
+ shift
+done
+
+if [ "$setoutput" == "" ] && [ "$calculated_output" != "" ]; then
+ asmopts+=("-o")
+ asmopts+=("$calculated_output")
+fi
+
+echo "Executing yasm ${asmopts[@]} $source"
+exec yasm ${asmopts[@]} "$source"
14 changes: 14 additions & 0 deletions recipes/gmp/all/patches/6.1.x-0001-fix-MSVC-next-prime-error.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--- nextprime.c
+++ nextprime.c
@@ -54,9 +54,9 @@

#include "gmp.h"
#include "gmp-impl.h"
+#ifndef _MSC_VER
#include <string.h> /* for memset */
+#endif
-
-
unsigned long int
gmp_nextprime (gmp_primesieve_t *ps)
{
14 changes: 14 additions & 0 deletions recipes/gmp/all/patches/6.2.x-0001-fix-MSVC-next-prime-error.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--- nextprime.c
+++ nextprime.c
@@ -53,9 +53,9 @@
*/

#include "gmp-impl.h"
+#ifndef _MSC_VER
#include <string.h> /* for memset */
+#endif
-
-
unsigned long int
gmp_nextprime (gmp_primesieve_t *ps)
{
6 changes: 4 additions & 2 deletions recipes/gmp/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
versions:
"6.1.2":
folder: all
"6.2.0":
folder: all
"6.2.1":
folder: all
"6.1.2":
folder: all

0 comments on commit 8704c0b

Please sign in to comment.