Skip to content

Commit ec3dfe8

Browse files
committed
fix: use MM to retrieve interface
1 parent bcc3e2e commit ec3dfe8

1 file changed

Lines changed: 43 additions & 22 deletions

File tree

_xtool/internal/config/config.go

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package config
22

33
import (
4+
"bufio"
5+
"maps"
46
"os"
57
"path/filepath"
8+
"slices"
9+
"sort"
610
"strings"
711

812
"github.com/goplus/lib/c/clang"
@@ -41,54 +45,49 @@ func PkgHfileInfo(includes []string, args []string, mix bool) *PkgHfilesInfo {
4145
}
4246
defer os.Remove(outfile.Name())
4347

44-
refMap := make(map[string]int, len(includes))
48+
mmOutput, err := os.CreateTemp("", "mmoutput_*")
49+
if err != nil {
50+
panic(err)
51+
}
52+
defer os.Remove(mmOutput.Name())
4553

4654
clangtool.ComposeIncludes(includes, outfile.Name())
4755
index, unit, err := clangutils.CreateTranslationUnit(&clangutils.Config{
4856
File: outfile.Name(),
4957
Temp: false,
50-
Args: args,
58+
Args: append(args, "-MMD", "-MF", mmOutput.Name()),
5159
})
60+
5261
defer unit.Dispose()
5362
defer index.Dispose()
5463
if err != nil {
5564
panic(err)
5665
}
5766

67+
inters := ParseMMOutout(outfile.Name(), mmOutput)
68+
var others []string
69+
5870
clangutils.GetInclusions(unit, func(inced clang.File, incins []clang.SourceLocation) {
5971
// not in the first level include maybe impl or third hfile
6072
filename := filepath.Clean(clang.GoString(inced.FileName()))
6173

62-
if len(incins) == 1 {
63-
info.Inters = append(info.Inters, filename)
64-
}
65-
66-
ref, ok := refMap[filename]
67-
if !ok {
68-
refMap[filename] = len(incins)
74+
// skip the composed header
75+
if filename == outfile.Name() {
6976
return
7077
}
71-
// Handle duplicate references: Retain only the reference with the smallest source location.
72-
// Example:
73-
// temp1.h: temp2 tempimpl.h
74-
// temp2.h: temp2
75-
// The reference count for temp2.h should be 1 (not 2).
76-
// If its count is 2, decrement it to 1.
77-
if len(incins) < ref {
78-
refMap[filename] = len(incins)
78+
if _, ok := inters[filename]; !ok {
79+
others = append(others, filename)
7980
}
8081
})
8182

83+
info.Inters = slices.Collect(maps.Keys(inters))
84+
8285
absLongestPrefix, err := filepath.Abs(CommonParentDir(info.Inters))
8386
if err != nil {
8487
panic(err)
8588
}
8689

87-
for filename, ref := range refMap {
88-
if ref == 1 {
89-
continue
90-
}
91-
90+
for _, filename := range others {
9291
if mix {
9392
info.Thirds = append(info.Thirds, filename)
9493
continue
@@ -104,6 +103,9 @@ func PkgHfileInfo(includes []string, args []string, mix bool) *PkgHfilesInfo {
104103
}
105104
}
106105

106+
sort.Strings(info.Inters)
107+
sort.Strings(info.Impls)
108+
107109
return info
108110
}
109111

@@ -128,3 +130,22 @@ func CommonParentDir(paths []string) string {
128130
}
129131
return filepath.Dir(paths[0])
130132
}
133+
134+
func ParseMMOutout(composedHeaderFileName string, outputFile *os.File) (inters map[string]struct{}) {
135+
scanner := bufio.NewScanner(outputFile)
136+
137+
fileName := strings.TrimSuffix(filepath.Base(composedHeaderFileName), ".h")
138+
139+
inters = make(map[string]struct{})
140+
141+
for scanner.Scan() {
142+
// skip composed header file
143+
if strings.Contains(scanner.Text(), fileName) {
144+
continue
145+
}
146+
inter := filepath.Clean(strings.TrimSpace(strings.TrimSuffix(scanner.Text(), `\`)))
147+
inters[inter] = struct{}{}
148+
}
149+
150+
return
151+
}

0 commit comments

Comments
 (0)