Merge pull request #137 from xushiwei/q

build: PkgLinkExtern
This commit is contained in:
xushiwei
2024-05-09 17:43:44 +08:00
committed by GitHub
4 changed files with 52 additions and 24 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

@@ -123,9 +123,10 @@ type instrOrValue interface {
const (
PkgNormal = iota
PkgLLGo
PkgNoInit // noinit: a package that don't need to be initialized
PkgDeclOnly // decl: a package that only have declarations
PkgLinkIR // link llvm ir (.ll)
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
// case "link:bc":
// return PkgLinkBitCode
return PkgLinkIR, ""
case "decl":
return PkgDeclOnly
return PkgDeclOnly, ""
case "noinit":
return PkgNoInit
return PkgNoInit, ""
default:
// case "link:bc":
// return PkgLinkBitCode
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() {
@@ -258,7 +267,8 @@ func buildPkg(prog llssa.Program, aPkg *aPackage, mode Mode, verbose bool) {
if verbose {
fmt.Fprintln(os.Stderr, pkgPath)
}
if pkgPath == "unsafe" { // TODO(xsw): maybe can remove this special case
if canSkipToBuild(pkgPath) {
pkg.ExportFile = ""
return
}
ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax)
@@ -270,6 +280,16 @@ func buildPkg(prog llssa.Program, aPkg *aPackage, mode Mode, verbose bool) {
aPkg.LPkg = ret
}
func canSkipToBuild(pkgPath string) bool {
switch pkgPath {
case "unsafe", "runtime", "errors", "sync", "sync/atomic":
return true
default:
return strings.HasPrefix(pkgPath, "internal/") ||
strings.HasPrefix(pkgPath, "runtime/internal/")
}
}
type aPackage struct {
*packages.Package
SSA *ssa.Package