diff --git a/Formula/emscripten.rb b/Formula/emscripten.rb index e73791180a5d..46156a0f7e4c 100644 --- a/Formula/emscripten.rb +++ b/Formula/emscripten.rb @@ -3,10 +3,8 @@ class Emscripten < Formula desc "LLVM bytecode to JavaScript compiler" homepage "https://emscripten.org/" - # TODO: Remove from versioned dependency conflict allowlist when `python` - # symlink is migrated to `python@3.10`. - url "https://github.com/emscripten-core/emscripten/archive/3.1.22.tar.gz" - sha256 "417be3a3ccec6a8ddaaecfd07e6962ceabc5a66cc26f3a7f885a7601832bc15c" + url "https://github.com/emscripten-core/emscripten/archive/3.1.23.tar.gz" + sha256 "f590deb9bb0a34efaa3c4a5621795c4673ba8f953ed363e80d1701aa835f812b" license all_of: [ "Apache-2.0", # binaryen "Apache-2.0" => { with: "LLVM-exception" }, # llvm @@ -49,13 +47,15 @@ class Emscripten < Formula fails_with gcc: "5" # Use emscripten's recommended binaryen revision to avoid build failures. + # https://github.com/emscripten-core/emscripten/issues/12252 # See llvm resource below for instructions on how to update this. resource "binaryen" do url "https://github.com/WebAssembly/binaryen.git", - revision: "989489020e635d35870b22894a5d129c8c55d640" + revision: "58bedde3ac54f82657d5de092e7142ffb2ff735c" end - # emscripten needs argument '-fignore-exceptions', which is only available in llvm >= 12 + # emscripten does not support using the stable version of LLVM. + # https://github.com/emscripten-core/emscripten/issues/11362 # To find the correct llvm revision, find a corresponding commit at: # https://github.com/emscripten-core/emsdk/blob/main/emscripten-releases-tags.json # Then take this commit and go to: @@ -63,7 +63,7 @@ class Emscripten < Formula # Then use the listed llvm_project_revision for the resource below. resource "llvm" do url "https://github.com/llvm/llvm-project.git", - revision: "8491d01cc385d08b8b4f5dd097239ea0009ddc63" + revision: "8b587113b746f31b63fd6473083df78cef30a72e" end def install @@ -71,11 +71,7 @@ def install # Prefer executables without `.py` extensions, but include those with `.py` # extensions if there isn't a matching executable without the `.py` extension. emscripts = buildpath.children.select do |pn| - next false unless pn.file? - next false unless pn.executable? - next false if pn.extname == ".py" && pn.basename(".py").exist? - - true + pn.file? && pn.executable? && !(pn.extname == ".py" && pn.basename(".py").exist?) end.map(&:basename) # All files from the repository are required as emscripten is a collection @@ -83,6 +79,9 @@ def install # repository. libexec.install buildpath.children + # Remove unneded files. See `tools/install.py`. + (libexec/"test/third_party").rmtree + # emscripten needs an llvm build with the following executables: # https://github.com/emscripten-core/emscripten/blob/#{version}/docs/packaging.md#dependencies resource("llvm").stage do @@ -99,31 +98,56 @@ def install # Apple's libstdc++ is too old to build LLVM ENV.libcxx if ENV.compiler == :clang - # compiler-rt has some iOS simulator features that require i386 symbols - # I'm assuming the rest of clang needs support too for 32-bit compilation - # to work correctly, but if not, perhaps universal binaries could be - # limited to compiler-rt. llvm makes this somewhat easier because compiler-rt - # can almost be treated as an entirely different build from llvm. - ENV.permit_arch_flags - + # See upstream configuration in `src/build.py` at + # https://chromium.googlesource.com/emscripten-releases/ args = %W[ - -DLLVM_ENABLE_PROJECTS=#{projects.join(";")} - -DLLVM_TARGETS_TO_BUILD=#{targets.join(";")} - -DLLVM_LINK_LLVM_DYLIB=ON - -DLLVM_BUILD_LLVM_DYLIB=ON + -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_INCLUDE_EXAMPLES=OFF + -DLLVM_LINK_LLVM_DYLIB=OFF + -DLLVM_BUILD_LLVM_DYLIB=OFF + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON + -DLLVM_ENABLE_BINDINGS=OFF + -DLLVM_TOOL_LTO_BUILD=OFF + -DLLVM_INSTALL_TOOLCHAIN_ONLY=ON + -DLLVM_TARGETS_TO_BUILD=#{targets.join(";")} + -DLLVM_ENABLE_PROJECTS=#{projects.join(";")} + -DLLVM_ENABLE_TERMINFO=#{!OS.linux?} + -DCLANG_ENABLE_ARCMT=OFF + -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INSTALL_UTILS=OFF + -DLLVM_ENABLE_ZSTD=OFF + -DLLVM_ENABLE_Z3_SOLVER=OFF ] - - sdk = MacOS.sdk_path_if_needed - args << "-DDEFAULT_SYSROOT=#{sdk}" if sdk + args << "-DLLVM_ENABLE_LIBEDIT=OFF" if OS.linux? system "cmake", "-S", "llvm", "-B", "build", "-G", "Unix Makefiles", *args, *std_cmake_args(install_prefix: libexec/"llvm") system "cmake", "--build", "build" system "cmake", "--build", "build", "--target", "install" + + # Remove unneeded tools. Taken from upstream `src/build.py`. + unneeded = %w[ + check cl cpp extef-mapping format func-mapping import-test offload-bundler refactor rename scan-deps + ].map { |suffix| "clang-#{suffix}" } + unneeded += %w[lld-link ld.lld ld64.lld llvm-lib ld64.lld.darwinnew ld64.lld.darwinold] + (libexec/"llvm/bin").glob("{#{unneeded.join(",")}}").map(&:unlink) + (libexec/"llvm/lib").glob("libclang.{dylib,so.*}").map(&:unlink) + + # Include needed tools omitted by `LLVM_INSTALL_TOOLCHAIN_ONLY`. + # Taken from upstream `src/build.py`. + extra_tools = %w[FileCheck llc llvm-as llvm-dis llvm-link llvm-mc + llvm-nm llvm-objdump llvm-readobj llvm-size opt + llvm-dwarfdump llvm-dwp] + (libexec/"llvm/bin").install extra_tools.map { |tool| "build/bin/#{tool}" } + + %w[clang clang++].each do |compiler| + (libexec/"llvm/bin").install_symlink compiler => "wasm32-#{compiler}" + (libexec/"llvm/bin").install_symlink compiler => "wasm32-wasi-#{compiler}" + bin.install_symlink libexec/"llvm/bin/wasm32-#{compiler}" + bin.install_symlink libexec/"llvm/bin/wasm32-wasi-#{compiler}" + end end resource("binaryen").stage do @@ -154,18 +178,33 @@ def install end def post_install + return if File.exist?("#{Dir.home}/.emscripten") return if (libexec/".emscripten").exist? system bin/"emcc", "--generate-config" inreplace libexec/".emscripten" do |s| - s.gsub!(/^(LLVM_ROOT.*)/, "#\\1\nLLVM_ROOT = \"#{libexec}/llvm/bin\"\\2") - s.gsub!(/^(BINARYEN_ROOT.*)/, "#\\1\nBINARYEN_ROOT = \"#{libexec}/binaryen\"\\2") + s.change_make_var! "LLVM_ROOT", "'#{libexec}/llvm/bin'" + s.change_make_var! "BINARYEN_ROOT", "'#{libexec}/binaryen'" + s.change_make_var! "NODE_JS", "'#{Formula["node"].opt_bin}/node'" + s.change_make_var! "JAVA", "'#{Formula["openjdk"].opt_bin}/java'" end end + def caveats + return unless File.exist?("#{Dir.home}/.emscripten") + return if (libexec/".emscripten").exist? + + <<~EOS + You have a ~/.emscripten configuration file, so the default configuration + file was not generated. To generate the default configuration: + rm ~/.emscripten + brew postinstall emscripten + EOS + end + test do - # Fixes "Unsupported architecture" Xcode prepocessor error - ENV.delete "CPATH" + # We're targetting WASM, so we don't want to use the macOS SDK here. + ENV.remove_macosxsdk if OS.mac? ENV["NODE_OPTIONS"] = "--no-experimental-fetch"