github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/lib/buildinfo/arch.go (about) 1 package buildinfo 2 3 import ( 4 "runtime" 5 6 "golang.org/x/sys/cpu" 7 ) 8 9 // GetSupportedGOARM returns the ARM compatibility level of the current CPU. 10 // 11 // Returns the integer value that can be set for the GOARM variable to 12 // build with this level as target, a value which normally corresponds to the 13 // ARM architecture version number, although it is the floating point hardware 14 // support which is the decicive factor. 15 // 16 // Only relevant for 32-bit ARM architectures, where GOARCH=arm, which means 17 // ARMv7 and lower (ARMv8 is GOARCH=arm64 and GOARM is not considered). 18 // Highest possible value is therefore 7, while other possible values are 19 // 6 (for ARMv6) and 5 (for ARMv5, which is the lowest currently supported 20 // in go. Returns value 0 for anything else. 21 // 22 // See also: 23 // 24 // https://go.dev/src/runtime/os_linux_arm.go 25 // https://github.com/golang/go/wiki/GoArm 26 func GetSupportedGOARM() int { 27 if runtime.GOARCH == "arm" && cpu.Initialized { 28 // This CPU is an ARM (32-bit), and cpu.Initialized true means its 29 // features could be retrieved on current GOOS so that we can check 30 // for floating point hardware support. 31 if cpu.ARM.HasVFPv3 { 32 // This CPU has VFPv3 floating point hardware, which means it can 33 // run programs built with any GOARM value, 7 and lower. 34 return 7 35 } else if cpu.ARM.HasVFP { 36 // This CPU has VFP floating point hardware, but not VFPv3, which 37 // means it can run programs built with GOARM value 6 and lower, 38 // but not 7. 39 return 6 40 } 41 // This CPU has no VFP floating point hardware, which means it can 42 // only run programs built with GOARM value 5, which is minimum supported. 43 // Note that the CPU can still in reality be based on e.g. ARMv7 44 // architecture, but simply lack hardfloat support. 45 return 5 46 } 47 return 0 48 } 49 50 // GetArch tells the rclone executable's architecture target. 51 func GetArch() string { 52 // Get the running program's architecture target. 53 arch := runtime.GOARCH 54 55 // For ARM architectures there are several variants, with different 56 // inconsistent and ambiguous naming. 57 // 58 // The most interesting thing here is which compatibility level of go is 59 // used, as controlled by GOARM build variable. We cannot in runtime get 60 // the actual value of GOARM used for building this program, but we can 61 // check the value supported by the current CPU by calling GetSupportedGOARM. 62 // This means we return information about the compatibility level (GOARM 63 // value) supported, when the current rclone executable may in reality be 64 // built with a lower level. 65 // 66 // Note that the kernel architecture, as returned by "uname -m", is not 67 // considered or included in results here, but it is included in the output 68 // from function GetOSVersion. It can have values such as armv6l, armv7l, 69 // armv8l, arm64 and aarch64, which may give relevant information. But it 70 // can also simply have value "arm", or it can have value "armv7l" for a 71 // processor based on ARMv7 but without floating point hardware - which 72 // means it in go needs to be built in ARMv5 compatibility mode (GOARM=5). 73 if arch == "arm64" { 74 // 64-bit ARM architecture, known as AArch64, was introduced with ARMv8. 75 // In go this architecture is a specific one, separate from other ARMs. 76 arch += " (ARMv8 compatible)" 77 } else if arch == "arm" { 78 // 32-bit ARM architecture, which is ARMv7 and lower. 79 // In go there are different compatibility levels represented by ARM 80 // architecture version number (like 5, 6 or 7). 81 switch GetSupportedGOARM() { 82 case 7: 83 arch += " (ARMv7 compatible)" 84 case 6: 85 arch += " (ARMv6 compatible)" 86 case 5: 87 arch += " (ARMv5 compatible, no hardfloat)" 88 } 89 } 90 return arch 91 }