Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add llcppcfg command to generate llcpp.cfg file #815

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
117 changes: 117 additions & 0 deletions chore/llcppcfg/cfg/cfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package cfg

import (
"bytes"
"encoding/json"
"fmt"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"
"unicode"
)

type LLCppConfig struct {
Name string `json:"name"`
Cflags string `json:"cflags"`
Include []string `json:"include"`
Libs string `json:"libs"`
TrimPrefixes []string `json:"trimPrefixes"`
ReplPrefixes []string `json:"replPrefixes"`
Cplusplus bool `json:"cplusplus"`
}

func CmdOutString(cmd *exec.Cmd) (string, error) {
outBuf := bytes.NewBufferString("")
cmd.Stdin = os.Stdin
cmd.Stdout = outBuf
err := cmd.Run()
if err != nil {
return outBuf.String(), err
}
return outBuf.String(), nil
}

func expandString(str string) string {
return os.Expand(str, func(s string) string {
args := strings.Fields(s)
if len(args) <= 0 {
return ""
}
outString, err := CmdOutString(exec.Command(args[0], args[1:]...))
if err != nil {
return ""
}
return outString
})
}

func expandCflags(str string, fn func(s string) bool) []string {
list := strings.FieldsFunc(str, func(r rune) bool {
return unicode.IsSpace(r)
})
contains := make(map[string]string, 0)
results := make([]string, 0)
for _, l := range list {
trimStr := strings.TrimPrefix(l, "-I")
trimStr += "/"
filepath.WalkDir(trimStr, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
if !fn(d.Name()) {
return nil
}
_, ok := contains[path]
if !ok {
results = append(results, d.Name())
contains[path] = d.Name()
}
return nil
})
}
return results
}

func NewLLCppConfig(name string, isCpp bool) *LLCppConfig {
cfg := &LLCppConfig{
Name: name,
}
cfg.Cflags = fmt.Sprintf("$(pkg-config --cflags %s)", name)
cfg.Libs = fmt.Sprintf("$(pkg-config --libs %s)", name)
cfg.TrimPrefixes = []string{}
cfg.ReplPrefixes = []string{}
cfg.Cplusplus = isCpp
cfg.Include = []string{}
Cflags := fmt.Sprintf("${pkg-config --cflags %s}", name)
cflags := expandString(Cflags)
cfg.Include = expandCflags(cflags, func(s string) bool {
ext := filepath.Ext(s)
return ext == ".h" || ext == ".hpp"
})
// expand Cflags and Libs
cfg.Cflags = strings.TrimLeft(strings.TrimRight(cflags, " \t\r\n"), " \t\r\n")
Libs := fmt.Sprintf("${pkg-config --libs %s}", name)
libs := expandString(Libs)
cfg.Libs = strings.TrimLeft(strings.TrimRight(libs, " \t\r\n"), " \t\r\n")
return cfg
}

func GenCfg(name string, cpp bool) (*bytes.Buffer, error) {
if len(name) <= 0 {
return nil, fmt.Errorf("name can't be empty")
}
cfg := NewLLCppConfig(name, cpp)
buf := bytes.NewBuffer([]byte{})
jsonEncoder := json.NewEncoder(buf)
jsonEncoder.SetIndent("", "\t")
err := jsonEncoder.Encode(cfg)
if err != nil {
return nil, err
}
return buf, nil
}
45 changes: 45 additions & 0 deletions chore/llcppcfg/llcppcfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"flag"
"fmt"
"log"
"os"

"github.com/goplus/llgo/chore/llcppcfg/cfg"
)

func printHelp() {
flag.Usage()
flag.PrintDefaults()
}

func main() {
var cpp bool = false
var help bool = false
flag.BoolVar(&cpp, "cpp", false, "if it is c++ lib")
flag.BoolVar(&help, "help", false, "print help message")
flag.Usage = func() {
fmt.Println(`llcppcfg is to generate llcpp.cfg file.
usage: llcppcfg [-cpp|-help] libname`)
}
flag.Parse()
if help || len(os.Args) <= 1 {
printHelp()
return
}
name := ""
if len(flag.Args()) > 0 {
name = flag.Arg(0)
}
buf, err := cfg.GenCfg(name, cpp)
if err != nil {
log.Fatal(err)
}
outFile := "./llcppg.cfg"
err = os.WriteFile(outFile, buf.Bytes(), 0644)
if err != nil {
log.Fatal(err)
}
log.Println("Config file has been generated at ", outFile, "!")
}
Loading