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  }