main: include prebuilt compiler-rt libraries in release tarball
This avoids depending on clang-7 to build compiler-rt for the most common ARM microcontrollers.
Этот коммит содержится в:
родитель
5b507593d2
коммит
9bbb233cf0
4 изменённых файлов: 111 добавлений и 34 удалений
6
Makefile
6
Makefile
|
@ -117,6 +117,9 @@ release: static gen-device
|
|||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
||||
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
|
||||
@mkdir -p build/release/tinygo/lib/nrfx
|
||||
@mkdir -p build/release/tinygo/pkg/armv6m-none-eabi
|
||||
@mkdir -p build/release/tinygo/pkg/armv7m-none-eabi
|
||||
@mkdir -p build/release/tinygo/pkg/armv7em-none-eabi
|
||||
@cp -p build/tinygo build/release/tinygo/bin
|
||||
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
||||
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
|
||||
|
@ -126,6 +129,9 @@ release: static gen-device
|
|||
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
|
||||
@cp -rp src build/release/tinygo/src
|
||||
@cp -rp targets build/release/tinygo/targets
|
||||
./build/tinygo build-builtins -target=armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/compiler-rt.a
|
||||
./build/tinygo build-builtins -target=armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/compiler-rt.a
|
||||
./build/tinygo build-builtins -target=armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/compiler-rt.a
|
||||
tar -czf build/release.tar.gz -C build/release tinygo
|
||||
|
||||
# Binary that can run on the host.
|
||||
|
|
|
@ -80,29 +80,45 @@ func cacheStore(tmppath, name, configKey string, sourceFiles []string) (string,
|
|||
return "", err
|
||||
}
|
||||
cachepath := filepath.Join(dir, name)
|
||||
err = os.Rename(tmppath, cachepath)
|
||||
if err != nil {
|
||||
inf, err := os.Open(tmppath)
|
||||
err = moveFile(tmppath, cachepath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer inf.Close()
|
||||
outf, err := os.Create(cachepath + ".tmp")
|
||||
return cachepath, nil
|
||||
}
|
||||
|
||||
// moveFile renames the file from src to dst. If renaming doesn't work (for
|
||||
// example, the rename crosses a filesystem boundary), the file is copied and
|
||||
// the old file is removed.
|
||||
func moveFile(src, dst string) error {
|
||||
err := os.Rename(src, dst)
|
||||
if err == nil {
|
||||
// Success!
|
||||
return nil
|
||||
}
|
||||
// Failed to move, probably a different filesystem.
|
||||
// Do a copy + remove.
|
||||
inf, err := os.Open(src)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
defer inf.Close()
|
||||
outpath := dst + ".tmp"
|
||||
outf, err := os.Create(outpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(outf, inf)
|
||||
if err != nil {
|
||||
return "", err
|
||||
os.Remove(outpath)
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.Rename(cachepath+".tmp", cachepath)
|
||||
err = os.Rename(dst+".tmp", dst)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
return cachepath, outf.Close()
|
||||
}
|
||||
return cachepath, nil
|
||||
return outf.Close()
|
||||
}
|
||||
|
|
58
builtins.go
58
builtins.go
|
@ -157,16 +157,29 @@ var aeabiBuiltins = []string{
|
|||
|
||||
func builtinFiles(target string) []string {
|
||||
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
||||
if target[:3] == "arm" {
|
||||
if strings.HasPrefix(target, "arm") {
|
||||
builtins = append(builtins, aeabiBuiltins...)
|
||||
}
|
||||
return builtins
|
||||
}
|
||||
|
||||
// builtinsDir returns the directory where the sources for compiler-rt are kept.
|
||||
func builtinsDir() string {
|
||||
return filepath.Join(sourceDir(), "lib", "compiler-rt", "lib", "builtins")
|
||||
}
|
||||
|
||||
// Get the builtins archive, possibly generating it as needed.
|
||||
func loadBuiltins(target string) (path string, err error) {
|
||||
// Try to load a precompiled compiler-rt library.
|
||||
precompiledPath := filepath.Join(sourceDir(), "pkg", target, "compiler-rt.a")
|
||||
if _, err := os.Stat(precompiledPath); err == nil {
|
||||
// Found a precompiled compiler-rt for this OS/architecture. Return the
|
||||
// path directly.
|
||||
return precompiledPath, nil
|
||||
}
|
||||
|
||||
outfile := "librt-" + target + ".a"
|
||||
builtinsDir := filepath.Join(sourceDir(), "lib", "compiler-rt", "lib", "builtins")
|
||||
builtinsDir := builtinsDir()
|
||||
|
||||
builtins := builtinFiles(target)
|
||||
srcs := make([]string, len(builtins))
|
||||
|
@ -178,9 +191,33 @@ func loadBuiltins(target string) (path string, err error) {
|
|||
return path, err
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "tinygo-builtins")
|
||||
var cachepath string
|
||||
err = compileBuiltins(target, func(path string) error {
|
||||
path, err := cacheStore(path, outfile, commands["clang"], srcs)
|
||||
cachepath = path
|
||||
return err
|
||||
})
|
||||
return cachepath, err
|
||||
}
|
||||
|
||||
// compileBuiltins compiles builtins from compiler-rt into a static library.
|
||||
// When it succeeds, it will call the callback with the resulting path. The path
|
||||
// will be removed after callback returns. If callback returns an error, this is
|
||||
// passed through to the return value of this function.
|
||||
func compileBuiltins(target string, callback func(path string) error) error {
|
||||
builtinsDir := builtinsDir()
|
||||
|
||||
builtins := builtinFiles(target)
|
||||
srcs := make([]string, len(builtins))
|
||||
for i, name := range builtins {
|
||||
srcs[i] = filepath.Join(builtinsDir, name)
|
||||
}
|
||||
|
||||
dirPrefix := "tinygo-builtins"
|
||||
remapDir := filepath.Join(os.TempDir(), dirPrefix)
|
||||
dir, err := ioutil.TempDir(os.TempDir(), dirPrefix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
|
@ -195,13 +232,16 @@ func loadBuiltins(target string) (path string, err error) {
|
|||
objpath := filepath.Join(dir, objname+".o")
|
||||
objs = append(objs, objpath)
|
||||
srcpath := filepath.Join(builtinsDir, name)
|
||||
cmd := exec.Command(commands["clang"], "-c", "-Oz", "-g", "-Werror", "-Wall", "-std=c11", "-fshort-enums", "-nostdlibinc", "-ffunction-sections", "-fdata-sections", "--target="+target, "-o", objpath, srcpath)
|
||||
// Note: -fdebug-prefix-map is necessary to make the output archive
|
||||
// reproducible. Otherwise the temporary directory is stored in the
|
||||
// archive itself, which varies each run.
|
||||
cmd := exec.Command(commands["clang"], "-c", "-Oz", "-g", "-Werror", "-Wall", "-std=c11", "-fshort-enums", "-nostdlibinc", "-ffunction-sections", "-fdata-sections", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir, "-o", objpath, srcpath)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Dir = dir
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return "", &commandError{"failed to build", srcpath, err}
|
||||
return &commandError{"failed to build", srcpath, err}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,8 +253,10 @@ func loadBuiltins(target string) (path string, err error) {
|
|||
cmd.Dir = dir
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return "", &commandError{"failed to make static library", arpath, err}
|
||||
return &commandError{"failed to make static library", arpath, err}
|
||||
}
|
||||
|
||||
return cacheStore(arpath, outfile, commands["clang"], srcs)
|
||||
// Give the caller the resulting file. The callback must copy the file,
|
||||
// because after it returns the temporary directory will be removed.
|
||||
return callback(arpath)
|
||||
}
|
||||
|
|
21
main.go
21
main.go
|
@ -186,13 +186,12 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
|||
|
||||
// Load builtins library from the cache, possibly compiling it on the
|
||||
// fly.
|
||||
var cachePath string
|
||||
var librt string
|
||||
if spec.RTLib == "compiler-rt" {
|
||||
librt, err := loadBuiltins(spec.Triple)
|
||||
librt, err = loadBuiltins(spec.Triple)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cachePath, _ = filepath.Split(librt)
|
||||
}
|
||||
|
||||
// Prepare link command.
|
||||
|
@ -200,7 +199,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
|||
tmppath := executable // final file
|
||||
ldflags := append(spec.LDFlags, "-o", executable, objfile)
|
||||
if spec.RTLib == "compiler-rt" {
|
||||
ldflags = append(ldflags, "-L", cachePath, "-lrt-"+spec.Triple)
|
||||
ldflags = append(ldflags, librt)
|
||||
}
|
||||
|
||||
// Compile extra files.
|
||||
|
@ -554,6 +553,20 @@ func main() {
|
|||
}
|
||||
err := Build(flag.Arg(0), *outpath, target, config)
|
||||
handleCompilerError(err)
|
||||
case "build-builtins":
|
||||
// Note: this command is only meant to be used while making a release!
|
||||
if *outpath == "" {
|
||||
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
if *target == "" {
|
||||
fmt.Fprintln(os.Stderr, "No target (-target).")
|
||||
}
|
||||
err := compileBuiltins(*target, func(path string) error {
|
||||
return moveFile(path, *outpath)
|
||||
})
|
||||
handleCompilerError(err)
|
||||
case "flash", "gdb":
|
||||
if *outpath != "" {
|
||||
fmt.Fprintln(os.Stderr, "Output cannot be specified with the flash command.")
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче