-
-
Notifications
You must be signed in to change notification settings - Fork 12.6k
/
Copy pathgcc.rb
281 lines (234 loc) · 10.1 KB
/
gcc.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
class Gcc < Formula
desc "GNU compiler collection"
homepage "https://gcc.gnu.org/"
license "GPL-3.0-or-later" => { with: "GCC-exception-3.1" }
head "https://gcc.gnu.org/git/gcc.git", branch: "master"
stable do
url "https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.xz"
mirror "https://ftpmirror.gnu.org/gcc/gcc-12.2.0/gcc-12.2.0.tar.xz"
sha256 "e549cf9cf3594a00e27b6589d4322d70e0720cdd213f39beb4181e06926230ff"
# Branch from the Darwin maintainer of GCC, with a few generic fixes and
# Apple Silicon support, located at https://github.com/iains/gcc-12-branch
patch do
url "https://raw.githubusercontent.com/Homebrew/formula-patches/1d184289/gcc/gcc-12.2.0-arm.diff"
sha256 "a7843b5c6bf1401e40c20c72af69c8f6fc9754ae980bb4a5f0540220b3dcb62d"
end
end
livecheck do
url :stable
regex(%r{href=["']?gcc[._-]v?(\d+(?:\.\d+)+)(?:/?["' >]|\.t)}i)
end
bottle do
rebuild 2
sha256 arm64_ventura: "d0dd262f7d681d5bbcc39bea85d0dd355f2f962060afe4de16432fbe9596bf8c"
sha256 arm64_monterey: "7bc86ca650f1e2764ed66e6c46852c035a336de89e1a373b6447e3980a4c0d8d"
sha256 arm64_big_sur: "2d450754fbe7125c9a1e30f8f865fdbd7f3adc730d2c6459fb43256f7bba9042"
sha256 ventura: "85b24fd8be088fd53cbf596fb98f77d616598e6410e4e48df7b61faf6b41f126"
sha256 monterey: "0b47a35b2d5405a3b414435b7c00875d349107a8f3f7471088ff183f62a57247"
sha256 big_sur: "7f97476baa2573f5f8df510b47f4ff5ce725622d1b57f4771b896b1b70d02ddb"
sha256 catalina: "6ba7396b412441e59eec2b67a349f3f5f7374a9b772eb33e0c4707f6c77f5bc0"
sha256 cellar: :any_skip_relocation, x86_64_linux: "d2080ede63b45e711bbb05c474af6affe3edc255fecf81009a85e23429b509e2"
end
# The bottles are built on systems with the CLT installed, and do not work
# out of the box on Xcode-only systems due to an incorrect sysroot.
pour_bottle? only_if: :clt_installed
depends_on "gmp"
depends_on "isl"
depends_on "libmpc"
depends_on "mpfr"
depends_on "zstd"
uses_from_macos "zlib"
on_linux do
depends_on "binutils"
end
# GCC bootstraps itself, so it is OK to have an incompatible C++ stdlib
cxxstdlib_check :skip
def version_suffix
if build.head?
"HEAD"
else
version.major.to_s
end
end
def install
# GCC will suffer build errors if forced to use a particular linker.
ENV.delete "LD"
# We avoiding building:
# - Ada and D, which require a pre-existing GCC to bootstrap
# - Go, currently not supported on macOS
# - BRIG
languages = %w[c c++ objc obj-c++ fortran]
pkgversion = "Homebrew GCC #{pkg_version} #{build.used_options*" "}".strip
# Use `lib/gcc/current` to provide a path that doesn't change with GCC's version.
args = %W[
--prefix=#{opt_prefix}
--libdir=#{opt_lib}/gcc/current
--disable-nls
--enable-checking=release
--with-gcc-major-version-only
--enable-languages=#{languages.join(",")}
--program-suffix=-#{version_suffix}
--with-gmp=#{Formula["gmp"].opt_prefix}
--with-mpfr=#{Formula["mpfr"].opt_prefix}
--with-mpc=#{Formula["libmpc"].opt_prefix}
--with-isl=#{Formula["isl"].opt_prefix}
--with-zstd=#{Formula["zstd"].opt_prefix}
--with-pkgversion=#{pkgversion}
--with-bugurl=#{tap.issues_url}
--with-system-zlib
]
if OS.mac?
cpu = Hardware::CPU.arm? ? "aarch64" : "x86_64"
args << "--build=#{cpu}-apple-darwin#{OS.kernel_version.major}"
# System headers may not be in /usr/include
sdk = MacOS.sdk_path_if_needed
args << "--with-sysroot=#{sdk}" if sdk
else
# Fix cc1: error while loading shared libraries: libisl.so.15
args << "--with-boot-ldflags=-static-libstdc++ -static-libgcc #{ENV.ldflags}"
# Fix Linux error: gnu/stubs-32.h: No such file or directory.
args << "--disable-multilib"
# Enable to PIE by default to match what the host GCC uses
args << "--enable-default-pie"
# Change the default directory name for 64-bit libraries to `lib`
# https://stackoverflow.com/a/54038769
inreplace "gcc/config/i386/t-linux64", "m64=../lib64", "m64="
end
mkdir "build" do
system "../configure", *args
system "make"
# Do not strip the binaries on macOS, it makes them unsuitable
# for loading plugins
install_target = OS.mac? ? "install" : "install-strip"
# To make sure GCC does not record cellar paths, we configure it with
# opt_prefix as the prefix. Then we use DESTDIR to install into a
# temporary location, then move into the cellar path.
system "make", install_target, "DESTDIR=#{Pathname.pwd}/../instdir"
mv Dir[Pathname.pwd/"../instdir/#{opt_prefix}/*"], prefix
end
bin.install_symlink bin/"gfortran-#{version_suffix}" => "gfortran"
# Provide a `lib/gcc/xy` directory to align with the versioned GCC formulae.
# We need to create `lib/gcc/xy` as a directory and not a symlink to avoid `brew link` conflicts.
(lib/"gcc"/version_suffix).install_symlink (lib/"gcc/current").children
# Only the newest brewed gcc should install gfortan libs as we can only have one.
lib.install_symlink lib.glob("gcc/current/libgfortran.*") if OS.linux?
# Handle conflicts between GCC formulae and avoid interfering
# with system compilers.
# Rename man7.
man7.glob("*.7") { |file| add_suffix file, version_suffix }
# Even when we disable building info pages some are still installed.
info.rmtree
# Work around GCC install bug
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105664
rm_rf bin.glob("*-gcc-tmp")
end
def add_suffix(file, suffix)
dir = File.dirname(file)
ext = File.extname(file)
base = File.basename(file, ext)
File.rename file, "#{dir}/#{base}-#{suffix}#{ext}"
end
def post_install
if OS.linux?
gcc = bin/"gcc-#{version_suffix}"
libgcc = Pathname.new(Utils.safe_popen_read(gcc, "-print-libgcc-file-name")).parent
raise "command failed: #{gcc} -print-libgcc-file-name" if $CHILD_STATUS.exitstatus.nonzero?
glibc = Formula["glibc"]
glibc_installed = glibc.any_version_installed?
# Symlink system crt1.o and friends where gcc can find it.
crtdir = if glibc_installed
glibc.opt_lib
else
Pathname.new(Utils.safe_popen_read("/usr/bin/cc", "-print-file-name=crti.o")).parent
end
ln_sf Dir[crtdir/"*crt?.o"], libgcc
# Create the GCC specs file
# See https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html
# Locate the specs file
specs = libgcc/"specs"
ohai "Creating the GCC specs file: #{specs}"
specs_orig = Pathname.new("#{specs}.orig")
rm_f [specs_orig, specs]
system_header_dirs = ["#{HOMEBREW_PREFIX}/include"]
if glibc_installed
# https://github.com/Linuxbrew/brew/issues/724
system_header_dirs << glibc.opt_include
else
# Locate the native system header dirs if user uses system glibc
target = Utils.safe_popen_read(gcc, "-print-multiarch").chomp
raise "command failed: #{gcc} -print-multiarch" if $CHILD_STATUS.exitstatus.nonzero?
system_header_dirs += ["/usr/include/#{target}", "/usr/include"]
end
# Save a backup of the default specs file
specs_string = Utils.safe_popen_read(gcc, "-dumpspecs")
raise "command failed: #{gcc} -dumpspecs" if $CHILD_STATUS.exitstatus.nonzero?
specs_orig.write specs_string
# Set the library search path
# For include path:
# * `-isysroot #{HOMEBREW_PREFIX}/nonexistent` prevents gcc searching built-in
# system header files.
# * `-idirafter <dir>` instructs gcc to search system header
# files after gcc internal header files.
# For libraries:
# * `-nostdlib -L#{libgcc} -L#{glibc.opt_lib}` instructs gcc to use
# brewed glibc if applied.
# * `-L#{libdir}` instructs gcc to find the corresponding gcc
# libraries. It is essential if there are multiple brewed gcc
# with different versions installed.
# Noted that it should only be passed for the `gcc@*` formulae.
# * `-L#{HOMEBREW_PREFIX}/lib` instructs gcc to find the rest
# brew libraries.
# Note: *link will silently add #{libdir} first to the RPATH
libdir = HOMEBREW_PREFIX/"lib/gcc/current"
specs.write specs_string + <<~EOS
*cpp_unique_options:
+ -isysroot #{HOMEBREW_PREFIX}/nonexistent #{system_header_dirs.map { |p| "-idirafter #{p}" }.join(" ")}
*link_libgcc:
#{glibc_installed ? "-nostdlib -L#{libgcc} -L#{glibc.opt_lib}" : "+"} -L#{libdir} -L#{HOMEBREW_PREFIX}/lib
*link:
+ --dynamic-linker #{HOMEBREW_PREFIX}/lib/ld.so -rpath #{libdir}
*homebrew_rpath:
-rpath #{HOMEBREW_PREFIX}/lib
EOS
inreplace(specs, " %o ", "\\0%(homebrew_rpath) ")
end
end
test do
(testpath/"hello-c.c").write <<~EOS
#include <stdio.h>
int main()
{
puts("Hello, world!");
return 0;
}
EOS
system "#{bin}/gcc-#{version_suffix}", "-o", "hello-c", "hello-c.c"
assert_equal "Hello, world!\n", shell_output("./hello-c")
(testpath/"hello-cc.cc").write <<~EOS
#include <iostream>
struct exception { };
int main()
{
std::cout << "Hello, world!" << std::endl;
try { throw exception{}; }
catch (exception) { }
catch (...) { }
return 0;
}
EOS
system "#{bin}/g++-#{version_suffix}", "-o", "hello-cc", "hello-cc.cc"
assert_equal "Hello, world!\n", shell_output("./hello-cc")
(testpath/"test.f90").write <<~EOS
integer,parameter::m=10000
real::a(m), b(m)
real::fact=0.5
do concurrent (i=1:m)
a(i) = a(i) + fact*b(i)
end do
write(*,"(A)") "Done"
end
EOS
system "#{bin}/gfortran", "-o", "test", "test.f90"
assert_equal "Done\n", shell_output("./test")
end
end