builder: add support for cross compiling to Darwin
This means that it will be possible to generate a Darwin binary on any platform (Windows, Linux, and MacOS of course), including CGo. Of course, the resulting binaries can only run on MacOS itself. The binary links against libSystem.dylib, which is a shared library. The macos-minimal-sdk repository contains open source header files and generated symbol stubs so we can generate a stub libSystem.dylib without copying any closed source code.
Этот коммит содержится в:
родитель
850a5fdbfb
коммит
cdd267fa10
12 изменённых файлов: 105 добавлений и 9 удалений
2
.github/workflows/build-macos.yml
предоставленный
2
.github/workflows/build-macos.yml
предоставленный
|
@ -48,7 +48,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-macos-v2
|
||||
key: llvm-build-13-macos-v3
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
|
|
4
.github/workflows/linux.yml
предоставленный
4
.github/workflows/linux.yml
предоставленный
|
@ -51,7 +51,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-linux-v1
|
||||
key: llvm-build-13-linux-v2
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
|
@ -192,7 +192,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-linux-asserts-v1
|
||||
key: llvm-build-13-linux-asserts-v2
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
|
|
2
.github/workflows/windows.yml
предоставленный
2
.github/workflows/windows.yml
предоставленный
|
@ -48,7 +48,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-windows-v1
|
||||
key: llvm-build-13-windows-v2
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
|
|
3
.gitmodules
предоставленный
3
.gitmodules
предоставленный
|
@ -32,3 +32,6 @@
|
|||
[submodule "lib/mingw-w64"]
|
||||
path = lib/mingw-w64
|
||||
url = https://github.com/mingw-w64/mingw-w64.git
|
||||
[submodule "lib/macos-minimal-sdk"]
|
||||
path = lib/macos-minimal-sdk
|
||||
url = https://github.com/aykevl/macos-minimal-sdk.git
|
||||
|
|
7
Makefile
7
Makefile
|
@ -73,6 +73,8 @@ ifeq ($(OS),Windows_NT)
|
|||
else ifeq ($(shell uname -s),Darwin)
|
||||
MD5SUM = md5
|
||||
|
||||
CGO_LDFLAGS += -lxar
|
||||
|
||||
USE_SYSTEM_BINARYEN ?= 1
|
||||
|
||||
else ifeq ($(shell uname -s),FreeBSD)
|
||||
|
@ -89,7 +91,7 @@ CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGe
|
|||
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
|
||||
|
||||
# Libraries that should be linked in for the statically linked LLD.
|
||||
LLD_LIB_NAMES = lldCOFF lldCommon lldCore lldDriver lldELF lldMachO lldMinGW lldReaderWriter lldWasm lldYAML
|
||||
LLD_LIB_NAMES = lldCOFF lldCommon lldCore lldDriver lldELF lldMachO2 lldMinGW lldReaderWriter lldWasm lldYAML
|
||||
LLD_LIBS = $(START_GROUP) $(addprefix -l,$(LLD_LIB_NAMES)) $(END_GROUP)
|
||||
|
||||
# Other libraries that are needed to link TinyGo.
|
||||
|
@ -566,6 +568,7 @@ endif
|
|||
@$(MD5SUM) test.hex
|
||||
GOOS=linux GOARCH=arm $(TINYGO) build -size short -o test.elf ./testdata/cgo
|
||||
GOOS=windows GOARCH=amd64 $(TINYGO) build -size short -o test.exe ./testdata/cgo
|
||||
GOOS=darwin GOARCH=amd64 $(TINYGO) build -o test ./testdata/cgo
|
||||
ifneq ($(OS),Windows_NT)
|
||||
# TODO: this does not yet work on Windows. Somehow, unused functions are
|
||||
# not garbage collected.
|
||||
|
@ -581,6 +584,7 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
|
|||
@mkdir -p build/release/tinygo/lib/clang/include
|
||||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
||||
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
|
||||
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
|
||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||
@mkdir -p build/release/tinygo/lib/musl/arch
|
||||
|
@ -604,6 +608,7 @@ endif
|
|||
@cp -rp lib/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt/lib
|
||||
@cp -rp lib/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt
|
||||
@cp -rp lib/compiler-rt/README.txt build/release/tinygo/lib/compiler-rt
|
||||
@cp -rp lib/macos-minimal-sdk/* build/release/tinygo/lib/macos-minimal-sdk
|
||||
@cp -rp lib/musl/arch/aarch64 build/release/tinygo/lib/musl/arch
|
||||
@cp -rp lib/musl/arch/arm build/release/tinygo/lib/musl/arch
|
||||
@cp -rp lib/musl/arch/generic build/release/tinygo/lib/musl/arch
|
||||
|
|
|
@ -107,6 +107,9 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||
root := goenv.Get("TINYGOROOT")
|
||||
var libcDependencies []*compileJob
|
||||
switch config.Target.Libc {
|
||||
case "darwin-libSystem":
|
||||
job := makeDarwinLibSystemJob(config, dir)
|
||||
libcDependencies = append(libcDependencies, job)
|
||||
case "musl":
|
||||
job, unlock, err := Musl.load(config, dir)
|
||||
if err != nil {
|
||||
|
|
58
builder/darwin-libsystem.go
Обычный файл
58
builder/darwin-libsystem.go
Обычный файл
|
@ -0,0 +1,58 @@
|
|||
package builder
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
// Create a job that builds a Darwin libSystem.dylib stub library. This library
|
||||
// contains all the symbols needed so that we can link against it, but it
|
||||
// doesn't contain any real symbol implementations.
|
||||
func makeDarwinLibSystemJob(config *compileopts.Config, tmpdir string) *compileJob {
|
||||
return &compileJob{
|
||||
description: "compile Darwin libSystem.dylib",
|
||||
run: func(job *compileJob) (err error) {
|
||||
arch := strings.Split(config.Triple(), "-")[0]
|
||||
job.result = filepath.Join(tmpdir, "libSystem.dylib")
|
||||
objpath := filepath.Join(tmpdir, "libSystem.o")
|
||||
inpath := filepath.Join(goenv.Get("TINYGOROOT"), "lib/macos-minimal-sdk/src", arch, "libSystem.s")
|
||||
|
||||
// Compile assembly file to object file.
|
||||
flags := []string{
|
||||
"-nostdlib",
|
||||
"--target=" + config.Triple(),
|
||||
"-c",
|
||||
"-o", objpath,
|
||||
inpath,
|
||||
}
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands("clang", flags...)
|
||||
}
|
||||
err = runCCompiler(flags...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Link object file to dynamic library.
|
||||
platformVersion := strings.TrimPrefix(strings.Split(config.Triple(), "-")[2], "macosx")
|
||||
flags = []string{
|
||||
"-flavor", "darwinnew",
|
||||
"-demangle",
|
||||
"-dynamic",
|
||||
"-dylib",
|
||||
"-arch", arch,
|
||||
"-platform_version", "macos", platformVersion, platformVersion,
|
||||
"-install_name", "/usr/lib/libSystem.B.dylib",
|
||||
"-o", job.result,
|
||||
objpath,
|
||||
}
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands("ld.lld", flags...)
|
||||
}
|
||||
return link("ld.lld", flags...)
|
||||
},
|
||||
}
|
||||
}
|
|
@ -11,6 +11,11 @@ bool tinygo_link_elf(int argc, char **argv) {
|
|||
return lld::elf::link(args, false, llvm::outs(), llvm::errs());
|
||||
}
|
||||
|
||||
bool tinygo_link_macho(int argc, char **argv) {
|
||||
std::vector<const char*> args(argv, argv + argc);
|
||||
return lld::macho::link(args, false, llvm::outs(), llvm::errs());
|
||||
}
|
||||
|
||||
bool tinygo_link_mingw(int argc, char **argv) {
|
||||
std::vector<const char*> args(argv, argv + argc);
|
||||
return lld::mingw::link(args, false, llvm::outs(), llvm::errs());
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
#include <stdlib.h>
|
||||
bool tinygo_clang_driver(int argc, char **argv);
|
||||
bool tinygo_link_elf(int argc, char **argv);
|
||||
bool tinygo_link_macho(int argc, char **argv);
|
||||
bool tinygo_link_mingw(int argc, char **argv);
|
||||
bool tinygo_link_wasm(int argc, char **argv);
|
||||
*/
|
||||
|
@ -27,8 +28,13 @@ const hasBuiltinTools = true
|
|||
// linking statically with LLVM (with the byollvm build tag).
|
||||
func RunTool(tool string, args ...string) error {
|
||||
linker := "elf"
|
||||
if tool == "ld.lld" && len(args) >= 2 && args[0] == "-m" && args[1] == "i386pep" {
|
||||
linker = "mingw"
|
||||
if tool == "ld.lld" && len(args) >= 2 {
|
||||
if args[0] == "-m" && args[1] == "i386pep" {
|
||||
linker = "mingw"
|
||||
} else if args[0] == "-flavor" {
|
||||
linker = args[1]
|
||||
args = args[2:]
|
||||
}
|
||||
}
|
||||
args = append([]string{"tinygo:" + tool}, args...)
|
||||
|
||||
|
@ -48,6 +54,8 @@ func RunTool(tool string, args ...string) error {
|
|||
ok = C.tinygo_clang_driver(C.int(len(args)), (**C.char)(buf))
|
||||
case "ld.lld":
|
||||
switch linker {
|
||||
case "darwinnew":
|
||||
ok = C.tinygo_link_macho(C.int(len(args)), (**C.char)(buf))
|
||||
case "elf":
|
||||
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
|
||||
case "mingw":
|
||||
|
|
|
@ -225,6 +225,11 @@ func (c *Config) CFlags() []string {
|
|||
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
||||
}
|
||||
switch c.Target.Libc {
|
||||
case "darwin-libSystem":
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
cflags = append(cflags,
|
||||
"--sysroot="+filepath.Join(root, "lib/macos-minimal-sdk/src"),
|
||||
)
|
||||
case "picolibc":
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
|
||||
|
|
|
@ -272,8 +272,16 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
|||
spec.Features = "+neon"
|
||||
}
|
||||
if goos == "darwin" {
|
||||
spec.CFlags = append(spec.CFlags, "-isysroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk")
|
||||
spec.LDFlags = append(spec.LDFlags, "-Wl,-dead_strip")
|
||||
spec.Linker = "ld.lld"
|
||||
spec.Libc = "darwin-libSystem"
|
||||
arch := strings.Split(triple, "-")[0]
|
||||
platformVersion := strings.TrimPrefix(strings.Split(triple, "-")[2], "macosx")
|
||||
spec.LDFlags = append(spec.LDFlags,
|
||||
"-flavor", "darwinnew",
|
||||
"-dead_strip",
|
||||
"-arch", arch,
|
||||
"-platform_version", "macos", platformVersion, platformVersion,
|
||||
)
|
||||
} else if goos == "linux" {
|
||||
spec.Linker = "ld.lld"
|
||||
spec.RTLib = "compiler-rt"
|
||||
|
|
1
lib/macos-minimal-sdk
Подмодуль
1
lib/macos-minimal-sdk
Подмодуль
|
@ -0,0 +1 @@
|
|||
Subproject commit a9a5a723a6d743a8562bbb62218c6f1361a05994
|
Загрузка…
Создание таблицы
Сослаться в новой задаче