build: fix linking args and llgo install
This commit is contained in:
@@ -204,19 +204,16 @@ func Do(args []string, conf *Config) {
|
|||||||
ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0}
|
ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0}
|
||||||
pkgs := buildAllPkgs(ctx, initial, verbose)
|
pkgs := buildAllPkgs(ctx, initial, verbose)
|
||||||
|
|
||||||
var llFiles []string
|
|
||||||
dpkg := buildAllPkgs(ctx, altPkgs[noRt:], verbose)
|
dpkg := buildAllPkgs(ctx, altPkgs[noRt:], verbose)
|
||||||
|
var linkArgs []string
|
||||||
for _, pkg := range dpkg {
|
for _, pkg := range dpkg {
|
||||||
if !strings.HasSuffix(pkg.ExportFile, ".ll") {
|
linkArgs = append(linkArgs, pkg.LinkArgs...)
|
||||||
continue
|
|
||||||
}
|
|
||||||
llFiles = append(llFiles, pkg.ExportFile)
|
|
||||||
}
|
}
|
||||||
if mode != ModeBuild {
|
if mode != ModeBuild {
|
||||||
nErr := 0
|
nErr := 0
|
||||||
for _, pkg := range initial {
|
for _, pkg := range initial {
|
||||||
if pkg.Name == "main" {
|
if pkg.Name == "main" {
|
||||||
nErr += linkMainPkg(ctx, pkg, pkgs, llFiles, conf, mode, verbose)
|
nErr += linkMainPkg(ctx, pkg, pkgs, linkArgs, conf, mode, verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nErr > 0 {
|
if nErr > 0 {
|
||||||
@@ -287,14 +284,14 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
|
|||||||
pkg.ExportFile = ""
|
pkg.ExportFile = ""
|
||||||
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
|
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
|
||||||
if len(pkg.GoFiles) > 0 {
|
if len(pkg.GoFiles) > 0 {
|
||||||
cgoParts, err := buildPkg(ctx, aPkg, verbose)
|
cgoLdflags, err := buildPkg(ctx, aPkg, verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
linkParts := concatPkgLinkFiles(ctx, pkg, verbose)
|
linkParts := concatPkgLinkFiles(ctx, pkg, verbose)
|
||||||
allParts := append(linkParts, cgoParts...)
|
allParts := append(linkParts, cgoLdflags...)
|
||||||
allParts = append(allParts, pkg.ExportFile)
|
allParts = append(allParts, pkg.ExportFile)
|
||||||
pkg.ExportFile = " " + strings.Join(allParts, " ")
|
aPkg.LinkArgs = allParts
|
||||||
} else {
|
} else {
|
||||||
// panic("todo")
|
// panic("todo")
|
||||||
// TODO(xsw): support packages out of llgo
|
// TODO(xsw): support packages out of llgo
|
||||||
@@ -322,48 +319,43 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
|
|||||||
panic(fmt.Sprintf("'%s' cannot locate the external library", param))
|
panic(fmt.Sprintf("'%s' cannot locate the external library", param))
|
||||||
}
|
}
|
||||||
|
|
||||||
command := ""
|
pkgLinkArgs := make([]string, 0, 3)
|
||||||
if expd[0] == '-' {
|
if expd[0] == '-' {
|
||||||
command += " " + expd
|
pkgLinkArgs = append(pkgLinkArgs, strings.Split(expd, " ")...)
|
||||||
} else {
|
} else {
|
||||||
linkFile := expd
|
linkFile := expd
|
||||||
dir, lib := filepath.Split(linkFile)
|
dir, lib := filepath.Split(linkFile)
|
||||||
command = " -l " + lib
|
pkgLinkArgs = append(pkgLinkArgs, "-l"+lib)
|
||||||
if dir != "" {
|
if dir != "" {
|
||||||
command += " -L " + dir[:len(dir)-1]
|
pkgLinkArgs = append(pkgLinkArgs, "-L"+dir)
|
||||||
ctx.nLibdir++
|
ctx.nLibdir++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := clangCheck.CheckLinkArgs(command); err != nil {
|
if err := clangCheck.CheckLinkArgs(pkgLinkArgs); err != nil {
|
||||||
panic(fmt.Sprintf("test link args '%s' failed\n\texpanded to: %s\n\tresolved to: %v\n\terror: %v", param, expd, command, err))
|
panic(fmt.Sprintf("test link args '%s' failed\n\texpanded to: %s\n\tresolved to: %v\n\terror: %v", param, expd, pkgLinkArgs, err))
|
||||||
}
|
|
||||||
if isSingleLinkFile(pkg.ExportFile) {
|
|
||||||
pkg.ExportFile = command + " " + pkg.ExportFile
|
|
||||||
} else {
|
|
||||||
pkg.ExportFile = command + pkg.ExportFile
|
|
||||||
}
|
}
|
||||||
|
aPkg.LinkArgs = append(aPkg.LinkArgs, pkgLinkArgs...)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
cgoParts, err := buildPkg(ctx, aPkg, verbose)
|
cgoLdflags, err := buildPkg(ctx, aPkg, verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
allParts := append(cgoParts, pkg.ExportFile)
|
aPkg.LinkArgs = append(cgoLdflags, pkg.ExportFile)
|
||||||
pkg.ExportFile = " " + strings.Join(allParts, " ")
|
|
||||||
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime, prog.NeedPyInit)
|
setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime, prog.NeedPyInit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles []string, conf *Config, mode Mode, verbose bool) (nErr int) {
|
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, linkArgs []string, conf *Config, mode Mode, verbose bool) (nErr int) {
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
name := path.Base(pkgPath)
|
name := path.Base(pkgPath)
|
||||||
app := conf.OutFile
|
app := conf.OutFile
|
||||||
if app == "" {
|
if app == "" {
|
||||||
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
||||||
}
|
}
|
||||||
args := make([]string, 0, len(pkg.Imports)+len(llFiles)+16)
|
args := make([]string, 0, len(pkg.Imports)+len(linkArgs)+16)
|
||||||
args = append(
|
args = append(
|
||||||
args,
|
args,
|
||||||
"-o", app,
|
"-o", app,
|
||||||
@@ -396,9 +388,14 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles
|
|||||||
}
|
}
|
||||||
needRuntime := false
|
needRuntime := false
|
||||||
needPyInit := false
|
needPyInit := false
|
||||||
|
pkgsMap := make(map[*packages.Package]*aPackage, len(pkgs))
|
||||||
|
for _, v := range pkgs {
|
||||||
|
pkgsMap[v.Package] = v
|
||||||
|
}
|
||||||
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) {
|
||||||
if p.ExportFile != "" { // skip packages that only contain declarations
|
if p.ExportFile != "" { // skip packages that only contain declarations
|
||||||
args = appendLinkFiles(args, p.ExportFile)
|
aPkg := pkgsMap[p]
|
||||||
|
args = append(args, aPkg.LinkArgs...)
|
||||||
need1, need2 := isNeedRuntimeOrPyInit(p)
|
need1, need2 := isNeedRuntimeOrPyInit(p)
|
||||||
if !needRuntime {
|
if !needRuntime {
|
||||||
needRuntime = need1
|
needRuntime = need1
|
||||||
@@ -419,9 +416,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles
|
|||||||
|
|
||||||
dirty := false
|
dirty := false
|
||||||
if needRuntime {
|
if needRuntime {
|
||||||
for _, file := range llFiles {
|
args = append(args, linkArgs...)
|
||||||
args = appendLinkFiles(args, file)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dirty = true
|
dirty = true
|
||||||
fn := aPkg.LPkg.FuncOf(cl.RuntimeInit)
|
fn := aPkg.LPkg.FuncOf(cl.RuntimeInit)
|
||||||
@@ -495,7 +490,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoParts []string, err error) {
|
func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoLdflags []string, err error) {
|
||||||
pkg := aPkg.Package
|
pkg := aPkg.Package
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
if debugBuild || verbose {
|
if debugBuild || verbose {
|
||||||
@@ -521,7 +516,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoParts []string, er
|
|||||||
cl.SetDebug(0)
|
cl.SetDebug(0)
|
||||||
}
|
}
|
||||||
check(err)
|
check(err)
|
||||||
cgoParts, err = buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose)
|
cgoLdflags, err = buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, verbose)
|
||||||
if needLLFile(ctx.mode) {
|
if needLLFile(ctx.mode) {
|
||||||
pkg.ExportFile += ".ll"
|
pkg.ExportFile += ".ll"
|
||||||
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
|
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
|
||||||
@@ -572,6 +567,8 @@ type aPackage struct {
|
|||||||
SSA *ssa.Package
|
SSA *ssa.Package
|
||||||
AltPkg *packages.Cached
|
AltPkg *packages.Cached
|
||||||
LPkg llssa.Package
|
LPkg llssa.Package
|
||||||
|
|
||||||
|
LinkArgs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func allPkgs(ctx *context, initial []*packages.Package, verbose bool) (all []*aPackage, errs []*packages.Package) {
|
func allPkgs(ctx *context, initial []*packages.Package, verbose bool) (all []*aPackage, errs []*packages.Package) {
|
||||||
@@ -590,7 +587,7 @@ func allPkgs(ctx *context, initial []*packages.Package, verbose bool) (all []*aP
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
all = append(all, &aPackage{p, ssaPkg, altPkg, nil})
|
all = append(all, &aPackage{p, ssaPkg, altPkg, nil, nil})
|
||||||
} else {
|
} else {
|
||||||
errs = append(errs, p)
|
errs = append(errs, p)
|
||||||
}
|
}
|
||||||
@@ -692,18 +689,6 @@ func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendLinkFiles(args []string, file string) []string {
|
|
||||||
if isSingleLinkFile(file) {
|
|
||||||
return append(args, file)
|
|
||||||
}
|
|
||||||
// TODO(xsw): consider filename with spaces
|
|
||||||
return append(args, strings.Split(file[1:], " ")...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isSingleLinkFile(ret string) bool {
|
|
||||||
return len(ret) > 0 && ret[0] != ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
func concatPkgLinkFiles(ctx *context, pkg *packages.Package, verbose bool) (parts []string) {
|
func concatPkgLinkFiles(ctx *context, pkg *packages.Package, verbose bool) (parts []string) {
|
||||||
llgoPkgLinkFiles(ctx, pkg, func(linkFile string) {
|
llgoPkgLinkFiles(ctx, pkg, func(linkFile string) {
|
||||||
parts = append(parts, linkFile)
|
parts = append(parts, linkFile)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ static void* _Cmalloc(size_t size) {
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string][]string, verbose bool) (cgoParts []string, err error) {
|
func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string][]string, verbose bool) (cgoLdflags []string, err error) {
|
||||||
cfiles, preambles, cdecls, err := parseCgo_(pkg, files)
|
cfiles, preambles, cdecls, err := parseCgo_(pkg, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -84,7 +84,7 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string
|
|||||||
}
|
}
|
||||||
for _, cfile := range cfiles {
|
for _, cfile := range cfiles {
|
||||||
clFile(ctx, cflags, cfile, pkg.ExportFile, func(linkFile string) {
|
clFile(ctx, cflags, cfile, pkg.ExportFile, func(linkFile string) {
|
||||||
cgoParts = append(cgoParts, linkFile)
|
cgoLdflags = append(cgoLdflags, linkFile)
|
||||||
}, verbose)
|
}, verbose)
|
||||||
}
|
}
|
||||||
re := regexp.MustCompile(`^(_cgo_[^_]+_Cfunc_)(.*)$`)
|
re := regexp.MustCompile(`^(_cgo_[^_]+_Cfunc_)(.*)$`)
|
||||||
@@ -117,10 +117,12 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
clFile(ctx, cflags, tmpName, pkg.ExportFile, func(linkFile string) {
|
clFile(ctx, cflags, tmpName, pkg.ExportFile, func(linkFile string) {
|
||||||
cgoParts = append(cgoParts, linkFile)
|
cgoLdflags = append(cgoLdflags, linkFile)
|
||||||
}, verbose)
|
}, verbose)
|
||||||
}
|
}
|
||||||
cgoParts = append(cgoParts, ldflags...)
|
for _, ldflag := range ldflags {
|
||||||
|
cgoLdflags = append(cgoLdflags, strings.Split(ldflag, " ")...)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckLinkArgs(args string) error {
|
func CheckLinkArgs(cmdArgs []string) error {
|
||||||
cmdArgs := strings.Split(args, " ")
|
|
||||||
cmd := exec.Command("clang")
|
cmd := exec.Command("clang")
|
||||||
nul := "/dev/null"
|
nul := "/dev/null"
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
|
|||||||
Reference in New Issue
Block a user