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 /builtins.go | |
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
Diffstat (limited to 'builtins.go')
-rw-r--r-- | builtins.go | 48 |
1 files changed, 42 insertions, 6 deletions
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, |