Permalink
Cannot retrieve contributors at this time
279 lines (232 sloc)
9.93 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
homebrew-core/Formula/gcc.rb /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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-13.1.0/gcc-13.1.0.tar.xz" | |
| mirror "https://ftpmirror.gnu.org/gcc/gcc-13.1.0/gcc-13.1.0.tar.xz" | |
| sha256 "61d684f0aa5e76ac6585ad8898a2427aade8979ed5e7f85492286c4dfc13ee86" | |
| # Branch from the Darwin maintainer of GCC, with a few generic fixes and | |
| # Apple Silicon support, located at https://github.com/iains/gcc-13-branch | |
| patch do | |
| url "https://raw.githubusercontent.com/Homebrew/formula-patches/5c206c47/gcc/gcc-13.1.0.diff" | |
| sha256 "cb4e8a89387f748a744da0273025d0dc2e3c76780cc390b18ada704676afea11" | |
| end | |
| end | |
| livecheck do | |
| url :stable | |
| regex(%r{href=["']?gcc[._-]v?(\d+(?:\.\d+)+)(?:/?["' >]|\.t)}i) | |
| end | |
| bottle do | |
| sha256 arm64_ventura: "d2b21a257c73e9b8f9c6bc03e6330ea8ba9fb3e7cdb9eb945d7ff7d96ba9708c" | |
| sha256 arm64_monterey: "5405f3b1ecdabb68e161308f35d72af907af21694a0e2b67f10edb25b2dd8f90" | |
| sha256 arm64_big_sur: "cc92fced3516bc72b69e31b0495fe416f206b540be02f1c817db96afbcc38f28" | |
| sha256 ventura: "3abd8c2c88a8e74b5df5c44f9c151ff7e760cf705307ecf3c95762492e777f1e" | |
| sha256 monterey: "f9cbc7eb14781df9228518a2d02590941206947e7dc419c0b232d523f39b1475" | |
| sha256 big_sur: "2eb458ed309ea4fa9451ab547fa3d797bd523ba4f50f01d5c997212109b74e5e" | |
| sha256 cellar: :any_skip_relocation, x86_64_linux: "cca77a5d6625d3bb711ce40551751974d4cb5c74306329fc2fc8cdcade2ef564" | |
| 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 |