Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gmp: bump + enable building static libraries on MSVC #3836

Merged
merged 2 commits into from
Dec 14, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions recipes/gmp/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
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"
- patch_file: "patches/6.1.x-0002-fix-MSVC-debug.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):
@@ -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:
@@ -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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only for Visual Studio? Is it not also required for all platforms if disable_assembly=False?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other platforms can just use the gnu assembler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using yasm, this also means that for the moment only x86 and x86_64 architectures are supported on MSVC.
Maybe it is possible to combine the GNU assembler (from binutils) with MSVC, but that's something I did not test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so LGTM

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")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏴

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is correct.
The tests are run in the build context.
The checks are also disabled by default, so there will be no timeouts.

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()

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)
{
11 changes: 11 additions & 0 deletions recipes/gmp/all/patches/6.1.x-0002-fix-MSVC-debug.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- configure
+++ configure
@@ -6776,7 +6776,7 @@
long i;
for (i = 0; i < 88 + 1; i++)
a[i] = ~0L;
- r = malloc (10000 * sizeof (unsigned long));
+ r = calloc (10000, sizeof (unsigned long));
r2 = r;
for (i = 0; i < 528; i += 23)
{
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
Comment on lines 2 to +5
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"6.2.0":
folder: all
"6.2.1":
folder: all
"6.2.1":
folder: all
"6.2.0":
folder: all

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it work adding 6.2.0 ... maybe justy keep the point release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add 6.2.1 in this pr.
This comment was just about ordering the versions in descending order.

"6.1.2":
folder: all