Skip to content

Commit 2218a5b

Browse files
committed
[gcc] Migrate to conan v2, add fortran
* Migrate gcc recipe to conan v2 * Add fortran as an enabled language to ensure that gfortran is built * Add binutils as a build_requires to remove dependency on system binaries * Refactor package test to ensure that the package compilers are under test and not the system compilers * Add fortran test binary * Export environment variables in the buildenv for gcc, g++, gfortran, ar, nm, ranlib
1 parent 8eabe5f commit 2218a5b

File tree

10 files changed

+262
-125
lines changed

10 files changed

+262
-125
lines changed

recipes/gcc/all/conandata.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
sources:
2-
"10.2.0":
3-
sha256: 27e879dccc639cd7b0cc08ed575c1669492579529b53c9ff27b0b96265fa867d
4-
url: https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.gz
52
"12.2.0":
63
sha256: ac6b317eb4d25444d87cf29c0d141dedc1323a1833ec9995211b13e1a851261c
74
url: https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.gz
5+
"10.2.0":
6+
sha256: 27e879dccc639cd7b0cc08ed575c1669492579529b53c9ff27b0b96265fa867d
7+
url: https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.gz

recipes/gcc/all/conanfile.py

Lines changed: 129 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,162 @@
1-
from conans import ConanFile, tools, AutoToolsBuildEnvironment
2-
from conans.errors import ConanException, ConanInvalidConfiguration
1+
from conan import ConanFile
2+
from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps
3+
from conan.errors import ConanInvalidConfiguration
4+
from conan.tools.layout import basic_layout
5+
from conan.tools.apple import XCRun
6+
from conan.tools.files import copy, get, replace_in_file, rmdir, rm
7+
from conan.tools.build import cross_building
8+
from conan.tools.env import VirtualBuildEnv
39
import os
410

5-
required_conan_version = ">=1.29.1"
11+
required_conan_version = ">=1.53.0"
612

713

814
class GccConan(ConanFile):
915
name = "gcc"
10-
description = "The GNU Compiler Collection includes front ends for C, " \
11-
"C++, Objective-C, Fortran, Ada, Go, and D, as well as " \
12-
"libraries for these languages (libstdc++,...). "
16+
description = (
17+
"The GNU Compiler Collection includes front ends for C, "
18+
"C++, Objective-C, Fortran, Ada, Go, and D, as well as "
19+
"libraries for these languages (libstdc++,...). "
20+
)
1321
topics = ("gcc", "gnu", "compiler", "c", "c++")
1422
homepage = "https://gcc.gnu.org"
1523
url = "https://github.com/conan-io/conan-center-index"
1624
license = "GPL-3.0-only"
1725
settings = "os", "compiler", "arch", "build_type"
18-
_autotools = None
1926

20-
def build_requirements(self):
21-
self.build_requires("flex/2.6.4")
22-
23-
def _configure_autotools(self):
24-
if self._autotools:
25-
return self._autotools
26-
self._autotools = AutoToolsBuildEnvironment(self)
27-
pkgversion = 'conan GCC %s' % self.version
28-
bugurl = self.url + '/issues'
29-
libdir = "%s/lib/gcc/%s" % (self.package_folder, self.version)
30-
args = [
31-
"--enable-languages=c,c++",
32-
"--disable-nls",
33-
"--disable-multilib",
34-
"--disable-bootstrap",
35-
"--with-system-zlib",
36-
"--with-gmp=%s" % self.deps_cpp_info['gmp'].rootpath,
37-
'--with-mpc=%s' % self.deps_cpp_info["mpc"].rootpath,
38-
"--with-mpfr=%s" % self.deps_cpp_info["mpfr"].rootpath,
39-
"--without-isl",
40-
"--libdir=%s" % libdir,
41-
'--with-pkgversion=%s' % pkgversion,
42-
"--program-suffix=-%s" % self.version,
43-
"--with-bugurl=%s" % bugurl
44-
]
45-
if self.settings.os == "Macos":
46-
xcrun = tools.XCRun(self.settings)
47-
args.extend([
48-
'--with-native-system-header-dir=/usr/include',
49-
"--with-sysroot={}".format(xcrun.sdk_path)
50-
])
51-
self._autotools.libs = [] # otherwise causes config.log to fail finding -lmpc
27+
def configure(self):
5228
if self.settings.compiler in ["clang", "apple-clang"]:
53-
# xgcc: error: unrecognized command-line option -stdlib=libc++
54-
if self.settings.compiler.libcxx == "libc++":
55-
self._autotools.cxx_flags.remove("-stdlib=libc++")
56-
elif self.settings.compiler.libcxx in ["libstdc++", "libstdc++11"]:
57-
self._autotools.cxx_flags.remove("-stdlib=libstdc++")
58-
self._autotools.configure(args=args, configure_dir=self._source_subfolder)
59-
return self._autotools
60-
61-
@property
62-
def _source_subfolder(self):
63-
return "source_subfolder"
29+
# Can't remove this from cxxflags with autotools - so get rid of it
30+
del self.settings.compiler.libcxx
31+
32+
def build_requirements(self):
33+
self.tool_requires("binutils/2.38")
34+
self.tool_requires("flex/2.6.4")
6435

6536
def requirements(self):
6637
self.requires("mpc/1.2.0")
6738
self.requires("mpfr/4.1.0")
68-
self.requires("gmp/6.2.0")
69-
self.requires("zlib/1.2.11")
39+
self.requires("gmp/6.2.1")
40+
self.requires("zlib/1.2.12")
41+
self.requires("isl/0.24")
7042

71-
def configure(self):
72-
if self.settings.os == "Windows":
73-
raise ConanInvalidConfiguration("Windows builds aren't supported (yet), sorry")
74-
if tools.cross_building(self.settings):
43+
def package_id(self):
44+
del self.info.settings.compiler
45+
46+
def validate(self):
47+
if self.info.settings.os == "Windows":
48+
raise ConanInvalidConfiguration(
49+
"Windows builds aren't supported (yet), sorry"
50+
)
51+
if cross_building(self):
7552
raise ConanInvalidConfiguration("no cross-building support (yet), sorry")
7653

77-
def source(self):
78-
tools.get(**self.conan_data["sources"][self.version])
79-
extracted_dir = "gcc-%s" % self.version
80-
os.rename(extracted_dir, self._source_subfolder)
54+
def layout(self):
55+
basic_layout(self, src_folder="source")
56+
57+
def generate(self):
58+
# Ensure binutils and flex are on the path
59+
buildenv = VirtualBuildEnv(self)
60+
buildenv.generate()
61+
62+
tc = AutotoolsToolchain(self)
63+
tc.configure_args.append("--enable-languages=c,c++,fortran")
64+
tc.configure_args.append("--disable-nls")
65+
tc.configure_args.append("--disable-multilib")
66+
tc.configure_args.append("--disable-bootstrap")
67+
tc.configure_args.append("--with-system-zlib")
68+
tc.configure_args.append(f"--prefix={self.package_folder}")
69+
tc.configure_args.append(f"--with-isl={self.deps_cpp_info['isl'].rootpath}")
70+
tc.configure_args.append(f"--with-gmp={self.deps_cpp_info['gmp'].rootpath}")
71+
tc.configure_args.append(f"--with-mpc={self.deps_cpp_info['mpc'].rootpath}")
72+
tc.configure_args.append(f"--with-mpfr={self.deps_cpp_info['mpfr'].rootpath}")
73+
tc.configure_args.append(f"--with-pkgversion=conan GCC {self.version}")
74+
tc.configure_args.append(f"--program-suffix=-{self.version}")
75+
tc.configure_args.append(f"--with-bugurl={self.url}/issues")
76+
77+
if self.info.settings.os == "Macos":
78+
xcrun = XCRun(self.settings)
79+
tc.configure_args.append("--with-native-system-header-dir=/usr/include")
80+
tc.configure_args.append(f"--with-sysroot={xcrun.sdk_path}")
81+
tc.make_args.append("BOOT_LDFLAGS=-Wl")
82+
tc.make_args.append("-headerpad_max_install_names")
83+
tc.generate()
84+
85+
deps = AutotoolsDeps(self)
86+
deps.generate()
8187

82-
@property
83-
def _make_args(self):
84-
if self.settings.os == "Macos":
85-
return ["BOOT_LDFLAGS=-Wl,-headerpad_max_install_names"]
86-
return []
88+
def source(self):
89+
get(self, **self.conan_data["sources"][self.version], strip_root=True)
8790

8891
def build(self):
8992
# If building on x86_64, change the default directory name for 64-bit libraries to "lib":
90-
libdir = "%s/lib/gcc/%s" % (self.package_folder, self.version)
91-
tools.replace_in_file(os.path.join(self.source_folder,
92-
self._source_subfolder, "gcc", "config", "i386", "t-linux64"),
93-
"m64=../lib64", "m64=../lib", strict=False)
93+
replace_in_file(
94+
self,
95+
os.path.join(self.source_folder, "gcc", "config", "i386", "t-linux64"),
96+
"m64=../lib64",
97+
"m64=../lib",
98+
strict=False,
99+
)
100+
94101
# Ensure correct install names when linking against libgcc_s;
95102
# see discussion in https://github.com/Homebrew/legacy-homebrew/pull/34303
96-
tools.replace_in_file(os.path.join(self.source_folder,
97-
self._source_subfolder, "libgcc", "config", "t-slibgcc-darwin"),
98-
"@shlib_slibdir@", libdir, strict=False)
99-
autotools = self._configure_autotools()
100-
autotools.make(args=self._make_args)
101-
102-
def package_id(self):
103-
del self.info.settings.compiler
103+
replace_in_file(
104+
self,
105+
os.path.join(self.source_folder, "libgcc", "config", "t-slibgcc-darwin"),
106+
"@shlib_slibdir@",
107+
os.path.join(self.package_folder, "lib"),
108+
strict=False,
109+
)
110+
111+
autotools = Autotools(self)
112+
autotools.configure()
113+
autotools.make()
104114

105115
def package(self):
106-
autotools = self._configure_autotools()
107-
if self.settings.build_type == "Debug":
108-
autotools.install(args=self._make_args)
109-
else:
110-
autotools.make(args=["install-strip"] + self._make_args)
111-
tools.rmdir(os.path.join(self.package_folder, "share"))
112-
tools.remove_files_by_mask(self.package_folder, "*.la")
113-
self.copy(pattern="COPYING*", dst="licenses", src=self._source_subfolder)
116+
autotools = Autotools(self)
117+
autotools.make(target="install-strip")
118+
119+
rmdir(self, os.path.join(self.package_folder, "share"))
120+
rm(self, "*.la", self.package_folder, recursive=True)
121+
copy(
122+
self,
123+
pattern="COPYING*",
124+
dst=os.path.join(self.package_folder, "licenses"),
125+
src=self.source_folder,
126+
keep_path=False,
127+
)
114128

115129
def package_info(self):
130+
if self.info.settings.os in ["Linux", "FreeBSD"]:
131+
self.cpp_info.system_libs.append("m")
132+
self.cpp_info.system_libs.append("rt")
133+
self.cpp_info.system_libs.append("pthread")
134+
self.cpp_info.system_libs.append("dl")
135+
116136
bindir = os.path.join(self.package_folder, "bin")
117-
self.output.info("Appending PATH env var with : " + bindir)
118-
self.env_info.PATH.append(bindir)
137+
self.output.info("Prepending PATH env var with: " + bindir)
138+
self.buildenv_info.prepend_path("PATH", bindir)
139+
140+
cc = os.path.join(bindir, f"gcc-{self.version}")
141+
self.output.info("Creating CC env var with: " + cc)
142+
self.buildenv_info.define("CC", cc)
143+
144+
cxx = os.path.join(bindir, f"g++-{self.version}")
145+
self.output.info("Creating CXX env var with: " + cxx)
146+
self.buildenv_info.define("CXX", cxx)
147+
148+
fc = os.path.join(bindir, f"gfortran-{self.version}")
149+
self.output.info("Creating FC env var with: " + fc)
150+
self.buildenv_info.define("FC", fc)
151+
152+
ar = os.path.join(bindir, f"gcc-ar-{self.version}")
153+
self.output.info("Creating AR env var with: " + ar)
154+
self.buildenv_info.define("AR", ar)
119155

120-
cc = os.path.join(bindir, "gcc-%s" % self.version)
121-
self.output.info("Creating CC env var with : " + cc)
122-
self.env_info.CC = cc
156+
nm = os.path.join(bindir, f"gcc-nm-{self.version}")
157+
self.output.info("Creating NM env var with: " + nm)
158+
self.buildenv_info.define("NM", nm)
123159

124-
cxx = os.path.join(bindir, "g++-%s" % self.version)
125-
self.output.info("Creating CXX env var with : " + cxx)
126-
self.env_info.CXX = cxx
160+
ranlib = os.path.join(bindir, f"gcc-ranlib-{self.version}")
161+
self.output.info("Creating RANLIB env var with: " + ranlib)
162+
self.buildenv_info.define("RANLIB", ranlib)
Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,81 @@
1-
from conans import ConanFile, tools
21
import os
2+
import shutil
3+
from conan import ConanFile
4+
from conan.tools.build import cross_building
5+
from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
36

47

5-
class TestPackageConan(ConanFile):
8+
class GccTestConan(ConanFile):
69
settings = "os", "compiler", "build_type", "arch"
7-
generators = "cmake"
10+
11+
@property
12+
def file_io(self):
13+
return {
14+
"c": {
15+
"compiler": "$CC",
16+
"src": os.path.join(self.source_folder, "hello.c"),
17+
"bin": os.path.join(self.build_folder, "hello_c"),
18+
},
19+
"cpp": {
20+
"compiler": "$CXX",
21+
"src": os.path.join(self.source_folder, "hello.cpp"),
22+
"bin": os.path.join(self.build_folder, "hello_cpp"),
23+
},
24+
"fortran": {
25+
"compiler": "$FC",
26+
"src": os.path.join(self.source_folder, "hello.f90"),
27+
"bin": os.path.join(self.build_folder, "hello_f90"),
28+
},
29+
}
30+
31+
def generate(self):
32+
buildenv = VirtualBuildEnv(self)
33+
buildenv.generate()
34+
35+
runenv = VirtualRunEnv(self)
36+
runenv.generate()
37+
38+
def build(self):
39+
self.run("echo PATH: $PATH")
40+
for language, files in self.file_io.items():
41+
self.output.info(f"Testing build using {language} compiler")
42+
# Confirm compiler is propagated to env
43+
envvar = files["compiler"].split("$")[1]
44+
self.run(f"echo {envvar}: {files['compiler']}", env="conanbuild")
45+
self.run(f"{files['compiler']} --version", env="conanbuild")
46+
self.run(f"{files['compiler']} -dumpversion", env="conanbuild")
47+
48+
# Confirm files can be compiled
49+
self.run(
50+
f"{files['compiler']} {files['src']} -o {files['bin']}",
51+
env="conanbuild",
52+
)
53+
self.output.info(f"Successfully built {files['bin']}")
854

955
def test(self):
1056
def chmod_plus_x(name):
11-
if os.name == 'posix':
57+
if os.name == "posix":
1258
os.chmod(name, os.stat(name).st_mode | 0o111)
1359

14-
cc = self.deps_env_info["gcc"].CC
15-
cxx = self.deps_env_info["gcc"].CXX
16-
hello_c = os.path.join(self.source_folder, "hello.c")
17-
hello_cpp = os.path.join(self.source_folder, "hello.cpp")
18-
self.run("%s --version" % cc, run_environment=True)
19-
self.run("%s --version" % cxx, run_environment=True)
20-
self.run("%s -dumpversion" % cc, run_environment=True)
21-
self.run("%s -dumpversion" % cxx, run_environment=True)
22-
self.run("%s %s -o hello_c" % (cc, hello_c), run_environment=True)
23-
self.run("%s %s -o hello_cpp" % (cxx, hello_cpp), run_environment=True)
24-
if not tools.cross_building(self.settings):
25-
chmod_plus_x("hello_c")
26-
chmod_plus_x("hello_cpp")
27-
self.run("./hello_c", run_environment=True)
28-
self.run("./hello_cpp", run_environment=True)
29-
if tools.which("readelf"):
30-
self.run("readelf -l hello_c", run_environment=True)
31-
self.run("readelf -l hello_cpp", run_environment=True)
32-
if tools.which("otool"):
33-
self.run("otool -L hello_c", run_environment=True)
34-
self.run("otool -L hello_cpp", run_environment=True)
60+
for language, files in self.file_io.items():
61+
self.output.info(f"Testing application built using {language} compiler")
62+
if not cross_building(self):
63+
chmod_plus_x(f"{files['bin']}")
64+
65+
if self.settings.os == "Linux":
66+
if shutil.which("readelf"):
67+
self.run(f"readelf -l {files['bin']}", env="conanrun")
68+
else:
69+
self.output.info(
70+
"readelf is not on the PATH. Skipping readelf test."
71+
)
72+
73+
if self.settings.os == "Macos":
74+
if shutil.which("otool"):
75+
self.run(f"otool -L {files['bin']}", env="conanrun")
76+
else:
77+
self.output.info(
78+
"otool is not on the PATH. Skipping otool test."
79+
)
80+
81+
self.run(f"{files['bin']}", env="conanrun")

recipes/gcc/all/test_package/hello.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
int main()
44
{
5-
puts("Hello, World!\n");
5+
puts(" gcc: Hello, World!");
66
return 0;
77
}
88

recipes/gcc/all/test_package/hello.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
int main()
44
{
5-
std::cout << "Hello, World!\n";
5+
std::cout << " g++: Hello, World!\n";
66
return 0;
77
}
88

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
program hello
2+
implicit none
3+
write(*,*) 'gfortran: Hello, World!'
4+
end program hello

0 commit comments

Comments
 (0)