@@ -47,6 +47,7 @@ type GoParser struct {
4747 types map [types.Type ]Identity
4848 files map [string ][]byte
4949 exclues []* regexp.Regexp
50+ cgoPkgs map [string ]bool // CGO packages
5051}
5152
5253type moduleInfo struct {
@@ -98,6 +99,7 @@ func newGoParser(name string, homePageDir string, opts Options) *GoParser {
9899func (p * GoParser ) collectGoMods (startDir string ) error {
99100 hasGoWork := false
100101 deps := map [string ]string {}
102+ var cgoPkgs map [string ]bool
101103 err := filepath .Walk (startDir , func (path string , info fs.FileInfo , err error ) error {
102104 if err != nil || ! strings .HasSuffix (path , "go.mod" ) {
103105 return nil
@@ -115,10 +117,18 @@ func (p *GoParser) collectGoMods(startDir string) error {
115117 p .repo .Modules [name ] = newModule (name , rel )
116118 p .modules = append (p .modules , newModuleInfo (name , rel , name ))
117119
118- deps , hasGoWork , err = getDeps (filepath .Dir (path ), hasGoWork )
120+ deps , hasGoWork , cgoPkgs , err = getDeps (filepath .Dir (path ), hasGoWork )
119121 if err != nil {
120122 return err
121123 }
124+ if p .cgoPkgs == nil {
125+ p .cgoPkgs = make (map [string ]bool )
126+ }
127+ for pkgPath := range cgoPkgs {
128+ if strings .HasPrefix (pkgPath , name ) {
129+ p .cgoPkgs [pkgPath ] = true
130+ }
131+ }
122132 for k , v := range deps {
123133 p .repo .Modules [name ].Dependencies [k ] = v
124134 p .modules = append (p .modules , newModuleInfo (k , "" , v ))
@@ -148,18 +158,20 @@ type dep struct {
148158 Dir string `json:"Dir"`
149159 GoMod string `json:"GoMod"`
150160 } `json:"Module"`
161+ CgoFiles []string `json:"CgoFiles"`
151162}
152163
153- func getDeps (dir string , goWork bool ) (a map [string ]string , hasGoWork bool , err error ) {
164+ func getDeps (dir string , goWork bool ) (a map [string ]string , hasGoWork bool , cgoPkgs map [string ]bool , err error ) {
165+ cgoPkgs = make (map [string ]bool )
154166 // run go mod tidy first to ensure all dependencies are resolved
155167 cmd := exec .Command ("go" , "mod" , "tidy" , "-e" )
156168 cmd .Dir = dir
157169 output , err := cmd .CombinedOutput ()
158170 if err != nil {
159- return nil , hasGoWork , fmt .Errorf ("failed to execute 'go mod tidy', err: %v, output: %s" , err , string (output ))
171+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to execute 'go mod tidy', err: %v, output: %s" , err , string (output ))
160172 }
161173 if hasNoDeps (filepath .Join (dir , "go.mod" )) {
162- return map [string ]string {}, hasGoWork , nil
174+ return map [string ]string {}, hasGoWork , cgoPkgs , nil
163175 }
164176 // -mod=mod to use go mod when go mod is inconsistent with go vendor
165177 // if go.work exist, it's no need to set -mod=mod
@@ -172,12 +184,12 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
172184 cmd .Dir = dir
173185 output , err = cmd .CombinedOutput ()
174186 if err != nil {
175- return nil , hasGoWork , fmt .Errorf ("failed to execute 'go list -json all', err: %v, output: %s, cmd string: %s, dir: %s" , err , string (output ), cmd .String (), dir )
187+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to execute 'go list -json all', err: %v, output: %s, cmd string: %s, dir: %s" , err , string (output ), cmd .String (), dir )
176188 }
177189 // ignore content until first open
178190 index := strings .Index (string (output ), "{" )
179191 if index == - 1 {
180- return nil , hasGoWork , fmt .Errorf ("failed to find '{' in output, output: %s" , string (output ))
192+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to find '{' in output, output: %s" , string (output ))
181193 }
182194 if index > 0 {
183195 log .Info ("go list skip prefix, output: %s" , string (output [:index ]))
@@ -191,13 +203,16 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
191203 if err .Error () == "EOF" {
192204 break
193205 }
194- return nil , hasGoWork , fmt .Errorf ("failed to decode json: %v, output: %s" , err , string (output ))
206+ return nil , hasGoWork , cgoPkgs , fmt .Errorf ("failed to decode json: %v, output: %s" , err , string (output ))
195207 }
196208 module := mod .Module
197209 // golang internal package, ignore it.
198210 if module .Path == "" {
199211 continue
200212 }
213+ if len (mod .CgoFiles ) > 0 {
214+ cgoPkgs [module .Path ] = true
215+ }
201216 if module .Replace != nil {
202217 deps [module .Path ] = module .Replace .Path + "@" + module .Replace .Version
203218 } else {
@@ -214,8 +229,7 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
214229 }
215230 }
216231 }
217-
218- return deps , hasGoWork , nil
232+ return deps , hasGoWork , cgoPkgs , nil
219233}
220234
221235// ParseRepo parse the entiry repo from homePageDir recursively until end
0 commit comments