Skip to content

Commit 35a4ee5

Browse files
committed
llgo:pretest embed clang
llvm build cache with mac cgo config with c++17 -Wl,-rpath with llvm
1 parent 2b72034 commit 35a4ee5

File tree

1 file changed

+167
-21
lines changed

1 file changed

+167
-21
lines changed

Formula/l/llgo.rb

Lines changed: 167 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
class Llgo < Formula
22
desc "Go compiler based on LLVM integrate with the C ecosystem and Python"
3-
homepage "https://github.com/goplus/llgo"
4-
url "https://github.com/goplus/llgo/archive/refs/tags/v0.11.5.tar.gz"
5-
sha256 "e025993d12c1f5e49e5b8dcb31c0e8b349efe56970d1a23d6c089ebd10928c6b"
3+
homepage "https://github.com/luoliwoshang/llgo"
4+
url "https://github.com/luoliwoshang/llgo/archive/refs/tags/v0.12.12.tar.gz"
5+
sha256 "20c1c968c955dcc3157445c788804ecbd85dbcac248c99c8dfd27bcc3b09e61d"
66
license "Apache-2.0"
7-
head "https://github.com/goplus/llgo.git", branch: "main"
7+
head "https://github.com/luoliwoshang/llgo.git", branch: "main"
88

99
livecheck do
1010
url :stable
@@ -21,18 +21,21 @@ class Llgo < Formula
2121
sha256 x86_64_linux: "2486bc3ddd7c27fe03c9ae10df73553c09b9f21b3d4dc94b55f99da632dbbf5f"
2222
end
2323

24+
depends_on "cmake" => :build
25+
depends_on "ninja" => :build
26+
depends_on "python@3.13" => :build
2427
depends_on "bdw-gc"
2528
depends_on "go@1.24"
2629
depends_on "libffi"
2730
depends_on "libuv"
28-
depends_on "lld@19"
29-
depends_on "llvm@19"
3031
depends_on "openssl@3"
3132
depends_on "pkgconf"
3233
uses_from_macos "zlib"
3334

34-
on_linux do
35-
depends_on "libunwind"
35+
resource "espressif-llvm" do
36+
url "https://github.com/espressif/llvm-project.git",
37+
revision: "xtensa_release_19.1.2",
38+
shallow: true
3639
end
3740

3841
def find_dep(name)
@@ -41,37 +44,176 @@ def find_dep(name)
4144
end
4245

4346
def install
44-
llvm = find_dep("llvm")
47+
ohai "Platform: #{OS.mac? ? "macOS" : "Linux"} #{Hardware::CPU.arch}"
48+
ohai "Building ESP32 LLVM toolchain from source..."
49+
# Build ESP32 LLVM toolchain
50+
cached_clang = "/tmp/homebrew-llgo-cache/cached-esp-clang"
51+
cache_base = "/tmp/homebrew-llgo-cache"
52+
# Test cache directory creation
53+
ohai "Testing cache directory creation at #{cache_base}..."
54+
mkdir_p cache_base
55+
test_file = "#{cache_base}/test-write-permission.txt"
56+
File.write(test_file, "Homebrew LLGO cache test - #{Time.now}")
57+
ohai "✅ Cache directory writable: #{File.read(test_file).strip}"
58+
File.delete(test_file)
59+
if File.directory?(cached_clang)
60+
ohai "Using cached ESP32 LLVM from #{cached_clang}..."
61+
(libexec/"crosscompile").mkpath
62+
cp_r cached_clang, libexec/"crosscompile/clang"
63+
else
64+
resource("espressif-llvm").stage do
65+
ohai "Building LLVM with Xtensa support..."
66+
# Create build directory
67+
mkdir "build" do
68+
# Prepare CMake arguments
69+
cmake_args = %w[
70+
-G Ninja
71+
-DCMAKE_BUILD_TYPE=Release
72+
-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly
73+
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa
74+
-DLLVM_ENABLE_PROJECTS=clang;lld
75+
-DLLVM_ENABLE_RUNTIMES=compiler-rt;libcxx;libcxxabi;libunwind
76+
-DLLVM_POLLY_LINK_INTO_TOOLS=ON
77+
-DLLVM_BUILD_EXTERNAL_COMPILER_RT=ON
78+
-DLLVM_ENABLE_EH=ON
79+
-DLLVM_ENABLE_RTTI=ON
80+
-DLLVM_INCLUDE_DOCS=OFF
81+
-DLLVM_INCLUDE_EXAMPLES=OFF
82+
-DLLVM_INCLUDE_TESTS=OFF
83+
-DLLVM_INCLUDE_BENCHMARKS=OFF
84+
-DLLVM_BUILD_DOCS=OFF
85+
-DLLVM_ENABLE_DOXYGEN=OFF
86+
-DLLVM_INSTALL_UTILS=ON
87+
-DLLVM_ENABLE_Z3_SOLVER=OFF
88+
-DLLVM_OPTIMIZED_TABLEGEN=ON
89+
-DLLVM_USE_RELATIVE_PATHS_IN_FILES=ON
90+
-DLLVM_SOURCE_PREFIX=.
91+
-DLIBCXX_INSTALL_MODULES=ON
92+
-DCLANG_FORCE_MATCHING_LIBCLANG_SOVERSION=OFF
93+
-DCOMPILER_RT_BUILD_SANITIZERS=OFF
94+
-DCOMPILER_RT_BUILD_XRAY=OFF
95+
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF
96+
-DCOMPILER_RT_BUILD_PROFILE=OFF
97+
-DCOMPILER_RT_BUILD_MEMPROF=OFF
98+
-DCOMPILER_RT_BUILD_ORC=OFF
99+
-DCOMPILER_RT_BUILD_GWP_ASAN=OFF
100+
-DCOMPILER_RT_BUILD_CTX_PROFILE=OFF
101+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
102+
-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF
103+
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON
104+
-DCOMPILER_RT_USE_BUILTINS_LIBRARY=ON
105+
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON
106+
-DLIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=OFF
107+
-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON
108+
-DLIBCXX_USE_COMPILER_RT=ON
109+
-DLIBCXX_HAS_ATOMIC_LIB=OFF
110+
-DLIBCXXABI_ENABLE_STATIC_UNWINDER=ON
111+
-DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY=OFF
112+
-DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=ON
113+
-DLIBCXXABI_USE_COMPILER_RT=ON
114+
-DLIBCXXABI_USE_LLVM_UNWINDER=ON
115+
-DLIBUNWIND_USE_COMPILER_RT=ON
116+
-DSANITIZER_CXX_ABI=libc++
117+
-DSANITIZER_TEST_CXX=libc++
118+
-DLLVM_LINK_LLVM_DYLIB=ON
119+
-DCLANG_LINK_CLANG_DYLIB=ON
120+
-DCMAKE_STRIP=/usr/bin/strip
121+
]
122+
123+
if OS.mac?
124+
ohai "SDK PATH: #{MacOS.sdk_path}"
125+
ohai "Hardware Architecture: #{Hardware::CPU.arch}"
126+
end
127+
# Add macOS-specific arguments
128+
cmake_args += if OS.mac?
129+
%W[
130+
-DLLVM_BUILD_LLVM_C_DYLIB=ON
131+
-DLLVM_ENABLE_LIBCXX=ON
132+
-DLIBCXX_PSTL_BACKEND=libdispatch
133+
-DCMAKE_OSX_SYSROOT=#{MacOS.sdk_path}
134+
-DCMAKE_OSX_ARCHITECTURES=#{Hardware::CPU.arch}
135+
-DLIBCXXABI_USE_SYSTEM_LIBS=ON
136+
]
137+
else
138+
%w[
139+
-DLLVM_ENABLE_LIBXML2=OFF
140+
-DLLVM_ENABLE_LIBCXX=OFF
141+
-DCLANG_DEFAULT_CXX_STDLIB=libstdc++
142+
-DLLVM_BUILD_LLVM_DYLIB=ON
143+
-DCOMPILER_RT_USE_LLVM_UNWINDER=ON
144+
]
145+
end
146+
147+
cmake_args << "-DCMAKE_INSTALL_PREFIX=#{libexec}/crosscompile/clang"
148+
149+
# Configure
150+
system "cmake", *cmake_args, "../llvm"
151+
152+
ohai "Ninjia build with #{ENV.make_jobs} jobs"
153+
154+
# Build with all available cores
155+
system "ninja", "-j#{ENV.make_jobs}"
156+
# Install
157+
system "ninja", "install"
158+
end
159+
160+
ohai "ESP32 LLVM toolchain built and installed to: #{libexec}/crosscompile/clang"
161+
# Cache the built toolchain for next time
162+
ohai "Caching ESP32 LLVM to #{cached_clang}..."
163+
cp_r (libexec/"crosscompile/clang").to_s, cached_clang
164+
end
165+
end
166+
167+
local_llvm_config = libexec/"crosscompile/clang/bin/llvm-config"
168+
45169
ldflags = %W[
46170
-s -w
47171
-X github.com/goplus/llgo/internal/env.buildVersion=v#{version}
48172
-X github.com/goplus/llgo/internal/env.buildTime=#{time.iso8601}
49-
-X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=#{llvm.opt_bin/"llvm-config"}
173+
-X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=#{local_llvm_config}
50174
]
51175
tags = nil
176+
177+
local_llvm_include = libexec/"crosscompile/clang/include"
178+
local_llvm_lib = libexec/"crosscompile/clang/lib"
179+
180+
ENV.prepend "CGO_CXXFLAGS", "-std=c++17"
181+
ENV.prepend "CGO_LDFLAGS", "-L#{local_llvm_lib} -lLLVM -Wl,-rpath,#{local_llvm_lib}"
52182
if OS.linux?
53183
ENV.prepend "CGO_CPPFLAGS",
54-
"-I#{llvm.opt_include} " \
184+
"-I#{local_llvm_include} " \
55185
"-D_GNU_SOURCE " \
56186
"-D__STDC_CONSTANT_MACROS " \
57187
"-D__STDC_FORMAT_MACROS " \
58188
"-D__STDC_LIMIT_MACROS"
59-
ENV.prepend "CGO_LDFLAGS", "-L#{llvm.opt_lib} -lLLVM"
60189
tags = "byollvm"
190+
ohai "Linux CGO setup - Include: #{local_llvm_include}, Lib: #{local_llvm_lib}"
191+
elsif OS.mac?
192+
# macos also needs custom llvm setup
193+
ENV.prepend "CGO_CPPFLAGS", "-I#{local_llvm_include}"
194+
tags = "byollvm"
195+
ohai "macOS CGO setup - Include: #{local_llvm_include}, Lib: #{local_llvm_lib}"
196+
ohai "CGO_CPPFLAGS: #{ENV["CGO_CPPFLAGS"]}"
197+
ohai "CGO_LDFLAGS: #{ENV["CGO_LDFLAGS"]}"
61198
end
62199

63-
system "go", "build", *std_go_args(ldflags:, tags:), "-o", libexec/"bin/", "./cmd/llgo"
200+
ohai "Building LLGO..."
201+
system "go", "build", *std_go_args(ldflags: ldflags, tags: tags), "-o", libexec/"bin/", "./cmd/llgo"
64202

65203
libexec.install "LICENSE", "README.md", "go.mod", "go.sum", "runtime"
66204

67-
path_deps = %w[lld go pkgconf].map { |name| find_dep(name).opt_bin }
68-
path_deps << llvm.opt_bin
205+
path_deps = %w[go pkgconf].map { |name| find_dep(name).opt_bin }
206+
path_deps << (libexec/"crosscompile/clang/bin")
69207
script_env = { PATH: "#{path_deps.join(":")}:$PATH" }
70208

71209
if OS.linux?
72-
libunwind = find_dep("libunwind")
73-
script_env[:CFLAGS] = "-I#{libunwind.opt_include} $CFLAGS"
74-
script_env[:LDFLAGS] = "-L#{libunwind.opt_lib} -rpath #{libunwind.opt_lib} $LDFLAGS"
210+
local_llvm_include = libexec/"crosscompile/clang/include"
211+
local_llvm_lib = libexec/"crosscompile/clang/lib"
212+
ohai "Setting up runtime environment for Linux..."
213+
ohai " LLVM Include: #{local_llvm_include}"
214+
ohai " LLVM Lib: #{local_llvm_lib}"
215+
script_env[:CFLAGS] = "-I#{local_llvm_include} $CFLAGS"
216+
script_env[:LDFLAGS] = "-L#{local_llvm_lib} -rpath #{local_llvm_lib} $LDFLAGS"
75217
end
76218

77219
(libexec/"bin").children.each do |f|
@@ -100,6 +242,7 @@ def install
100242
"fmt"
101243
102244
"github.com/goplus/lib/c"
245+
"github.com/goplus/lib/cpp/std"
103246
)
104247
105248
func Foo() string {
@@ -109,6 +252,7 @@ def install
109252
func main() {
110253
fmt.Println("Hello LLGo by fmt.Println")
111254
c.Printf(c.Str("Hello LLGo by c.Printf\\n"))
255+
c.Printf(std.Str("Hello LLGo by cpp/std.Str\\n").CStr())
112256
}
113257
GO
114258
(testpath/"hello_test.go").write <<~GO
@@ -130,12 +274,14 @@ module hello
130274
system go.opt_bin/"go", "get", "github.com/goplus/lib"
131275
# Test llgo run
132276
assert_equal "Hello LLGo by fmt.Println\n" \
133-
"Hello LLGo by c.Printf\n",
134-
shell_output("#{bin}/llgo run .")
277+
"Hello LLGo by c.Printf\n" \
278+
"Hello LLGo by cpp/std.Str\n",
279+
shell_output("#{bin}/llgo run -v .")
135280
# Test llgo build
136281
system bin/"llgo", "build", "-o", "hello", "."
137282
assert_equal "Hello LLGo by fmt.Println\n" \
138-
"Hello LLGo by c.Printf\n",
283+
"Hello LLGo by c.Printf\n" \
284+
"Hello LLGo by cpp/std.Str\n",
139285
shell_output("./hello")
140286
# Test llgo test
141287
assert_match "PASS", shell_output("#{bin}/llgo test .")

0 commit comments

Comments
 (0)