diff options
author | Lucas Teske <[email protected]> | 2020-05-20 13:05:25 -0300 |
---|---|---|
committer | Ayke <[email protected]> | 2020-05-21 00:57:19 +0200 |
commit | 726d735ad35f1c1ea0ffc59a25a44e2d167a8ccf (patch) | |
tree | bd609c09ef2bc58f72b21ff9d2f6f2b5132edcfc | |
parent | b9fd6cee6f0e427d1f2317734f49411e190cec75 (diff) | |
download | tinygo-726d735ad35f1c1ea0ffc59a25a44e2d167a8ccf.tar.gz tinygo-726d735ad35f1c1ea0ffc59a25a44e2d167a8ccf.zip |
cgo: Add LDFlags support
-rw-r--r-- | builder/build.go | 6 | ||||
-rw-r--r-- | cgo/cgo.go | 20 | ||||
-rw-r--r-- | cgo/cgo_test.go | 2 | ||||
-rw-r--r-- | cgo/testdata/flags.go | 7 | ||||
-rw-r--r-- | cgo/testdata/flags.out.go | 1 | ||||
-rw-r--r-- | compiler/compiler.go | 16 | ||||
-rw-r--r-- | loader/loader.go | 4 | ||||
-rw-r--r-- | src/testing/testing.go | 8 |
8 files changed, 46 insertions, 18 deletions
diff --git a/builder/build.go b/builder/build.go index e67cb2bff..f8247f8b5 100644 --- a/builder/build.go +++ b/builder/build.go @@ -32,7 +32,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri if err != nil { return err } - mod, extraFiles, errs := compiler.Compile(pkgName, machine, config) + mod, extraFiles, extraLDFlags, errs := compiler.Compile(pkgName, machine, config) if errs != nil { return newMultiError(errs) } @@ -187,6 +187,10 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri ldflags = append(ldflags, outpath) } + if len(extraLDFlags) > 0 { + ldflags = append(ldflags, extraLDFlags...) + } + // Link the object files together. err = link(config.Target.Linker, ldflags...) if err != nil { diff --git a/cgo/cgo.go b/cgo/cgo.go index d6470a522..7cc61b9ce 100644 --- a/cgo/cgo.go +++ b/cgo/cgo.go @@ -41,6 +41,7 @@ type cgoPackage struct { elaboratedTypes map[string]*elaboratedTypeInfo enums map[string]enumInfo anonStructNum int + ldflags []string } // constantInfo stores some information about a CGo constant found by libclang @@ -156,7 +157,7 @@ typedef unsigned long long _Cgo_ulonglong; // newly created *ast.File that should be added to the list of to-be-parsed // files. If there is one or more error, it returns these in the []error slice // but still modifies the AST. -func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string) (*ast.File, []error) { +func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string) (*ast.File, []string, []error) { p := &cgoPackage{ dir: dir, fset: fset, @@ -183,7 +184,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string // Find the absolute path for this package. packagePath, err := filepath.Abs(fset.File(files[0].Pos()).Name()) if err != nil { - return nil, []error{ + return nil, nil, []error{ scanner.Error{ Pos: fset.Position(files[0].Pos()), Msg: "cgo: cannot find absolute path: " + err.Error(), // TODO: wrap this error @@ -359,6 +360,19 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string } makePathsAbsolute(flags, packagePath) cflags = append(cflags, flags...) + case "LDFLAGS": + flags, err := shlex.Split(value) + if err != nil { + // TODO: find the exact location where the error happened. + p.addErrorAfter(comment.Slash, comment.Text[:lineStart+colon+1], "failed to parse flags in #cgo line: "+err.Error()) + continue + } + if err := checkLinkerFlags(name, flags); err != nil { + p.addErrorAfter(comment.Slash, comment.Text[:lineStart+colon+1], err.Error()) + continue + } + makePathsAbsolute(flags, packagePath) + p.ldflags = append(p.ldflags, flags...) default: startPos := strings.LastIndex(line[4:colon], name) + 4 p.addErrorAfter(comment.Slash, comment.Text[:lineStart+startPos], "invalid #cgo line: "+name) @@ -412,7 +426,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string // Print the newly generated in-memory AST, for debugging. //ast.Print(fset, p.generated) - return p.generated, p.errors + return p.generated, p.ldflags, p.errors } // makePathsAbsolute converts some common path compiler flags (-I, -L) from diff --git a/cgo/cgo_test.go b/cgo/cgo_test.go index 5673ebad8..745824154 100644 --- a/cgo/cgo_test.go +++ b/cgo/cgo_test.go @@ -50,7 +50,7 @@ func TestCGo(t *testing.T) { } // Process the AST with CGo. - cgoAST, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags) + cgoAST, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags) // Check the AST for type errors. var typecheckErrors []error diff --git a/cgo/testdata/flags.go b/cgo/testdata/flags.go index d52bbc5b9..012fad78d 100644 --- a/cgo/testdata/flags.go +++ b/cgo/testdata/flags.go @@ -21,6 +21,13 @@ package main #if defined(NOTDEFINED) #warning flag must not be defined #endif + +// Check Compiler flags +#cgo LDFLAGS: -lc + +// This flag is not valid ldflags +#cgo LDFLAGS: -does-not-exists + */ import "C" diff --git a/cgo/testdata/flags.out.go b/cgo/testdata/flags.out.go index 0bcad0d5a..4eb70112a 100644 --- a/cgo/testdata/flags.out.go +++ b/cgo/testdata/flags.out.go @@ -1,6 +1,7 @@ // CGo errors: // testdata/flags.go:5:7: invalid #cgo line: NOFLAGS // testdata/flags.go:8:13: invalid flag: -fdoes-not-exist +// testdata/flags.go:29:14: invalid flag: -does-not-exists package main diff --git a/compiler/compiler.go b/compiler/compiler.go index e21f4a4e6..5ed85c053 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -103,7 +103,7 @@ func NewTargetMachine(config *compileopts.Config) (llvm.TargetMachine, error) { // violation. Eventually, this Compile function should only compile a single // package and not the whole program, and loading of the program (including CGo // processing) should be moved outside the compiler package. -func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Config) (llvm.Module, []string, []error) { +func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Config) (mod llvm.Module, extrafiles []string, extraldflags []string, errors []error) { c := &compilerContext{ Config: config, difiles: make(map[string]llvm.Metadata), @@ -148,7 +148,7 @@ func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Con wd, err := os.Getwd() if err != nil { - return c.mod, nil, []error{err} + return c.mod, nil, nil, []error{err} } lprogram := &loader.Program{ Build: &build.Context{ @@ -211,14 +211,14 @@ func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Con if strings.HasSuffix(pkgName, ".go") { _, err = lprogram.ImportFile(pkgName) if err != nil { - return c.mod, nil, []error{err} + return c.mod, nil, nil, []error{err} } } else { _, err = lprogram.Import(pkgName, wd, token.Position{ Filename: "build command-line-arguments", }) if err != nil { - return c.mod, nil, []error{err} + return c.mod, nil, nil, []error{err} } } @@ -226,12 +226,12 @@ func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Con Filename: "build default import", }) if err != nil { - return c.mod, nil, []error{err} + return c.mod, nil, nil, []error{err} } err = lprogram.Parse(c.TestConfig.CompileTestBinary) if err != nil { - return c.mod, nil, []error{err} + return c.mod, nil, nil, []error{err} } c.ir = ir.NewProgram(lprogram, pkgName) @@ -239,7 +239,7 @@ func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Con // Run a simple dead code elimination pass. err = c.ir.SimpleDCE() if err != nil { - return c.mod, nil, []error{err} + return c.mod, nil, nil, []error{err} } // Initialize debug information. @@ -383,7 +383,7 @@ func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Con } } - return c.mod, extraFiles, c.diagnostics + return c.mod, extraFiles, lprogram.LDFlags, c.diagnostics } // getLLVMRuntimeType obtains a named type from the runtime package and returns diff --git a/loader/loader.go b/loader/loader.go index 5682bfa4a..28ade8d2e 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -31,6 +31,7 @@ type Program struct { Dir string // current working directory (for error reporting) TINYGOROOT string // root of the TinyGo installation or root of the source code CFlags []string + LDFlags []string ClangHeaders string } @@ -425,11 +426,12 @@ func (p *Package) parseFiles(includeTests bool) ([]*ast.File, error) { if p.ClangHeaders != "" { cflags = append(cflags, "-Xclang", "-internal-isystem", "-Xclang", p.ClangHeaders) } - generated, errs := cgo.Process(files, p.Program.Dir, p.fset, cflags) + generated, ldflags, errs := cgo.Process(files, p.Program.Dir, p.fset, cflags) if errs != nil { fileErrs = append(fileErrs, errs...) } files = append(files, generated) + p.LDFlags = append(p.LDFlags, ldflags...) } if len(fileErrs) != 0 { return nil, Errors{p, fileErrs} diff --git a/src/testing/testing.go b/src/testing/testing.go index f476514f6..ca353c608 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -20,10 +20,10 @@ import ( type common struct { output io.Writer - failed bool // Test or benchmark has failed. - skipped bool // Test of benchmark has been skipped. - finished bool // Test function has completed. - name string // Name of test or benchmark. + failed bool // Test or benchmark has failed. + skipped bool // Test of benchmark has been skipped. + finished bool // Test function has completed. + name string // Name of test or benchmark. } // TB is the interface common to T and B. |