build: support pkg-config and link args

This commit is contained in:
Li Jie
2024-06-04 16:30:21 +08:00
parent 2ddf8a44bc
commit 52d60d9623
4 changed files with 88 additions and 6 deletions

View File

@@ -34,6 +34,8 @@ import (
"github.com/goplus/llgo/cl"
"github.com/goplus/llgo/internal/packages"
"github.com/goplus/llgo/xtool/clang"
clangCheck "github.com/goplus/llgo/xtool/clang/check"
"github.com/goplus/llgo/xtool/env"
llssa "github.com/goplus/llgo/ssa"
)
@@ -207,11 +209,33 @@ func buildAllPkgs(prog llssa.Program, initial []*packages.Package, mode Mode, ve
pkg.ExportFile = ""
}
if kind == cl.PkgLinkExtern { // 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[:len(dir)-1]
// format: ';' separated alternative link methods. e.g.
// link: $LLGO_LIB_PYTHON; $(pkg-config --libs python3-embed); -lpython3
expd := ""
altParts := strings.Split(param, ";")
for _, param := range altParts {
expd = strings.TrimSpace(env.ExpandEnv(strings.TrimSpace(param)))
if len(expd) > 0 {
break
}
}
if expd == "" {
panic(fmt.Sprintf("'%s' cannot locate the external library", param))
}
command := ""
if expd[0] == '-' {
command += " " + expd
} else {
linkFile := expd
dir, lib := filepath.Split(linkFile)
command = " -l " + lib
if dir != "" {
command += " -L " + dir[:len(dir)-1]
}
}
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

View File

@@ -23,7 +23,7 @@ import (
)
const (
LLGoPackage = "link: $LLGO_LIB_PYTHON"
LLGoPackage = "link: $LLGO_LIB_PYTHON; $(pkg-config --libs python3-embed)"
)
// -----------------------------------------------------------------------------

View File

@@ -0,0 +1,26 @@
package check
import (
"errors"
"os/exec"
"runtime"
"strings"
)
func CheckLinkArgs(args string) error {
cmdArgs := strings.Split(args, " ")
cmd := exec.Command("clang")
nul := "/dev/null"
if runtime.GOOS == "windows" {
nul = "NUL"
}
cmd.Args = append(cmd.Args, cmdArgs...)
cmd.Args = append(cmd.Args, "-x", "c", "-o", nul, "-")
src := "int main() {return 0;}"
srcIn := strings.NewReader(src)
cmd.Stdin = srcIn
if out, err := cmd.CombinedOutput(); err != nil {
return errors.New(string(out))
}
return nil
}

32
xtool/env/env.go vendored Normal file
View File

@@ -0,0 +1,32 @@
package env
import (
"os"
"os/exec"
"regexp"
"runtime"
"strings"
)
func ExpandEnv(s string) string {
return expandEnvWithCmd(s)
}
func expandEnvWithCmd(s string) string {
re := regexp.MustCompile(`\$\(([^)]+)\)`)
expanded := re.ReplaceAllStringFunc(s, func(m string) string {
cmd := re.FindStringSubmatch(m)[1]
var out []byte
var err error
if runtime.GOOS == "windows" {
out, err = exec.Command("cmd", "/C", cmd).Output()
} else {
out, err = exec.Command("sh", "-c", cmd).Output()
}
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
})
return os.Expand(expanded, os.Getenv)
}