homebrew-core/Formula/emscripten.rb

185 lines
6.7 KiB
Ruby

require "language/node"
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.21.tar.gz"
sha256 "641f92dbceb6fa5644e6e037e8ad520f9132f0f4910277b1e729bdf05c087892"
license all_of: [
"Apache-2.0", # binaryen
"Apache-2.0" => { with: "LLVM-exception" }, # llvm
any_of: ["MIT", "NCSA"], # emscripten
]
head "https://github.com/emscripten-core/emscripten.git", branch: "main"
livecheck do
url :stable
regex(/^v?(\d+(?:\.\d+)+)$/i)
end
bottle do
sha256 cellar: :any, arm64_monterey: "e029eaa4dc763afcf49d6e74af33c531493b4069d58e2272a9ea7863d508a7d8"
sha256 cellar: :any, arm64_big_sur: "c2fd4998b56b69bf1a3f2aa4aa8c72bf2d1717b7236616507394f202e3b73012"
sha256 cellar: :any, monterey: "6893e7c9b3a7b6c8fd61b57a4ec8abe169ba31286b0cdcd867a0de82d14ca6ee"
sha256 cellar: :any, big_sur: "6ba4872aa926ae1a8dbeb818bd1a1cdca46b5a17e955bc1061740fda97d36dce"
sha256 cellar: :any, catalina: "0763b68a24ba727f9d36388fc212990284440525db643c3c5d6a0d24e56f74f2"
sha256 cellar: :any_skip_relocation, x86_64_linux: "402fce30cf5d0f194e5a1870981e29f3ab39dbf949edf317cc339ba16cfb09b2"
end
depends_on "cmake" => :build
depends_on "node"
# TODO: Check if we can use `uses_from_macos "python"`.
depends_on "python@3.10"
depends_on "yuicompressor"
# OpenJDK is needed as a dependency on Linux and ARM64 for google-closure-compiler,
# an emscripten dependency, because the native GraalVM image will not work.
on_macos do
on_arm do
depends_on "openjdk"
end
end
on_linux do
depends_on "openjdk"
end
fails_with gcc: "5"
# Use emscripten's recommended binaryen revision to avoid build failures.
# See llvm resource below for instructions on how to update this.
resource "binaryen" do
url "https://github.com/WebAssembly/binaryen.git",
revision: "d4d33b1e175c962548347c59339783c11d5d1a23"
end
# emscripten needs argument '-fignore-exceptions', which is only available in llvm >= 12
# 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:
# https://chromium.googlesource.com/emscripten-releases/+/<commit>/DEPS
# Then use the listed llvm_project_revision for the resource below.
resource "llvm" do
url "https://github.com/llvm/llvm-project.git",
revision: "a4a29438f451370ed241dde30bfcaab0fdf2ab71"
end
def install
# Avoid hardcoding the executables we pass to `write_env_script` below.
# 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
end.map(&:basename)
# All files from the repository are required as emscripten is a collection
# of scripts which need to be installed in the same layout as in the Git
# repository.
libexec.install buildpath.children
# 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
projects = %w[
clang
lld
]
targets = %w[
host
WebAssembly
]
# 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
args = %W[
-DLLVM_ENABLE_PROJECTS=#{projects.join(";")}
-DLLVM_TARGETS_TO_BUILD=#{targets.join(";")}
-DLLVM_LINK_LLVM_DYLIB=ON
-DLLVM_BUILD_LLVM_DYLIB=ON
-DLLVM_INCLUDE_EXAMPLES=OFF
-DLLVM_INCLUDE_TESTS=OFF
-DLLVM_INSTALL_UTILS=OFF
]
sdk = MacOS.sdk_path_if_needed
args << "-DDEFAULT_SYSROOT=#{sdk}" if sdk
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"
end
resource("binaryen").stage do
system "cmake", "-S", ".", "-B", "build", *std_cmake_args(install_prefix: libexec/"binaryen")
system "cmake", "--build", "build"
system "cmake", "--install", "build"
end
cd libexec do
system "npm", "install", *Language::Node.local_npm_install_args
rm_f "node_modules/ws/builderror.log" # Avoid references to Homebrew shims
# Delete native GraalVM image in incompatible platforms.
if OS.linux?
rm_rf "node_modules/google-closure-compiler-linux"
elsif Hardware::CPU.arm?
rm_rf "node_modules/google-closure-compiler-osx"
end
end
# Add JAVA_HOME to env_script on ARM64 macOS and Linux, so that google-closure-compiler
# can find OpenJDK
emscript_env = { PYTHON: Formula["python@3.10"].opt_bin/"python3.10" }
emscript_env.merge! Language::Java.overridable_java_home_env if OS.linux? || Hardware::CPU.arm?
emscripts.each do |emscript|
(bin/emscript).write_env_script libexec/emscript, emscript_env
end
end
def post_install
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")
end
end
test do
# Fixes "Unsupported architecture" Xcode prepocessor error
ENV.delete "CPATH"
ENV["NODE_OPTIONS"] = "--no-experimental-fetch"
(testpath/"test.c").write <<~EOS
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
EOS
system bin/"emcc", "test.c", "-o", "test.js", "-s", "NO_EXIT_RUNTIME=0"
assert_equal "Hello World!", shell_output("node test.js").chomp
end
end