build: PkgLinkExtern

This commit is contained in:
xushiwei
2024-05-09 14:51:01 +08:00
parent 093af00bbe
commit b133f70b6b
4 changed files with 40 additions and 23 deletions

View File

@@ -140,16 +140,19 @@ func TestPkgNoInit(t *testing.T) {
}
func TestPkgKind(t *testing.T) {
if v := pkgKind("noinit"); v != PkgNoInit {
if v, _ := pkgKind("link: hello.a"); v != PkgLinkExtern {
t.Fatal("pkgKind:", v)
}
if v := pkgKind(""); v != PkgLLGo {
if v, _ := pkgKind("noinit"); v != PkgNoInit {
t.Fatal("pkgKind:", v)
}
if v, _ := pkgKind(""); v != PkgLLGo {
t.Fatal("pkgKind:", v)
}
}
func TestPkgKindOf(t *testing.T) {
if v := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
if v, _ := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
t.Fatal("PkgKindOf unsafe:", v)
}
pkg := types.NewPackage("foo", "foo")
@@ -158,7 +161,7 @@ func TestPkgKindOf(t *testing.T) {
0, pkg, "LLGoPackage", types.Typ[types.String],
constant.MakeString("noinit")),
)
if v := PkgKindOf(pkg); v != PkgNoInit {
if v, _ := PkgKindOf(pkg); v != PkgNoInit {
t.Fatal("PkgKindOf foo:", v)
}
}

View File

@@ -126,6 +126,7 @@ const (
PkgNoInit // noinit: a package that don't need to be initialized
PkgDeclOnly // decl: a package that only have declarations
PkgLinkIR // link llvm ir (.ll)
PkgLinkExtern // link external object (.a/.so/.dll/.dylib/etc.)
// PkgLinkBitCode // link bitcode (.bc)
)

View File

@@ -77,44 +77,48 @@ func (p *pkgSymInfo) initLinknames(ctx *context) {
}
// PkgKindOf returns the kind of a package.
func PkgKindOf(pkg *types.Package) int {
func PkgKindOf(pkg *types.Package) (int, string) {
scope := pkg.Scope()
kind := pkgKindByScope(scope)
kind, param := pkgKindByScope(scope)
if kind == PkgNormal {
kind = pkgKindByPath(pkg.Path())
}
return kind
return kind, param
}
// decl: a package that only contains declarations
// noinit: a package that does not need to be initialized
func pkgKind(v string) int {
func pkgKind(v string) (int, string) {
switch v {
case "link":
return PkgLinkIR
return PkgLinkIR, ""
case "decl":
return PkgDeclOnly, ""
case "noinit":
return PkgNoInit, ""
default:
// case "link:bc":
// return PkgLinkBitCode
case "decl":
return PkgDeclOnly
case "noinit":
return PkgNoInit
if strings.HasPrefix(v, "link:") { // "link: <libpath>"
return PkgLinkExtern, v[5:]
}
return PkgLLGo
}
return PkgLLGo, ""
}
func pkgKindByScope(scope *types.Scope) int {
func pkgKindByScope(scope *types.Scope) (int, string) {
if v, ok := scope.Lookup("LLGoPackage").(*types.Const); ok {
if v := v.Val(); v.Kind() == constant.String {
return pkgKind(constant.StringVal(v))
}
return PkgLLGo
return PkgLLGo, ""
}
return PkgNormal
return PkgNormal, ""
}
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
scope := pkg.Scope()
kind := pkgKindByScope(scope)
kind, _ := pkgKindByScope(scope)
if kind == PkgNormal {
return
}

View File

@@ -167,12 +167,12 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
}
for _, aPkg := range pkgs {
pkg := aPkg.Package
switch kind := cl.PkgKindOf(pkg.Types); kind {
switch kind, param := cl.PkgKindOf(pkg.Types); kind {
case cl.PkgDeclOnly:
// skip packages that only contain declarations
// and set no export file
pkg.ExportFile = ""
case cl.PkgLinkIR: // cl.PkgLinkBitCode:
case cl.PkgLinkIR:
// skip packages that don't need to be compiled but need to be linked
pkgPath := pkg.PkgPath
if isPkgInLLGo(pkgPath) {
@@ -180,6 +180,15 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
} else {
panic("todo")
}
case cl.PkgLinkExtern:
// skip packages that don't need to be compiled but need to be linked with external library
linkFile := os.ExpandEnv(strings.TrimSpace(param))
dir, lib := filepath.Split(linkFile)
command := " -l " + lib
if dir != "" {
command += " -L " + dir
}
pkg.ExportFile = command
default:
buildPkg(prog, aPkg, mode, verbose)
if prog.NeedRuntime() {