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

[gcc] Migrate recipe to conan v2, add gfortran to compilation #13896

Merged
Merged
Show file tree
Hide file tree
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
9 changes: 6 additions & 3 deletions recipes/gcc/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
sources:
"10.2.0":
sha256: 27e879dccc639cd7b0cc08ed575c1669492579529b53c9ff27b0b96265fa867d
url: https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.gz
"12.2.0":
sha256: ac6b317eb4d25444d87cf29c0d141dedc1323a1833ec9995211b13e1a851261c
url: https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.gz
samuel-emrys marked this conversation as resolved.
Show resolved Hide resolved
"11.3.0":
sha256: 98438e6cc7294298b474cf0da7655d9a8c8b796421bb0210531c294a950374ed
url: https://ftp.gnu.org/gnu/gcc/gcc-11.3.0/gcc-11.3.0.tar.gz
"10.2.0":
sha256: 27e879dccc639cd7b0cc08ed575c1669492579529b53c9ff27b0b96265fa867d
url: https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.gz
254 changes: 162 additions & 92 deletions recipes/gcc/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,126 +1,196 @@
from conans import ConanFile, tools, AutoToolsBuildEnvironment
from conans.errors import ConanException, ConanInvalidConfiguration
from conan import ConanFile
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.errors import ConanInvalidConfiguration
from conan.tools.layout import basic_layout
from conan.tools.apple import XCRun
from conan.tools.files import copy, get, replace_in_file, rmdir, rm
from conan.tools.build import cross_building
from conan.tools.env import VirtualBuildEnv
from conan.tools.microsoft import is_msvc
import os

required_conan_version = ">=1.29.1"
required_conan_version = ">=1.53.0"


class GccConan(ConanFile):
name = "gcc"
description = "The GNU Compiler Collection includes front ends for C, " \
"C++, Objective-C, Fortran, Ada, Go, and D, as well as " \
"libraries for these languages (libstdc++,...). "
description = (
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding package_type as recommended in Conan 2.0 documentation (see https://docs.conan.io/en/2.0/reference/conanfile/attributes.html?highlight=package_type#package-type)

package_type = "application"

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'd thought about this, but I think that there's also utility in exporting the libraries as well. Especially as it relates to gfortran, libgfortran is often required at link time for any generated executable, so I'm not sure it's feasible for this to be considered only an application package.

"The GNU Compiler Collection includes front ends for C, "
"C++, Objective-C, Fortran, Ada, Go, and D, as well as "
"libraries for these languages (libstdc++,...). "
)
topics = ("gcc", "gnu", "compiler", "c", "c++")
homepage = "https://gcc.gnu.org"
url = "https://github.com/conan-io/conan-center-index"
license = "GPL-3.0-only"
settings = "os", "compiler", "arch", "build_type"
_autotools = None

def build_requirements(self):
self.build_requires("flex/2.6.4")

def _configure_autotools(self):
if self._autotools:
return self._autotools
self._autotools = AutoToolsBuildEnvironment(self)
pkgversion = 'conan GCC %s' % self.version
bugurl = self.url + '/issues'
libdir = "%s/lib/gcc/%s" % (self.package_folder, self.version)
args = [
"--enable-languages=c,c++",
"--disable-nls",
"--disable-multilib",
"--disable-bootstrap",
"--with-system-zlib",
"--with-gmp=%s" % self.deps_cpp_info['gmp'].rootpath,
'--with-mpc=%s' % self.deps_cpp_info["mpc"].rootpath,
"--with-mpfr=%s" % self.deps_cpp_info["mpfr"].rootpath,
"--without-isl",
"--libdir=%s" % libdir,
'--with-pkgversion=%s' % pkgversion,
"--program-suffix=-%s" % self.version,
"--with-bugurl=%s" % bugurl
]
if self.settings.os == "Macos":
xcrun = tools.XCRun(self.settings)
args.extend([
'--with-native-system-header-dir=/usr/include',
"--with-sysroot={}".format(xcrun.sdk_path)
])
self._autotools.libs = [] # otherwise causes config.log to fail finding -lmpc
def configure(self):
if self.settings.compiler in ["clang", "apple-clang"]:
# xgcc: error: unrecognized command-line option -stdlib=libc++
if self.settings.compiler.libcxx == "libc++":
self._autotools.cxx_flags.remove("-stdlib=libc++")
elif self.settings.compiler.libcxx in ["libstdc++", "libstdc++11"]:
self._autotools.cxx_flags.remove("-stdlib=libstdc++")
self._autotools.configure(args=args, configure_dir=self._source_subfolder)
return self._autotools

@property
def _source_subfolder(self):
return "source_subfolder"
# Can't remove this from cxxflags with autotools - so get rid of it
samuel-emrys marked this conversation as resolved.
Show resolved Hide resolved
del self.settings.compiler.libcxx

def build_requirements(self):
if self.settings.os == "Linux":
# binutils recipe is broken for Macos, and Windows uses tools
# distributed with msys/mingw
self.tool_requires("binutils/2.38")
Copy link
Member

Choose a reason for hiding this comment

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

Broken how? Which tool is required? Need to consider user configuration too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the validation in the binutils recipe:

if self.options.target_os == "Macos":
raise ConanInvalidConfiguration("cci does not support building binutils for Macos since binutils is degraded there (no as/ld + armv8 does not build)")

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm unclear on what is driving the need to specify binutils as a build-time dependency for Linux. I was able to build fine without it. If there are conditions where it is needed, it would be nice to scope the dependency down to those circumstances. Also, the latest version of Conan 2.0 doesn't like the use of self.info.settings in the build_requirements method, so while my recommendation would be to eliminate this if-block altogether, at a minimum it likely needs to be changed to:

if self.settings.os == "Linux":

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You were able to build without it because there will be autodiscovery of the your system binutils, which should exist on all linux systems. This is here in the interest of explicitly modelling dependencies and moving away from a reliance on/contamination by your system executables. Specifically, binutils provides the assembler and linker for linux systems. On macos, the assembler and linker are provided by cctools (#14169). I think on windows these are bundled with the msys/mingw subsystems.

This allows a user to specify/override the version of binutils being used explicitly to control the binaries used independently of what's installed on your system.

self.tool_requires("flex/2.6.4")

def requirements(self):
self.requires("mpc/1.2.0")
self.requires("mpfr/4.1.0")
self.requires("gmp/6.2.0")
self.requires("zlib/1.2.11")
self.requires("gmp/6.2.1")
self.requires("zlib/1.2.13")
self.requires("isl/0.24")

def configure(self):
if self.settings.os == "Windows":
raise ConanInvalidConfiguration("Windows builds aren't supported (yet), sorry")
if tools.cross_building(self.settings):
raise ConanInvalidConfiguration("no cross-building support (yet), sorry")
def package_id(self):
del self.info.settings.compiler

def source(self):
tools.get(**self.conan_data["sources"][self.version])
extracted_dir = "gcc-%s" % self.version
os.rename(extracted_dir, self._source_subfolder)
def validate_build(self):
if is_msvc(self):
raise ConanInvalidConfiguration("GCC can't be built with MSVC")

@property
def _make_args(self):
def validate(self):
if self.settings.os == "Windows":
raise ConanInvalidConfiguration(
"Windows builds aren't currently supported. Contributions to support this are welcome."
)
if self.settings.os == "Macos":
return ["BOOT_LDFLAGS=-Wl,-headerpad_max_install_names"]
return []
# FIXME: This recipe should largely support Macos, however the following
# errors are present when building using the c3i CI:
# clang: error: unsupported option '-print-multi-os-directory'
# clang: error: no input files
raise ConanInvalidConfiguration(
"Macos builds aren't currently supported. Contributions to support this are welcome."
)
if cross_building(self):
raise ConanInvalidConfiguration(
"Cross builds are not current supported. Contributions to support this are welcome"
)

def layout(self):
basic_layout(self, src_folder="src")

def generate(self):
# Ensure binutils and flex are on the path.
# TODO: Remove when conan 2.0 is released as this will be default behaviour
buildenv = VirtualBuildEnv(self)
buildenv.generate()

tc = AutotoolsToolchain(self)
tc.configure_args.append("--enable-languages=c,c++,fortran")
tc.configure_args.append("--disable-nls")
tc.configure_args.append("--disable-multilib")
tc.configure_args.append("--disable-bootstrap")
# TODO: Remove --prefix and --libexecdir args when c3i supports conan 1.55.0.
# This change should only happen in conjunction with a move to
# autotools.install("install-strip")
tc.configure_args.append(f"--prefix={self.package_folder}")
samuel-emrys marked this conversation as resolved.
Show resolved Hide resolved
tc.configure_args.append(f"--libexecdir={os.path.join(self.package_folder, 'bin', 'libexec')}")
tc.configure_args.append(f"--with-zlib={self.dependencies['zlib'].package_folder}")
tc.configure_args.append(f"--with-isl={self.dependencies['isl'].package_folder}")
tc.configure_args.append(f"--with-gmp={self.dependencies['gmp'].package_folder}")
tc.configure_args.append(f"--with-mpc={self.dependencies['mpc'].package_folder}")
tc.configure_args.append(f"--with-mpfr={self.dependencies['mpfr'].package_folder}")
tc.configure_args.append(f"--with-pkgversion=conan GCC {self.version}")
tc.configure_args.append(f"--program-suffix=-{self.version}")
tc.configure_args.append(f"--with-bugurl={self.url}/issues")

if self.settings.os == "Macos":
xcrun = XCRun(self)
tc.configure_args.append(f"--with-sysroot={xcrun.sdk_path}")
# Set native system header dir to ${{sysroot}}/usr/include to
# isolate installation from the system as much as possible
tc.configure_args.append("--with-native-system-header-dir=/usr/include")
tc.make_args.append("BOOT_LDFLAGS=-Wl,-headerpad_max_install_names")
tc.generate()

# Don't use AutotoolsDeps here - deps are passed directly in configure_args.
# Using AutotoolsDeps causes the compiler tests to fail by erroneously adding
# additional $LIBS to the test compilation

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

def build(self):
# If building on x86_64, change the default directory name for 64-bit libraries to "lib":
libdir = "%s/lib/gcc/%s" % (self.package_folder, self.version)
tools.replace_in_file(os.path.join(self.source_folder,
self._source_subfolder, "gcc", "config", "i386", "t-linux64"),
"m64=../lib64", "m64=../lib", strict=False)
replace_in_file(
self,
os.path.join(self.source_folder, "gcc", "config", "i386", "t-linux64"),
"m64=../lib64",
"m64=../lib",
strict=False,
)

# Ensure correct install names when linking against libgcc_s;
# see discussion in https://github.com/Homebrew/legacy-homebrew/pull/34303
tools.replace_in_file(os.path.join(self.source_folder,
self._source_subfolder, "libgcc", "config", "t-slibgcc-darwin"),
"@shlib_slibdir@", libdir, strict=False)
autotools = self._configure_autotools()
autotools.make(args=self._make_args)

def package_id(self):
del self.info.settings.compiler
replace_in_file(
self,
os.path.join(self.source_folder, "libgcc", "config", "t-slibgcc-darwin"),
"@shlib_slibdir@",
os.path.join(self.package_folder, "lib"),
strict=False,
)

autotools = Autotools(self)
autotools.configure()
autotools.make()

def package(self):
autotools = self._configure_autotools()
if self.settings.build_type == "Debug":
autotools.install(args=self._make_args)
else:
autotools.make(args=["install-strip"] + self._make_args)
tools.rmdir(os.path.join(self.package_folder, "share"))
tools.remove_files_by_mask(self.package_folder, "*.la")
self.copy(pattern="COPYING*", dst="licenses", src=self._source_subfolder)
autotools = Autotools(self)
# TODO: Use more modern autotools.install(target="install-strip") when c3i supports
# conan client version of 1.55.0. Make sure that the minimum conan version is also bumped
# when this is changed.
autotools.make(target="install-strip")
samuel-emrys marked this conversation as resolved.
Show resolved Hide resolved

rmdir(self, os.path.join(self.package_folder, "share"))
rm(self, "*.la", self.package_folder, recursive=True)
copy(
self,
pattern="COPYING*",
dst=os.path.join(self.package_folder, "licenses"),
src=self.source_folder,
keep_path=False,
)

def package_info(self):
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.append("m")
self.cpp_info.system_libs.append("rt")
self.cpp_info.system_libs.append("pthread")
self.cpp_info.system_libs.append("dl")

bindir = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH env var with : " + bindir)
self.env_info.PATH.append(bindir)

cc = os.path.join(bindir, "gcc-%s" % self.version)
self.output.info("Creating CC env var with : " + cc)
self.env_info.CC = cc
cc = os.path.join(bindir, f"gcc-{self.version}")
samuel-emrys marked this conversation as resolved.
Show resolved Hide resolved
self.output.info("Creating CC env var with: " + cc)
self.buildenv_info.define("CC", cc)

cxx = os.path.join(bindir, "g++-%s" % self.version)
self.output.info("Creating CXX env var with : " + cxx)
cxx = os.path.join(bindir, f"g++-{self.version}")
self.output.info("Creating CXX env var with: " + cxx)
self.buildenv_info.define("CXX", cxx)

fc = os.path.join(bindir, f"gfortran-{self.version}")
self.output.info("Creating FC env var with: " + fc)
self.buildenv_info.define("FC", fc)

ar = os.path.join(bindir, f"gcc-ar-{self.version}")
self.output.info("Creating AR env var with: " + ar)
self.buildenv_info.define("AR", ar)

nm = os.path.join(bindir, f"gcc-nm-{self.version}")
self.output.info("Creating NM env var with: " + nm)
self.buildenv_info.define("NM", nm)

ranlib = os.path.join(bindir, f"gcc-ranlib-{self.version}")
self.output.info("Creating RANLIB env var with: " + ranlib)
self.buildenv_info.define("RANLIB", ranlib)

# TODO: Remove after conan 2.0 is released
self.env_info.CC = cc
self.env_info.CXX = cxx
self.env_info.FC = fc
self.env_info.AR = ar
self.env_info.NM = nm
self.env_info.RANLIB = ranlib
Loading