From 8e5fff6c5fa460dc001775930ac708895441d189 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Sun, 17 Nov 2024 16:19:49 +0800 Subject: [PATCH] build: fix linking args and llgo install --- internal/build/build.go | 73 +++++++++++++++----------------------- internal/build/cgo.go | 10 +++--- xtool/clang/check/check.go | 3 +- 3 files changed, 36 insertions(+), 50 deletions(-) diff --git a/internal/build/build.go b/internal/build/build.go index ca7cd220..b7be325e 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -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} pkgs := buildAllPkgs(ctx, initial, verbose) - var llFiles []string dpkg := buildAllPkgs(ctx, altPkgs[noRt:], verbose) + var linkArgs []string for _, pkg := range dpkg { - if !strings.HasSuffix(pkg.ExportFile, ".ll") { - continue - } - llFiles = append(llFiles, pkg.ExportFile) + linkArgs = append(linkArgs, pkg.LinkArgs...) } if mode != ModeBuild { nErr := 0 for _, pkg := range initial { 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 { @@ -287,14 +284,14 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs pkg.ExportFile = "" case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule: if len(pkg.GoFiles) > 0 { - cgoParts, err := buildPkg(ctx, aPkg, verbose) + cgoLdflags, err := buildPkg(ctx, aPkg, verbose) if err != nil { panic(err) } linkParts := concatPkgLinkFiles(ctx, pkg, verbose) - allParts := append(linkParts, cgoParts...) + allParts := append(linkParts, cgoLdflags...) allParts = append(allParts, pkg.ExportFile) - pkg.ExportFile = " " + strings.Join(allParts, " ") + aPkg.LinkArgs = allParts } else { // panic("todo") // 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)) } - command := "" + pkgLinkArgs := make([]string, 0, 3) if expd[0] == '-' { - command += " " + expd + pkgLinkArgs = append(pkgLinkArgs, strings.Split(expd, " ")...) } else { linkFile := expd dir, lib := filepath.Split(linkFile) - command = " -l " + lib + pkgLinkArgs = append(pkgLinkArgs, "-l"+lib) if dir != "" { - command += " -L " + dir[:len(dir)-1] + pkgLinkArgs = append(pkgLinkArgs, "-L"+dir) ctx.nLibdir++ } } - if err := clangCheck.CheckLinkArgs(command); 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)) - } - if isSingleLinkFile(pkg.ExportFile) { - pkg.ExportFile = command + " " + pkg.ExportFile - } else { - pkg.ExportFile = command + pkg.ExportFile + 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, pkgLinkArgs, err)) } + aPkg.LinkArgs = append(aPkg.LinkArgs, pkgLinkArgs...) } default: - cgoParts, err := buildPkg(ctx, aPkg, verbose) + cgoLdflags, err := buildPkg(ctx, aPkg, verbose) if err != nil { panic(err) } - allParts := append(cgoParts, pkg.ExportFile) - pkg.ExportFile = " " + strings.Join(allParts, " ") + aPkg.LinkArgs = append(cgoLdflags, pkg.ExportFile) setNeedRuntimeOrPyInit(pkg, prog.NeedRuntime, prog.NeedPyInit) } } 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 name := path.Base(pkgPath) app := conf.OutFile if app == "" { 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, "-o", app, @@ -396,9 +388,14 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles } needRuntime := 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) { 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) if !needRuntime { needRuntime = need1 @@ -419,9 +416,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles dirty := false if needRuntime { - for _, file := range llFiles { - args = appendLinkFiles(args, file) - } + args = append(args, linkArgs...) } else { dirty = true fn := aPkg.LPkg.FuncOf(cl.RuntimeInit) @@ -495,7 +490,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles 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 pkgPath := pkg.PkgPath if debugBuild || verbose { @@ -521,7 +516,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) (cgoParts []string, er cl.SetDebug(0) } 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) { pkg.ExportFile += ".ll" os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644) @@ -572,6 +567,8 @@ type aPackage struct { SSA *ssa.Package AltPkg *packages.Cached LPkg llssa.Package + + LinkArgs []string } 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 } } - all = append(all, &aPackage{p, ssaPkg, altPkg, nil}) + all = append(all, &aPackage{p, ssaPkg, altPkg, nil, nil}) } else { 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) { llgoPkgLinkFiles(ctx, pkg, func(linkFile string) { parts = append(parts, linkFile) diff --git a/internal/build/cgo.go b/internal/build/cgo.go index 02d72ed6..160e2a8f 100644 --- a/internal/build/cgo.go +++ b/internal/build/cgo.go @@ -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) if err != nil { return @@ -84,7 +84,7 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string } for _, cfile := range cfiles { clFile(ctx, cflags, cfile, pkg.ExportFile, func(linkFile string) { - cgoParts = append(cgoParts, linkFile) + cgoLdflags = append(cgoLdflags, linkFile) }, verbose) } re := regexp.MustCompile(`^(_cgo_[^_]+_Cfunc_)(.*)$`) @@ -117,10 +117,12 @@ func buildCgo(ctx *context, pkg *aPackage, files []*ast.File, externs map[string return nil, err } clFile(ctx, cflags, tmpName, pkg.ExportFile, func(linkFile string) { - cgoParts = append(cgoParts, linkFile) + cgoLdflags = append(cgoLdflags, linkFile) }, verbose) } - cgoParts = append(cgoParts, ldflags...) + for _, ldflag := range ldflags { + cgoLdflags = append(cgoLdflags, strings.Split(ldflag, " ")...) + } return } diff --git a/xtool/clang/check/check.go b/xtool/clang/check/check.go index a740a519..b5ae35f0 100644 --- a/xtool/clang/check/check.go +++ b/xtool/clang/check/check.go @@ -7,8 +7,7 @@ import ( "strings" ) -func CheckLinkArgs(args string) error { - cmdArgs := strings.Split(args, " ") +func CheckLinkArgs(cmdArgs []string) error { cmd := exec.Command("clang") nul := "/dev/null" if runtime.GOOS == "windows" {