diff options
author | Ayke van Laethem <[email protected]> | 2019-04-07 15:40:03 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2019-04-11 11:53:58 +0200 |
commit | 315cd4059fd38be4c078a5974556e5d120d1662a (patch) | |
tree | 934a64bc4834ca751a7c66d2c5caa1fd83f94674 | |
parent | 078dd9ff5236e40bfd530f8418d72916ce111e33 (diff) | |
download | tinygo-315cd4059fd38be4c078a5974556e5d120d1662a.tar.gz tinygo-315cd4059fd38be4c078a5974556e5d120d1662a.zip |
main: drop the dependency on llvm-ar
The ar file format is pretty simple and can be implemented by using a Go
library. Use that instead of calling out to llvm-ar.
There are a few limitations to the used package, but that doesn't seem
to matter for our use case (linking compiler-rt for use with ld.lld):
* no index is created
* long filenames are truncated
* no support for archives bigger than 4GB
-rw-r--r-- | .circleci/config.yml | 2 | ||||
-rw-r--r-- | Gopkg.lock | 9 | ||||
-rw-r--r-- | builtins.go | 48 | ||||
-rw-r--r-- | commands.go | 1 | ||||
-rw-r--r-- | commands_macos.go | 1 |
5 files changed, 51 insertions, 10 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index bc71b59d1..adb28790b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -154,7 +154,6 @@ commands: name: "Create LLVM symlinks" command: | ln -s $PWD/llvm-build/bin/clang-8 /go/bin/clang-8 - ln -s $PWD/llvm-build/bin/llvm-ar /go/bin/llvm-ar-8 ln -s $PWD/llvm-build/bin/ld.lld /go/bin/ld.lld-8 ln -s $PWD/llvm-build/bin/wasm-ld /go/bin/wasm-ld-8 - dep @@ -220,7 +219,6 @@ commands: name: "Create LLVM symlinks" command: | ln -s $PWD/llvm-build/bin/clang-8 /usr/local/bin/clang-8 - ln -s $PWD/llvm-build/bin/llvm-ar /usr/local/bin/llvm-ar - run: name: "Install Go dependencies" command: dep ensure --vendor-only diff --git a/Gopkg.lock b/Gopkg.lock index 4cf9b0f8e..e6e7dba1e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,6 +3,14 @@ [[projects]] branch = "master" + digest = "1:06519a2ec1d59040eaccec40206f9d0b59dc662db2a032f974d6d6b9a2bcb839" + name = "github.com/blakesmith/ar" + packages = ["."] + pruneopts = "UT" + revision = "8bd4349a67f2533b078dbc524689d15dba0f4659" + +[[projects]] + branch = "master" digest = "1:00b45e06c7843541372fc17d982242bd6adfc2fc382b6f2e9ef9ce53d87a50b9" name = "github.com/marcinbor85/gohex" packages = ["."] @@ -33,6 +41,7 @@ analyzer-name = "dep" analyzer-version = 1 input-imports = [ + "github.com/blakesmith/ar", "github.com/marcinbor85/gohex", "golang.org/x/tools/go/ast/astutil", "golang.org/x/tools/go/ssa", diff --git a/builtins.go b/builtins.go index 2ec155884..a34001a77 100644 --- a/builtins.go +++ b/builtins.go @@ -1,11 +1,16 @@ package main import ( + "errors" + "io" "io/ioutil" "os" "os/exec" "path/filepath" "strings" + "time" + + "github.com/blakesmith/ar" ) // These are the GENERIC_SOURCES according to CMakeList.txt. @@ -246,14 +251,45 @@ func compileBuiltins(target string, callback func(path string) error) error { } // Put all builtins in an archive to link as a static library. + // Note: this does not create a symbol index, but ld.lld doesn't seem to + // care. arpath := filepath.Join(dir, "librt.a") - cmd := exec.Command(commands["ar"], append([]string{"cr", arpath}, objs...)...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Dir = dir - err = cmd.Run() + arfile, err := os.Create(arpath) + if err != nil { + return err + } + defer arfile.Close() + arwriter := ar.NewWriter(arfile) + err = arwriter.WriteGlobalHeader() if err != nil { - return &commandError{"failed to make static library", arpath, err} + return &os.PathError{"write ar header", arpath, err} + } + for _, objpath := range objs { + name := filepath.Base(objpath) + objfile, err := os.Open(objpath) + if err != nil { + return err + } + defer objfile.Close() + st, err := objfile.Stat() + if err != nil { + return err + } + arwriter.WriteHeader(&ar.Header{ + Name: name, + ModTime: time.Unix(0, 0), + Uid: 0, + Gid: 0, + Mode: 0644, + Size: st.Size(), + }) + n, err := io.Copy(arwriter, objfile) + if err != nil { + return err + } + if n != st.Size() { + return errors.New("file modified during ar creation: " + arpath) + } } // Give the caller the resulting file. The callback must copy the file, diff --git a/commands.go b/commands.go index 8fb9d13da..a975b5b2c 100644 --- a/commands.go +++ b/commands.go @@ -4,7 +4,6 @@ package main // commands used by the compilation process might have different file names on Linux than those used on macOS. var commands = map[string]string{ - "ar": "llvm-ar-8", "clang": "clang-8", "ld.lld": "ld.lld-8", "wasm-ld": "wasm-ld-8", diff --git a/commands_macos.go b/commands_macos.go index e457ba886..9ec428ec6 100644 --- a/commands_macos.go +++ b/commands_macos.go @@ -4,7 +4,6 @@ package main // commands used by the compilation process might have different file names on macOS than those used on Linux. var commands = map[string]string{ - "ar": "llvm-ar", "clang": "clang-8", "ld.lld": "ld.lld", "wasm-ld": "wasm-ld", |