build: PkgLinkExtern
This commit is contained in:
@@ -140,16 +140,19 @@ func TestPkgNoInit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPkgKind(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)
|
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)
|
t.Fatal("pkgKind:", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPkgKindOf(t *testing.T) {
|
func TestPkgKindOf(t *testing.T) {
|
||||||
if v := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
|
if v, _ := PkgKindOf(types.Unsafe); v != PkgDeclOnly {
|
||||||
t.Fatal("PkgKindOf unsafe:", v)
|
t.Fatal("PkgKindOf unsafe:", v)
|
||||||
}
|
}
|
||||||
pkg := types.NewPackage("foo", "foo")
|
pkg := types.NewPackage("foo", "foo")
|
||||||
@@ -158,7 +161,7 @@ func TestPkgKindOf(t *testing.T) {
|
|||||||
0, pkg, "LLGoPackage", types.Typ[types.String],
|
0, pkg, "LLGoPackage", types.Typ[types.String],
|
||||||
constant.MakeString("noinit")),
|
constant.MakeString("noinit")),
|
||||||
)
|
)
|
||||||
if v := PkgKindOf(pkg); v != PkgNoInit {
|
if v, _ := PkgKindOf(pkg); v != PkgNoInit {
|
||||||
t.Fatal("PkgKindOf foo:", v)
|
t.Fatal("PkgKindOf foo:", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,9 +123,10 @@ type instrOrValue interface {
|
|||||||
const (
|
const (
|
||||||
PkgNormal = iota
|
PkgNormal = iota
|
||||||
PkgLLGo
|
PkgLLGo
|
||||||
PkgNoInit // noinit: a package that don't need to be initialized
|
PkgNoInit // noinit: a package that don't need to be initialized
|
||||||
PkgDeclOnly // decl: a package that only have declarations
|
PkgDeclOnly // decl: a package that only have declarations
|
||||||
PkgLinkIR // link llvm ir (.ll)
|
PkgLinkIR // link llvm ir (.ll)
|
||||||
|
PkgLinkExtern // link external object (.a/.so/.dll/.dylib/etc.)
|
||||||
// PkgLinkBitCode // link bitcode (.bc)
|
// PkgLinkBitCode // link bitcode (.bc)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
32
cl/import.go
32
cl/import.go
@@ -77,44 +77,48 @@ func (p *pkgSymInfo) initLinknames(ctx *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PkgKindOf returns the kind of a package.
|
// PkgKindOf returns the kind of a package.
|
||||||
func PkgKindOf(pkg *types.Package) int {
|
func PkgKindOf(pkg *types.Package) (int, string) {
|
||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
kind := pkgKindByScope(scope)
|
kind, param := pkgKindByScope(scope)
|
||||||
if kind == PkgNormal {
|
if kind == PkgNormal {
|
||||||
kind = pkgKindByPath(pkg.Path())
|
kind = pkgKindByPath(pkg.Path())
|
||||||
}
|
}
|
||||||
return kind
|
return kind, param
|
||||||
}
|
}
|
||||||
|
|
||||||
// decl: a package that only contains declarations
|
// decl: a package that only contains declarations
|
||||||
// noinit: a package that does not need to be initialized
|
// noinit: a package that does not need to be initialized
|
||||||
func pkgKind(v string) int {
|
func pkgKind(v string) (int, string) {
|
||||||
switch v {
|
switch v {
|
||||||
case "link":
|
case "link":
|
||||||
return PkgLinkIR
|
return PkgLinkIR, ""
|
||||||
// case "link:bc":
|
|
||||||
// return PkgLinkBitCode
|
|
||||||
case "decl":
|
case "decl":
|
||||||
return PkgDeclOnly
|
return PkgDeclOnly, ""
|
||||||
case "noinit":
|
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, ok := scope.Lookup("LLGoPackage").(*types.Const); ok {
|
||||||
if v := v.Val(); v.Kind() == constant.String {
|
if v := v.Val(); v.Kind() == constant.String {
|
||||||
return pkgKind(constant.StringVal(v))
|
return pkgKind(constant.StringVal(v))
|
||||||
}
|
}
|
||||||
return PkgLLGo
|
return PkgLLGo, ""
|
||||||
}
|
}
|
||||||
return PkgNormal
|
return PkgNormal, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
func (p *context) importPkg(pkg *types.Package, i *pkgInfo) {
|
||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
kind := pkgKindByScope(scope)
|
kind, _ := pkgKindByScope(scope)
|
||||||
if kind == PkgNormal {
|
if kind == PkgNormal {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,12 +167,12 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
}
|
}
|
||||||
for _, aPkg := range pkgs {
|
for _, aPkg := range pkgs {
|
||||||
pkg := aPkg.Package
|
pkg := aPkg.Package
|
||||||
switch kind := cl.PkgKindOf(pkg.Types); kind {
|
switch kind, param := cl.PkgKindOf(pkg.Types); kind {
|
||||||
case cl.PkgDeclOnly:
|
case cl.PkgDeclOnly:
|
||||||
// skip packages that only contain declarations
|
// skip packages that only contain declarations
|
||||||
// and set no export file
|
// and set no export file
|
||||||
pkg.ExportFile = ""
|
pkg.ExportFile = ""
|
||||||
case cl.PkgLinkIR: // cl.PkgLinkBitCode:
|
case cl.PkgLinkIR:
|
||||||
// skip packages that don't need to be compiled but need to be linked
|
// skip packages that don't need to be compiled but need to be linked
|
||||||
pkgPath := pkg.PkgPath
|
pkgPath := pkg.PkgPath
|
||||||
if isPkgInLLGo(pkgPath) {
|
if isPkgInLLGo(pkgPath) {
|
||||||
@@ -180,6 +180,15 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
|
|||||||
} else {
|
} else {
|
||||||
panic("todo")
|
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:
|
default:
|
||||||
buildPkg(prog, aPkg, mode, verbose)
|
buildPkg(prog, aPkg, mode, verbose)
|
||||||
if prog.NeedRuntime() {
|
if prog.NeedRuntime() {
|
||||||
|
|||||||
Reference in New Issue
Block a user