From 315cd4059fd38be4c078a5974556e5d120d1662a Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 7 Apr 2019 15:40:03 +0200 Subject: [PATCH] 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 --- .circleci/config.yml | 2 -- Gopkg.lock | 9 +++++++++ builtins.go | 48 ++++++++++++++++++++++++++++++++++++++------ commands.go | 1 - commands_macos.go | 1 - 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bc71b59d..adb28790 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 4cf9b0f8..e6e7dba1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,14 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + digest = "1:06519a2ec1d59040eaccec40206f9d0b59dc662db2a032f974d6d6b9a2bcb839" + name = "github.com/blakesmith/ar" + packages = ["."] + pruneopts = "UT" + revision = "8bd4349a67f2533b078dbc524689d15dba0f4659" + [[projects]] branch = "master" digest = "1:00b45e06c7843541372fc17d982242bd6adfc2fc382b6f2e9ef9ce53d87a50b9" @@ -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 2ec15588..a34001a7 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 &commandError{"failed to make static library", arpath, err} + return err + } + defer arfile.Close() + arwriter := ar.NewWriter(arfile) + err = arwriter.WriteGlobalHeader() + if err != nil { + 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 8fb9d13d..a975b5b2 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 e457ba88..9ec428ec 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",