Files
llgo/chore/_xtool/llcppsymg/config/cfgparse/parse.go
2024-10-21 18:48:56 +08:00

110 lines
2.6 KiB
Go

package cfgparse
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
)
// Note: This package is not placed under the 'config' package because 'config'
// depends on 'cjson'. The parsing of Libs and cflags is intended to be usable
// by both llgo and go, without introducing additional dependencies.
type Libs struct {
Paths []string // Dylib Path
Names []string
}
type CFlags struct {
Paths []string // Include Path
}
func ParseLibs(libs string) *Libs {
parts := strings.Fields(libs)
lbs := &Libs{}
for _, part := range parts {
if strings.HasPrefix(part, "-L") {
lbs.Paths = append(lbs.Paths, part[2:])
} else if strings.HasPrefix(part, "-l") {
lbs.Names = append(lbs.Names, part[2:])
}
}
return lbs
}
// searches for each library name in the provided paths and default paths,
// appending the appropriate file extension (.dylib for macOS, .so for Linux).
//
// Example: For "-L/opt/homebrew/lib -llua -lm":
// - It will search for liblua.dylib (on macOS) or liblua.so (on Linux)
// - System libs like -lm are ignored and included in notFound
//
// So error is returned if no libraries found at all.
func (l *Libs) GenDylibPaths(defaultPaths []string) ([]string, []string, error) {
var foundPaths []string
var notFound []string
affix := ".dylib"
if runtime.GOOS == "linux" {
affix = ".so"
}
searchPaths := append(l.Paths, defaultPaths...)
for _, name := range l.Names {
var foundPath string
for _, path := range searchPaths {
dylibPath := filepath.Join(path, "lib"+name+affix)
if _, err := os.Stat(dylibPath); err == nil {
foundPath = dylibPath
break
}
}
if foundPath != "" {
foundPaths = append(foundPaths, foundPath)
} else {
notFound = append(notFound, name)
}
}
if len(foundPaths) == 0 {
return nil, notFound, fmt.Errorf("failed to find any libraries")
}
return foundPaths, notFound, nil
}
func ParseCFlags(cflags string) *CFlags {
parts := strings.Fields(cflags)
cf := &CFlags{}
for _, part := range parts {
if strings.HasPrefix(part, "-I") {
cf.Paths = append(cf.Paths, part[2:])
}
}
return cf
}
func (cf *CFlags) GenHeaderFilePaths(files []string) ([]string, []string, error) {
var foundPaths []string
var notFound []string
for _, file := range files {
var found bool
for _, path := range cf.Paths {
fullPath := filepath.Join(path, file)
if _, err := os.Stat(fullPath); err == nil {
foundPaths = append(foundPaths, fullPath)
found = true
break
}
}
if !found {
notFound = append(notFound, file)
}
}
if len(foundPaths) == 0 {
return nil, notFound, fmt.Errorf("failed to find any header files")
}
return foundPaths, notFound, nil
}