aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtins.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-04-07 15:40:03 +0200
committerRon Evans <[email protected]>2019-04-11 11:53:58 +0200
commit315cd4059fd38be4c078a5974556e5d120d1662a (patch)
tree934a64bc4834ca751a7c66d2c5caa1fd83f94674 /builtins.go
parent078dd9ff5236e40bfd530f8418d72916ce111e33 (diff)
downloadtinygo-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.go48
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,