mirror of
https://github.com/mappu/miqt.git
synced 2025-01-03 06:08:38 +00:00
genbindings/main: support custom clang ast node matchers
This commit is contained in:
parent
20f6d7878b
commit
d639160886
@ -9,6 +9,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -18,7 +19,26 @@ const (
|
|||||||
ClangRetryDelay = 3 * time.Second
|
ClangRetryDelay = 3 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func clangExec(ctx context.Context, clangBin, inputHeader string, cflags []string) ([]interface{}, error) {
|
type ClangMatcher func(astNodeFilename string) bool
|
||||||
|
|
||||||
|
func ClangMatchSameHeaderDefinitionOnly(astNodeFilename string) bool {
|
||||||
|
return astNodeFilename == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type clangMatchUnderPath struct {
|
||||||
|
basePath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *clangMatchUnderPath) Match(astNodeFilename string) bool {
|
||||||
|
if astNodeFilename == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return strings.HasPrefix(astNodeFilename, c.basePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
func clangExec(ctx context.Context, clangBin, inputHeader string, cflags []string, matcher ClangMatcher) ([]interface{}, error) {
|
||||||
|
|
||||||
clangArgs := []string{`-x`, `c++`}
|
clangArgs := []string{`-x`, `c++`}
|
||||||
clangArgs = append(clangArgs, cflags...)
|
clangArgs = append(clangArgs, cflags...)
|
||||||
@ -44,7 +64,7 @@ func clangExec(ctx context.Context, clangBin, inputHeader string, cflags []strin
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
inner, innerErr = clangStripUpToFile(pr, inputHeader)
|
inner, innerErr = clangStripUpToFile(pr, matcher)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
@ -57,10 +77,10 @@ func clangExec(ctx context.Context, clangBin, inputHeader string, cflags []strin
|
|||||||
return inner, innerErr
|
return inner, innerErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustClangExec(ctx context.Context, clangBin, inputHeader string, cflags []string) []interface{} {
|
func mustClangExec(ctx context.Context, clangBin, inputHeader string, cflags []string, matcher ClangMatcher) []interface{} {
|
||||||
|
|
||||||
for i := 0; i < ClangMaxRetries; i++ {
|
for i := 0; i < ClangMaxRetries; i++ {
|
||||||
astInner, err := clangExec(ctx, clangBin, inputHeader, cflags)
|
astInner, err := clangExec(ctx, clangBin, inputHeader, cflags, matcher)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Log and continue with next retry
|
// Log and continue with next retry
|
||||||
log.Printf("WARNING: Clang execution failed: %v", err)
|
log.Printf("WARNING: Clang execution failed: %v", err)
|
||||||
@ -83,7 +103,7 @@ func mustClangExec(ctx context.Context, clangBin, inputHeader string, cflags []s
|
|||||||
// This cleans out everything in the translation unit that came from an
|
// This cleans out everything in the translation unit that came from an
|
||||||
// #included file.
|
// #included file.
|
||||||
// @ref https://stackoverflow.com/a/71128654
|
// @ref https://stackoverflow.com/a/71128654
|
||||||
func clangStripUpToFile(stdout io.Reader, inputFilePath string) ([]interface{}, error) {
|
func clangStripUpToFile(stdout io.Reader, matcher ClangMatcher) ([]interface{}, error) {
|
||||||
|
|
||||||
var obj = map[string]interface{}{}
|
var obj = map[string]interface{}{}
|
||||||
err := json.NewDecoder(stdout).Decode(&obj)
|
err := json.NewDecoder(stdout).Decode(&obj)
|
||||||
@ -108,10 +128,8 @@ func clangStripUpToFile(stdout io.Reader, inputFilePath string) ([]interface{},
|
|||||||
return nil, errors.New("entry is not a map")
|
return nil, errors.New("entry is not a map")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := entry["isImplicit"]; ok {
|
// Check where this AST node came from, if it was directly written
|
||||||
// Don't keep
|
// in this header or if it as part of an #include
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var match_filename = ""
|
var match_filename = ""
|
||||||
|
|
||||||
@ -140,16 +158,13 @@ func clangStripUpToFile(stdout io.Reader, inputFilePath string) ([]interface{},
|
|||||||
|
|
||||||
// log.Printf("# name=%v kind=%v filename=%q\n", entry["name"], entry["kind"], match_filename)
|
// log.Printf("# name=%v kind=%v filename=%q\n", entry["name"], entry["kind"], match_filename)
|
||||||
|
|
||||||
if match_filename == "" {
|
if matcher(match_filename) {
|
||||||
// Keep
|
// Keep
|
||||||
ret = append(ret, entry)
|
ret = append(ret, entry)
|
||||||
|
|
||||||
} else if match_filename != inputFilePath {
|
|
||||||
// Skip this
|
|
||||||
} else {
|
|
||||||
// Keep this
|
|
||||||
// ret = append(ret, entry)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, discard this AST node, it comes from some imported file
|
||||||
|
// that we will likely scan separately
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
@ -113,6 +113,7 @@ func main() {
|
|||||||
*clang,
|
*clang,
|
||||||
strings.Fields(pkgConfigCflags("Qt5Widgets")),
|
strings.Fields(pkgConfigCflags("Qt5Widgets")),
|
||||||
filepath.Join(*outDir, "qt"),
|
filepath.Join(*outDir, "qt"),
|
||||||
|
ClangMatchSameHeaderDefinitionOnly,
|
||||||
)
|
)
|
||||||
|
|
||||||
generate(
|
generate(
|
||||||
@ -123,10 +124,11 @@ func main() {
|
|||||||
*clang,
|
*clang,
|
||||||
strings.Fields(pkgConfigCflags("Qt5PrintSupport")),
|
strings.Fields(pkgConfigCflags("Qt5PrintSupport")),
|
||||||
filepath.Join(*outDir, "qt/qprintsupport"),
|
filepath.Join(*outDir, "qt/qprintsupport"),
|
||||||
|
ClangMatchSameHeaderDefinitionOnly,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generate(packageName string, srcDirs []string, clangBin string, cflags []string, outDir string) {
|
func generate(packageName string, srcDirs []string, clangBin string, cflags []string, outDir string, matcher ClangMatcher) {
|
||||||
|
|
||||||
var includeFiles []string
|
var includeFiles []string
|
||||||
for _, srcDir := range srcDirs {
|
for _, srcDir := range srcDirs {
|
||||||
@ -152,7 +154,7 @@ func generate(packageName string, srcDirs []string, clangBin string, cflags []st
|
|||||||
// PASS 0 (Fill clang cache)
|
// PASS 0 (Fill clang cache)
|
||||||
//
|
//
|
||||||
|
|
||||||
generateClangCaches(includeFiles, clangBin, cflags)
|
generateClangCaches(includeFiles, clangBin, cflags, matcher)
|
||||||
|
|
||||||
// The cache should now be fully populated.
|
// The cache should now be fully populated.
|
||||||
|
|
||||||
@ -279,7 +281,7 @@ func generate(packageName string, srcDirs []string, clangBin string, cflags []st
|
|||||||
log.Printf("Processing %d file(s) completed", len(includeFiles))
|
log.Printf("Processing %d file(s) completed", len(includeFiles))
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateClangCaches(includeFiles []string, clangBin string, cflags []string) {
|
func generateClangCaches(includeFiles []string, clangBin string, cflags []string, matcher ClangMatcher) {
|
||||||
|
|
||||||
var clangChan = make(chan string, 0)
|
var clangChan = make(chan string, 0)
|
||||||
var clangWg sync.WaitGroup
|
var clangWg sync.WaitGroup
|
||||||
@ -301,7 +303,7 @@ func generateClangCaches(includeFiles []string, clangBin string, cflags []string
|
|||||||
|
|
||||||
// Parse the file
|
// Parse the file
|
||||||
// This seems to intermittently fail, so allow retrying
|
// This seems to intermittently fail, so allow retrying
|
||||||
astInner := mustClangExec(ctx, clangBin, inputHeader, cflags)
|
astInner := mustClangExec(ctx, clangBin, inputHeader, cflags, matcher)
|
||||||
|
|
||||||
// Write to cache
|
// Write to cache
|
||||||
jb, err := json.MarshalIndent(astInner, "", "\t")
|
jb, err := json.MarshalIndent(astInner, "", "\t")
|
||||||
|
Loading…
Reference in New Issue
Block a user