Skip to content

Commit

Permalink
(conan-io#14687) MPFR: partial Conan 2.0 Compatibility
Browse files Browse the repository at this point in the history
* MPFR Conan 2.0 Compatibility

* Fixed lint errors

* Missed one

* Fixed lint error in test_package

* Cleaned up patch records for older release

* Added patch descriptions

* Tweaked how win_bash is set

* Added more patch metadata

* Bump required_conan_version

* Account for path differences with Conan 2.0

* Make work on Windows (but requires VS 2022)

* Use NMake to work around MSBuild bug

* Differentiate MSVC from Windows

* Re-ordered apply_conandata_patches

* Add call to fix_apple_shared_install_name

* Deleted blank line to unstick CI

* Remove blank line to spur CI

* Removed redundant setting of --enable-shared and --enable-static

* Use test_package.c from ../test_project

* Use ../test_package/test_package.c

* Apply suggestion from code review

* Tweak previous change

* Added find_package to v1 CMakeLists.txt

* Try making conan_basic_setup(TARGETS) work

* Add cmake_find_package_multi generator per template

* Put back add_subdirectory

* Another try at making v1 work with TARGETS

* Removed extra blank link

* Try setting CMAKE_RUNTIME_OUTPUT_DIRECTORY instead of add_subdirectory

* Try using CMAKE_CURRENT_SOURCE_DIR

* Leverage CONAN_PKG::mpfr from conan_basic_setup(TARGETS)

* Restore use of PROJECT_NAME

* Apply suggestions from code review

Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com>

* Various cleanup changes

* Added autogen option to shield autoconf workflow

* Fixed lint error

* Removed autogen support

* Fixed lint warnings

* Bumped required_conan_version

* Bumped required_conan_version

* Update recipes/mpfr/all/test_v1_package/CMakeLists.txt

Co-authored-by: Uilian Ries <uilianries@gmail.com>

---------

Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com>
Co-authored-by: Rubén Rincón Blanco <rubenrb@jfrog.com>
Co-authored-by: Uilian Ries <uilianries@gmail.com>
  • Loading branch information
4 people authored and MartinDelille committed Apr 12, 2023
1 parent 17e6ff1 commit 5a18d61
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 152 deletions.
11 changes: 5 additions & 6 deletions recipes/mpfr/all/CMakeLists.txt.in
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
cmake_minimum_required(VERSION 2.8.11)
cmake_minimum_required(VERSION 3.19)
project(cmake_wrapper)

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

# autotools project does not allow building a shared mpfr library (because of libtool limitation)

find_package(gmp REQUIRED CONFIG)

add_library(mpfr {mpfr_sources})
target_compile_definitions(mpfr PRIVATE {definitions})
target_include_directories(mpfr PRIVATE "${{CMAKE_BINARY_DIR}}" "${{CMAKE_BINARY_DIR}}/src" "${{CMAKE_CURRENT_SOURCE_DIR}}")
target_link_libraries(mpfr PRIVATE ${{CONAN_LIBS}})
target_include_directories(mpfr PRIVATE "${{CMAKE_BINARY_DIR}}" "${{CMAKE_BINARY_DIR}}/src" "${{CMAKE_CURRENT_SOURCE_DIR}}/src")
target_link_libraries(mpfr PRIVATE gmp::gmp)
if(BUILD_SHARED_LIBS)
target_compile_definitions(mpfr PRIVATE MPFR_DLL)
endif()
Expand Down
14 changes: 6 additions & 8 deletions recipes/mpfr/all/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ sources:
url: https://ftp.gnu.org/gnu/mpfr/mpfr-4.0.2.tar.gz
patches:
"4.1.0":
- base_path: "source_subfolder"
patch_file: "patches/4.1.0-0001-windows-allow-mixed-shared-static.patch"
- base_path: "source_subfolder"
patch_file: "patches/4.1.0-0002-windows-header-dll.patch"
- patch_file: "patches/4.1.0-0002-windows-header-dll.patch"
patch_description: "Windows header DLL"
patch_type: "portability"
"4.0.2":
- base_path: "source_subfolder"
patch_file: "patches/4.0.2-0001-windows-allow-mixed-shared-static.patch"
- base_path: "source_subfolder"
patch_file: "patches/4.0.2-0002-windows-header-dll.patch"
- patch_file: "patches/4.0.2-0002-windows-header-dll.patch"
patch_description: "Windows header DLL"
patch_type: "portability"
182 changes: 94 additions & 88 deletions recipes/mpfr/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from conans import ConanFile, AutoToolsBuildEnvironment, CMake, tools
from conans.errors import ConanException
import contextlib
from conan import ConanFile
from conan.tools.files import save, load, copy, get, rmdir, replace_in_file, apply_conandata_patches
from conan.tools.layout import basic_layout
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake, cmake_layout
from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps
from conan.tools.microsoft import is_msvc, check_min_vs, unix_path
from conan.tools.apple import fix_apple_shared_install_name
from conan.errors import ConanException
import os
import re
import shlex

required_conan_version = ">=1.33.0"
required_conan_version = ">=1.58.0"


class MpfrConan(ConanFile):
name = "mpfr"
package_type = "library"
description = "The MPFR library is a C library for multiple-precision floating-point computations with " \
"correct rounding"
topics = ("mpfr", "multiprecision", "math", "mathematics")
Expand All @@ -20,7 +26,7 @@ class MpfrConan(ConanFile):
options = {
"shared": [True, False],
"fPIC": [True, False],
"exact_int": ["mpir", "gmp",]
"exact_int": ["mpir", "gmp",],
}
default_options = {
"shared": False,
Expand All @@ -29,146 +35,146 @@ class MpfrConan(ConanFile):
}

exports_sources = "CMakeLists.txt.in", "patches/**"
generators = "cmake"

_autotools = None
_cmake = None

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

@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)

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

def configure(self):
if self.options.shared:
del self.options.fPIC
del self.settings.compiler.libcxx
del self.settings.compiler.cppstd
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")

def requirements(self):
if self.options.exact_int == "gmp":
self.requires("gmp/6.2.1")
self.requires("gmp/6.2.1", transitive_headers=True)
elif self.options.exact_int == "mpir":
self.requires("mpir/3.0.0")

def build_requirements(self):
if self._settings_build.os == "Windows" and not tools.get_env("CONAN_BASH_PATH"):
self.build_requires("msys2/cci.latest")
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")

def layout(self):
if self.settings.os == "Windows":
cmake_layout(self, src_folder="src")
else:
basic_layout(self, src_folder="src")

def source(self):
tools.get(**self.conan_data["sources"][self.version],
destination=self._source_subfolder, strip_root=True)

def _configure_autotools(self):
if self._autotools:
return self._autotools
self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
yes_no = lambda v: "yes" if v else "no"
args = [
"--enable-thread-safe",
"--with-gmp-include={}".format(tools.unix_path(os.path.join(self.deps_cpp_info[str(self.options.exact_int)].rootpath, "include"))),
"--with-gmp-lib={}".format(tools.unix_path(os.path.join(self.deps_cpp_info[str(self.options.exact_int)].rootpath, "lib"))),
"--enable-shared={}".format(yes_no(self.options.shared)),
"--enable-static={}".format(yes_no(not self.options.shared)),
]
get(self, **self.conan_data["sources"][self.version],
destination=self.source_folder, strip_root=True)

def generate(self):
if self.settings.os == "Windows":
if is_msvc(self) and not check_min_vs(self, 193, raise_invalid=False) and \
not self.conf.get("tools.cmake.cmaketoolchain:generator", check_type=str):
# Use NMake to workaround bug in MSBuild versions prior to 2022 that shows up as:
# error MSB6001: Invalid command line switch for "cmd.exe". System.ArgumentException: Item
# has already been added. Key in dictionary: 'tmp' Key being added: 'TMP'
self.conf.define("tools.cmake.cmaketoolchain:generator", "NMake Makefiles")
tc = CMakeToolchain(self)
tc.generate()
tc = CMakeDeps(self)
tc.generate()
else: # Even with multiple toolchains (see below), can only have one "deps" generator as multiple ones will collide
tc = AutotoolsDeps(self)
tc.generate()

# Setup autotools on all platforms because we need to run autotools.configure when using CMake
tc = AutotoolsToolchain(self)
tc.configure_args.append("--enable-thread-safe")
tc.configure_args.append(f'--with-gmp={unix_path(self, self.dependencies[str(self.options.exact_int)].package_folder)}')
if self.settings.compiler == "clang":
# warning: optimization flag '-ffloat-store' is not supported
args.append("mpfr_cv_gcc_floatconv_bug=no")
tc.configure_args.append("mpfr_cv_gcc_floatconv_bug=no")
if self.settings.arch == "x86":
# fatal error: error in backend: Unsupported library call operation!
args.append("--disable-float128")
tc.configure_args.append("--disable-float128")

if self.options.exact_int == "mpir":
self._autotools.include_paths.append(self.build_folder)
if self.settings.compiler == "Visual Studio":
self._autotools.flags.append("-FS")
self._autotools.libs = []
self._autotools.configure(args=args, configure_dir=self._source_subfolder)
return self._autotools

def _configure_cmake(self):
if self._cmake:
return self._cmake
self._cmake = CMake(self)
self._cmake.configure(source_dir=os.path.join(self._source_subfolder, "src"))
return self._cmake
tc.extra_cflags.append(f"-I{self.build_folder}")
if is_msvc(self):
tc.extra_cflags.append("-FS")

env = tc.environment()
if is_msvc(self):
env.define("CC", "cl -nologo")
env.define("CXX", "cl -nologo")
tc.generate(env) # Create conanbuild.conf

def _extract_makefile_variable(self, makefile, variable):
makefile_contents = tools.load(makefile)
match = re.search("{}[ \t]*=[ \t]*((?:(?:[a-zA-Z0-9 \t.=/_-])|(?:\\\\\"))*(?:\\\\\n(?:(?:[a-zA-Z0-9 \t.=/_-])|(?:\\\"))*)*)\n".format(variable), makefile_contents)
makefile_contents = load(self, makefile)
match = re.search(f'{variable}[ \t]*=[ \t]*((?:(?:[a-zA-Z0-9 \t.=/_-])|(?:\\\\\"))*(?:\\\\\n(?:(?:[a-zA-Z0-9 \t.=/_-])|(?:\\\"))*)*)\n', makefile_contents)
if not match:
raise ConanException("Cannot extract variable {} from {}".format(variable, makefile_contents))
raise ConanException(f"Cannot extract variable {variable} from {makefile_contents}")
lines = [line.strip(" \t\\") for line in match.group(1).split()]
return [item for line in lines for item in shlex.split(line) if item]

def _extract_mpfr_autotools_variables(self):
makefile_am = os.path.join(self._source_subfolder, "src", "Makefile.am")
makefile_am = os.path.join(self.source_folder, "src", "Makefile.am") # src/src/Makefile.am
makefile = os.path.join("src", "Makefile")
sources = self._extract_makefile_variable(makefile_am, "libmpfr_la_SOURCES")
headers = self._extract_makefile_variable(makefile_am, "include_HEADERS")
defs = self._extract_makefile_variable(makefile, "DEFS")
return sources, headers, defs

@contextlib.contextmanager
def _build_context(self):
if self.settings.compiler == "Visual Studio":
with tools.vcvars(self):
env = {
"AR": "lib",
"CC": "cl -nologo",
"CXX": "cl -nologo",
"LD": "link",
"NM": "dumpbin -symbols",
"OBJDUMP": ":",
"RANLIB": ":",
"STRIP": ":",
}
with tools.environment_append(env):
yield
else:
yield

def build(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
tools.patch(**patch)
apply_conandata_patches(self)

if self.settings.os == "Windows": # Allow mixed shared and static libs
replace_in_file(self, os.path.join(self.source_folder, "configure"),
'as_fn_error $? "libgmp isn\'t provided as a DLL: use --enable-static --disable-shared" "$LINENO" 5',
'# as_fn_error $? "libgmp isn\'t provided as a DLL: use --enable-static --disable-shared" "$LINENO" 5')
replace_in_file(self, os.path.join(self.source_folder, "configure"),
'as_fn_error $? "libgmp is provided as a DLL: use --disable-static --enable-shared" "$LINENO" 5',
'# as_fn_error $? "libgmp is provided as a DLL: use --disable-static --enable-shared" "$LINENO" 5')

if self.options.exact_int == "mpir":
tools.replace_in_file(os.path.join(self._source_subfolder, "configure"),
replace_in_file(self, os.path.join(self.source_folder, "configure"),
"-lgmp", "-lmpir")
tools.replace_in_file(os.path.join(self._source_subfolder, "src", "mpfr.h"),
replace_in_file(self, os.path.join(self.source_folder, "src", "mpfr.h"),
"<gmp.h>", "<mpir.h>")
tools.save("gmp.h", "#pragma once\n#include <mpir.h>\n")
with self._build_context():
autotools = self._configure_autotools()
save(self, "gmp.h", "#pragma once\n#include <mpir.h>\n")

autotools = Autotools(self)
autotools.configure() # Need to generate Makefile to extract variables for CMake below

if self.settings.os == "Windows":
cmakelists_in = tools.load("CMakeLists.txt.in")
cmakelists_in = load(self, os.path.join(self.export_sources_folder, "CMakeLists.txt.in"))
sources, headers, definitions = self._extract_mpfr_autotools_variables()
tools.save(os.path.join(self._source_subfolder, "src", "CMakeLists.txt"), cmakelists_in.format(
sources = ["src/" + src for src in sources]
headers = ["src/" + hdr for hdr in headers]
save(self, os.path.join(self.source_folder, "CMakeLists.txt"), cmakelists_in.format(
mpfr_sources=" ".join(sources),
mpfr_headers=" ".join(headers),
definitions=" ".join(definitions),
))
cmake = self._configure_cmake()
cmake = CMake(self)
cmake.configure()
cmake.build()
else:
autotools.make(args=["V=0"])

def package(self):
self.copy("COPYING", dst="licenses", src=self._source_subfolder)
copy(self, "COPYING", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
if self.settings.os == "Windows":
cmake = self._configure_cmake()
cmake = CMake(self)
cmake.install()
else:
autotools = self._configure_autotools()
autotools = Autotools(self)
autotools.install()
fix_apple_shared_install_name(self)
os.unlink(os.path.join(self.package_folder, "lib", "libmpfr.la"))
tools.rmdir(os.path.join(self.package_folder, "share"))
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "share"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))

def package_info(self):
self.cpp_info.libs = ["mpfr"]
Expand Down
21 changes: 21 additions & 0 deletions recipes/mpfr/all/patches/4.0.2-0001-configure.ac-fixes.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--- configure.ac
+++ configure.ac
@@ -27,6 +27,7 @@

dnl Add check-news when it checks for more than 15 lines
AC_INIT([MPFR],[4.0.2])
+AC_CANONICAL_TARGET

dnl Older Automake versions than 1.13 may still be supported, but no longer
dnl tested, and many things have changed in 1.13. Moreover the INSTALL file

--- acinclude.m4
+++ acinclude.m4
@@ -41,7 +41,6 @@
AC_REQUIRE([AC_OBJEXT])
AC_REQUIRE([MPFR_CHECK_LIBM])
AC_REQUIRE([MPFR_CHECK_LIBQUADMATH])
-AC_REQUIRE([AC_HEADER_TIME])
AC_REQUIRE([AC_CANONICAL_HOST])

dnl Features for the MPFR shared cache. This needs to be done

This file was deleted.

22 changes: 22 additions & 0 deletions recipes/mpfr/all/patches/4.1.0-0001-configure.ac-fixes.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--- configure.ac
+++ configure.ac
@@ -27,6 +27,7 @@

dnl Add check-news when it checks for more than 15 lines
AC_INIT([MPFR],[4.1.0])
+AC_CANONICAL_TARGET

dnl Older Automake versions than 1.13 may still be supported, but no longer
dnl tested, and many things have changed in 1.13. Moreover the INSTALL file

--- acinclude.m4
+++ acinclude.m4
@@ -40,7 +40,6 @@
AC_REQUIRE([AC_OBJEXT])
AC_REQUIRE([MPFR_CHECK_LIBM])
AC_REQUIRE([MPFR_CHECK_LIBQUADMATH])
-AC_REQUIRE([AC_HEADER_TIME])
AC_REQUIRE([AC_CANONICAL_HOST])

dnl Features for the MPFR shared cache. This needs to be done

This file was deleted.

Loading

0 comments on commit 5a18d61

Please sign in to comment.