Created
May 15, 2021 09:59
-
-
Save cpbotha/5f44a7f44ad93445128113c208b4a252 to your computer and use it in GitHub Desktop.
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
# three changes by Charl Botha https://github.com/cpbotha to get this building | |
# on the M1 | |
# 1. use the iains branch of gcc (see head spec) | |
# 2. change build config to "--build=aarch64-apple-darwin#{osmajor}" | |
# 3. remove --with-bugurl | |
# then build with: | |
# brew install --verbose --build-from-source -head --formula ./libgccjit.rb | |
# took about 18 minutes on my M1 MBA | |
# this seemed successful, but trying to do | |
# brew reinstall emacs-plus@28 --verbose --with-no-titlebar --with-native-comp | |
# ... failed on not finding the libgccjit, which I could work around by copying | |
# those libs to where they could be found | |
# then it failed on the gccjit smoketest, which I tried to build and run on my | |
# machine, finally stopping when I could not get it past: | |
# ld: library not found for -lgcc_s.1.1 | |
# libgccjit.so: error: error invoking gcc driver | |
# NULL result | |
# gcc_s.1.1 is there, and reported as linked in by otool -L. current thinking | |
# is because I'm using iains branch for libgccjit-11, but standard homebrew | |
# cask for gcc-11. Taking a break from this, but let me know if you have better | |
# luck! | |
class Libgccjit < Formula | |
desc "JIT library for the GNU compiler collection" | |
homepage "https://gcc.gnu.org/" | |
url "https://ftp.gnu.org/gnu/gcc/gcc-11.1.0/gcc-11.1.0.tar.xz" | |
sha256 "4c4a6fb8a8396059241c2e674b85b351c26a5d678274007f076957afa1cc9ddf" | |
license "GPL-3.0-or-later" => { | |
with: "GCC-exception-3.1", | |
} | |
head "https://github.com/iains/gcc-darwin-arm64.git", branch: "master-wip-apple-si" | |
livecheck do | |
url :stable | |
regex(%r{href=.*?gcc[._-]v?(\d+(?:\.\d+)+)(?:/?["' >]|\.t)}i) | |
end | |
bottle do | |
sha256 big_sur: "287ce8f8321249e34989748a1406a28f0d6d94c1f23bbea8a3fbabc5d3d162d4" | |
sha256 catalina: "026a9c50299fc6c5f0a530e338003422c31974e44fc7a658242e8b7825f47666" | |
sha256 mojave: "b17b18f077040d14ff4b1d3a863473c6fa21ea24b1695799b8fb6a5ebf1b3617" | |
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? do | |
reason "The bottle needs the Xcode CLT to be installed." | |
satisfy { MacOS::CLT.installed? } | |
end | |
depends_on "gcc" => :test | |
depends_on "gmp" | |
depends_on "isl" | |
depends_on "libmpc" | |
depends_on "mpfr" | |
uses_from_macos "zlib" | |
# GCC bootstraps itself, so it is OK to have an incompatible C++ stdlib | |
cxxstdlib_check :skip | |
def install | |
# GCC will suffer build errors if forced to use a particular linker. | |
ENV.delete "LD" | |
osmajor = `uname -r`.split(".").first | |
pkgversion = "Homebrew GCC #{pkg_version} #{build.used_options*" "}".strip | |
# remove #{osmajor} appended to build config name | |
args = %W[ | |
--build=aarch64-apple-darwin#{osmajor} | |
--prefix=#{prefix} | |
--libdir=#{lib}/gcc/#{version.major} | |
--disable-nls | |
--enable-checking=release | |
--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-system-zlib | |
--with-pkgversion=#{pkgversion} | |
] | |
# try to work around: NoMethodError: undefined method `issues_url' for nil:NilClass | |
#--with-bugurl=#{tap.issues_url} | |
# Xcode 10 dropped 32-bit support | |
args << "--disable-multilib" if DevelopmentTools.clang_build_version >= 1000 | |
# System headers may not be in /usr/include | |
sdk = MacOS.sdk_path_if_needed | |
if sdk | |
args << "--with-native-system-header-dir=/usr/include" | |
args << "--with-sysroot=#{sdk}" | |
end | |
# Use -headerpad_max_install_names in the build, | |
# otherwise updated load commands won't fit in the Mach-O header. | |
# This is needed because `gcc` avoids the superenv shim. | |
make_args = ["BOOT_LDFLAGS=-Wl,-headerpad_max_install_names"] | |
# Building jit needs --enable-host-shared, which slows down the compiler. | |
mkdir "build-jit" do | |
system "../configure", *args, "--enable-languages=jit", "--enable-host-shared" | |
system "make", *make_args | |
system "make", "install" | |
end | |
# We only install the relevant libgccjit files from libexec and delete the rest. | |
Dir["#{prefix}/**/*"].each do |f| | |
rm_rf f if !File.directory?(f) && !File.basename(f).to_s.start_with?("libgccjit") | |
end | |
end | |
test do | |
(testpath/"test-libgccjit.c").write <<~EOS | |
#include <libgccjit.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
static void create_code (gcc_jit_context *ctxt) { | |
gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); | |
gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR); | |
gcc_jit_param *param_name = gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name"); | |
gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, | |
void_type, "greet", 1, ¶m_name, 0); | |
gcc_jit_param *param_format = gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format"); | |
gcc_jit_function *printf_func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, | |
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT), "printf", 1, ¶m_format, 1); | |
gcc_jit_rvalue *args[2]; | |
args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s"); | |
args[1] = gcc_jit_param_as_rvalue (param_name); | |
gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); | |
gcc_jit_block_add_eval (block, NULL, gcc_jit_context_new_call (ctxt, NULL, printf_func, 2, args)); | |
gcc_jit_block_end_with_void_return (block, NULL); | |
} | |
int main (int argc, char **argv) { | |
gcc_jit_context *ctxt; | |
gcc_jit_result *result; | |
ctxt = gcc_jit_context_acquire (); | |
if (!ctxt) { | |
fprintf (stderr, "NULL ctxt"); | |
exit (1); | |
} | |
gcc_jit_context_set_bool_option (ctxt, GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 0); | |
create_code (ctxt); | |
result = gcc_jit_context_compile (ctxt); | |
if (!result) { | |
fprintf (stderr, "NULL result"); | |
exit (1); | |
} | |
typedef void (*fn_type) (const char *); | |
fn_type greet = (fn_type)gcc_jit_result_get_code (result, "greet"); | |
if (!greet) { | |
fprintf (stderr, "NULL greet"); | |
exit (1); | |
} | |
greet ("world"); | |
fflush (stdout); | |
gcc_jit_context_release (ctxt); | |
gcc_jit_result_release (result); | |
return 0; | |
} | |
EOS | |
gcc_major_ver = Formula["gcc"].any_installed_version.major | |
gcc = Formula["gcc"].opt_bin/"gcc-#{gcc_major_ver}" | |
libs = "#{HOMEBREW_PREFIX}/lib/gcc/#{gcc_major_ver}" | |
system gcc.to_s, "-I#{include}", "test-libgccjit.c", "-o", "test", "-L#{libs}", "-lgccjit" | |
assert_equal "hello world", shell_output("./test") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment