cgo: Add LDFlags support
Этот коммит содержится в:
родитель
b9fd6cee6f
коммит
726d735ad3
8 изменённых файлов: 46 добавлений и 18 удалений
|
@ -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 {
|
||||
|
|
20
cgo/cgo.go
20
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
|
||||
|
|
|
@ -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
|
||||
|
|
7
cgo/testdata/flags.go
предоставленный
7
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"
|
||||
|
||||
|
|
1
cgo/testdata/flags.out.go
предоставленный
1
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче