Files
llgo/internal/xtool/llvm/llvm_test.go
2025-04-08 10:46:14 +08:00

151 lines
4.4 KiB
Go

//go:build !llgo
// +build !llgo
package llvm
import (
"os/exec"
"strings"
"testing"
)
func TestGetTargetTriple(t *testing.T) {
// Get the list of supported architectures from clang
cmd := exec.Command("clang", "--print-targets")
output, err := cmd.Output()
if err != nil {
t.Fatalf("Failed to run clang --print-targets: %v", err)
}
// Parse the output to get the list of supported architectures
supportedArchs := make(map[string]bool)
lines := strings.Split(string(output), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line != "" && !strings.HasPrefix(line, "Registered Targets:") {
// Extract the architecture from the line
parts := strings.SplitN(line, " - ", 2)
if len(parts) > 0 {
arch := strings.TrimSpace(parts[0])
supportedArchs[arch] = true
}
}
}
if len(supportedArchs) == 0 {
t.Fatal("No supported architectures found from clang --print-targets")
}
t.Logf("Found %d supported architectures from clang", len(supportedArchs))
// Map our architecture names to clang's architecture names
clangArchMap := map[string][]string{
"x86_64": {"x86-64", "x86_64"},
"i386": {"x86", "i386"},
"aarch64": {"aarch64", "arm64"},
"arm64": {"arm64", "aarch64"},
"armv7": {"arm", "thumb"},
"wasm32": {"wasm32"},
}
// Define a function to check if the architecture is supported by clang
isArchSupported := func(archPart string) (bool, string) {
if mappedArchs, ok := clangArchMap[archPart]; ok {
for _, mappedArch := range mappedArchs {
if supportedArchs[mappedArch] {
return true, mappedArch
}
}
} else if supportedArchs[archPart] {
// Direct match
return true, archPart
}
return false, ""
}
// Define a function to verify OS name
isOSValid := func(os, goos string) bool {
validOSMap := map[string][]string{
"linux": {"linux", "linux-gnu"},
"darwin": {"macosx", "darwin"},
"windows": {"windows", "win32"},
"wasip1": {"wasip1", "wasi"},
"js": {"js", "javascript"},
}
if validVariants, ok := validOSMap[goos]; ok {
for _, validVariant := range validVariants {
if strings.HasPrefix(os, validVariant) {
return true
}
}
}
return false
}
// Define a function to check if vendor is valid
isVendorValid := func(vendor string) bool {
validVendors := map[string]bool{
"unknown": true,
"apple": true,
"pc": true,
"ibm": true,
}
return validVendors[vendor]
}
// Define the test function
checkTriple := func(t *testing.T, testName, goos, goarch, expected string) {
t.Helper()
got := GetTargetTriple(goos, goarch)
// Check if the generated triple matches the expected value
if got != expected {
t.Errorf("getTargetTriple(%q, %q) = %q, want %q",
goos, goarch, got, expected)
}
// Extract the architecture part from the triple (first component)
parts := strings.Split(got, "-")
if len(parts) < 3 {
t.Errorf("Invalid target triple format: %s, should have at least 3 components", got)
return
}
archPart := parts[0]
vendor := parts[1]
os := parts[2]
// Check if the architecture is supported by clang
supported, mappedArch := isArchSupported(archPart)
if supported {
t.Logf("Architecture %s (mapped to %s) is supported by clang", archPart, mappedArch)
} else {
t.Logf("WARNING: Architecture %s from triple %q for %s/%s not found in clang's supported architectures",
archPart, got, goos, goarch)
}
// Verify vendor
if !isVendorValid(vendor) {
t.Errorf("Invalid vendor in triple: %s", vendor)
}
// Verify OS
if !isOSValid(os, goos) {
t.Errorf("OS in triple %q doesn't match expected OS %q", os, goos)
}
}
// Run tests for different OS/arch combinations
checkTriple(t, "wasip1/wasm", "wasip1", "wasm", "wasm32-unknown-wasip1")
checkTriple(t, "linux/amd64", "linux", "amd64", "x86_64-unknown-linux")
checkTriple(t, "linux/386", "linux", "386", "i386-unknown-linux")
checkTriple(t, "linux/arm64", "linux", "arm64", "aarch64-unknown-linux")
checkTriple(t, "linux/arm", "linux", "arm", "armv7-unknown-linux")
checkTriple(t, "darwin/amd64", "darwin", "amd64", "x86_64-apple-macosx")
checkTriple(t, "darwin/arm64", "darwin", "arm64", "arm64-apple-macosx")
checkTriple(t, "windows/amd64", "windows", "amd64", "x86_64-unknown-windows")
checkTriple(t, "windows/386", "windows", "386", "i386-unknown-windows")
checkTriple(t, "js/wasm", "js", "wasm", "wasm32-unknown-js")
}