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