github.com/metux/go-metabuild@v0.0.0-20240118143255-d9ed5ab697f9/util/compiler/probe/cxx.go (about) 1 package probe 2 3 import ( 4 "log" 5 "os" 6 "strings" 7 8 cmdrun "github.com/metux/go-metabuild/util/cmd" 9 "github.com/metux/go-metabuild/util/compiler/base" 10 ) 11 12 func probeCXX(ci *base.CompilerInfo, envvar string, prefix string) bool { 13 ci.Language = base.LangCxx 14 15 if fromenv := cmdrun.EnvCmdline(envvar); len(fromenv) != 0 { 16 return probeCXXcmd(ci, fromenv) 17 } 18 19 // FIXME: clang detection yet broken 20 compilers := []string{"g++", "clang++", "c++"} 21 for _, c := range compilers { 22 if probeCXXcmd(ci, cmdrun.StrCmdline(prefix+c)) { 23 return true 24 } 25 } 26 return false 27 } 28 29 func probeCXXcmd(ci *base.CompilerInfo, cmd []string) bool { 30 if len(cmd) == 0 || cmd[0] == "" { 31 return false 32 } 33 ci.Command = cmd 34 35 // try to guess from help output 36 37 out, err := cmdrun.RunOutOne(append(ci.Command, "--help"), false) 38 if err != nil { 39 log.Println("probeCompilerId: cant get help page") 40 return false 41 } 42 if strings.Contains(out, "clang LLVM compiler") { 43 return probeClang(ci) 44 } 45 if probeGCC(ci) { 46 return true 47 } 48 49 // cant detect it 50 log.Println("neither gcc nor clang") 51 return false 52 } 53 54 func DetectCXX() (base.CompilerInfo, base.CompilerInfo, error) { 55 56 crossPrefix, crossCompile := CheckCross() 57 58 infoTarget := base.CompilerInfo{Language: base.LangCxx, CrossForHost: crossCompile, CrossPrefix: crossPrefix} 59 infoHost := base.CompilerInfo{Language: base.LangCxx, CrossForBuild: crossCompile} 60 61 if !probeCXX(&infoTarget, "CXX", crossPrefix) { 62 return infoTarget, infoHost, base.ErrNoUsableCompiler 63 } 64 65 if crossCompile { 66 if os.Getenv("HOST_CXX") != "" { 67 if !probeCXX(&infoHost, "HOST_CXX", "") { 68 return base.CompilerInfo{}, base.CompilerInfo{}, base.ErrNoUsableCompiler 69 } 70 } else if crossPrefix != "" { 71 if !probeCXX(&infoHost, "", "") { 72 return base.CompilerInfo{}, base.CompilerInfo{}, base.ErrNoUsableCompiler 73 } 74 } else { 75 return infoTarget, infoHost, base.ErrCrossMissingCXX 76 } 77 } 78 79 // no cross, so return the target compiler twice 80 return infoTarget, infoTarget, nil 81 }