diff --git a/cl/compile.go b/cl/compile.go index 954412c9..14cbce34 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -123,6 +123,7 @@ const ( PkgLLGo PkgNoInit // noinit: a package that don't need to be initialized PkgDeclOnly // decl: a package that only have declarations + PkgLinkOnly // link: a package that don't need to be compiled but need to be linked ) type pkgInfo struct { diff --git a/cl/import.go b/cl/import.go index 600abf82..8f5f149f 100644 --- a/cl/import.go +++ b/cl/import.go @@ -58,6 +58,8 @@ func PkgKindOf(pkg *types.Package) int { // noinit: a package that does not need to be initialized func pkgKind(v string) int { switch v { + case "link": + return PkgLinkOnly case "decl": return PkgDeclOnly case "noinit": diff --git a/internal/build/build.go b/internal/build/build.go index 2d39af8e..bb5c64c1 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -163,10 +163,26 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve } fmt.Fprintln(os.Stderr, "cannot build SSA for package", errPkg) } - for _, pkg := range pkgs { - buildPkg(prog, pkg, mode, verbose) - if prog.NeedRuntime() { - setNeedRuntime(pkg.Package) + for _, aPkg := range pkgs { + pkg := aPkg.Package + switch cl.PkgKindOf(pkg.Types) { + case cl.PkgDeclOnly: + // skip packages that only contain declarations + // and set no export file + pkg.ExportFile = "" + case cl.PkgLinkOnly: + // skip packages that don't need to be compiled but need to be linked + pkgPath := pkg.PkgPath + if isPkgInLLGo(pkgPath) { + pkg.ExportFile = strings.TrimSuffix(llgoPkgLinkFile(pkgPath), ".ll") + } else { + panic("todo") + } + default: + buildPkg(prog, aPkg, mode, verbose) + if prog.NeedRuntime() { + setNeedRuntime(pkg) + } } } return @@ -236,12 +252,6 @@ func linkMainPkg(pkg *packages.Package, pkgs []*aPackage, runtimeFiles []string, func buildPkg(prog llssa.Program, aPkg *aPackage, mode Mode, verbose bool) { pkg := aPkg.Package - if cl.PkgKindOf(pkg.Types) == cl.PkgDeclOnly { - // skip packages that only contain declarations - // and set no export file - pkg.ExportFile = "" - return - } pkgPath := pkg.PkgPath if verbose { fmt.Fprintln(os.Stderr, pkgPath) @@ -342,11 +352,10 @@ func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) { func allLinkFiles(rt []*packages.Package) (outFiles []string) { outFiles = make([]string, 0, len(rt)) - root := rootLLGo(rt[0]) packages.Visit(rt, nil, func(p *packages.Package) { pkgPath := p.PkgPath if isRuntimePkg(pkgPath) { - outFile := filepath.Join(root+pkgPath[len(llgoModPath):], "llgo_autogen.ll") + outFile := llgoPkgLinkFile(pkgPath) outFiles = append(outFiles, outFile) } }) @@ -366,16 +375,29 @@ func isRuntimePkg(pkgPath string) bool { return false } -// TODO(xsw): llgo root dir -func rootLLGo(runtime *packages.Package) string { - return runtime.Module.Dir +var ( + rootDir string +) + +func llgoRoot() string { + if rootDir == "" { + root := os.Getenv("LLGOROOT") + if root == "" { + panic("todo: LLGOROOT not set") + } + rootDir, _ = filepath.Abs(root) + } + return rootDir +} + +func llgoPkgLinkFile(pkgPath string) string { + return filepath.Join(llgoRoot()+pkgPath[len(llgoModPath):], "llgo_autogen.ll") } const ( llgoModPath = "github.com/goplus/llgo" ) -/* func isPkgInLLGo(pkgPath string) bool { return isPkgInMod(pkgPath, llgoModPath) } @@ -387,7 +409,6 @@ func isPkgInMod(pkgPath, modPath string) bool { } return false } -*/ func check(err error) { if err != nil {