#include "target.h" #include "tier0/commandline.h" #include "tier1/utlstring.h" #include "sys/utsname.h" // see Target_t::HostTarget #if defined(__i386__) && defined(POSIX) static utsname s_uname; static int s_iuNameRes = uname(&s_uname); #endif //----------------------------------------------------------------------------- // Generates triplet suitable for most compilers. //----------------------------------------------------------------------------- CUtlString Target_t::GetTriplet() { CUtlString triplet = ""; if ( cpu == TARGET_CPU_AMD64 ) triplet.AppendTail("x86_64"); if ( cpu == TARGET_CPU_80386 ) triplet.AppendTail("i386"); if ( cpu == TARGET_CPU_80486 ) triplet.AppendTail("i486"); if ( cpu == TARGET_CPU_80586 ) triplet.AppendTail("i586"); if ( cpu == TARGET_CPU_80686 ) triplet.AppendTail("i686"); if ( cpu == TARGET_CPU_AARCH64 ) triplet.AppendTail("aarch64"); if ( cpu == TARGET_CPU_WASM32 ) triplet.AppendTail("wasm32"); triplet.AppendTail("-"); if ( kernel == TARGET_KERNEL_UNKNOWN ) triplet.AppendTail("unknown-unknown"); if ( kernel == TARGET_KERNEL_UNKNOWN_LINUX ) triplet.AppendTail("unknown-linux"); if ( kernel == TARGET_KERNEL_PC_LINUX ) triplet.AppendTail("pc-linux"); if ( kernel == TARGET_KERNEL_ALPINE_LINUX ) triplet.AppendTail("alpine-linux"); if ( kernel == TARGET_KERNEL_WINDOWS ) triplet.AppendTail("pc-windows"); if ( kernel == TARGET_KERNEL_DARWIN ) triplet.AppendTail("apple-darwin"); if ( kernel == TARGET_KERNEL_IOS ) triplet.AppendTail("apple-ios"); if ( kernel == TARGET_KERNEL_ANDROID ) triplet.AppendTail("linux-android"); if ( kernel == TARGET_KERNEL_WASI ) triplet.AppendTail("unknown-wasi"); if ( kernel == TARGET_KERNEL_EMSCRIPTEN ) triplet.AppendTail("unknown-emscripten"); if ( abi != TARGET_ABI_DEFAULT ) triplet.AppendTail("-"); if ( abi == TARGET_ABI_GNU ) triplet.AppendTail("gnu"); if ( abi == TARGET_ABI_MUSL ) triplet.AppendTail("musl"); return triplet; } const char *Target_t::GetExecutableFileFormat() { if (kernel & TARGET_KERNEL_POSIX) return ""; if (kernel & TARGET_KERNEL_WINDOWS_DEVICES) { return "%s.exe"; } return NULL; } const char *Target_t::GetStaticLibraryFileFormat() { if (kernel & TARGET_KERNEL_POSIX) return "lib%s.a"; if (kernel & TARGET_KERNEL_WINDOWS_DEVICES) { switch(abi) { case TARGET_ABI_MSVC: return "%s.lib"; default: return "lib%s.a"; } } return NULL; } const char *Target_t::GetDynamicLibraryFileFormat() { if (kernel & TARGET_KERNEL_LINUX_DEVICES) return "lib%s.so"; if (kernel & TARGET_KERNEL_APPLE_DEVICES) return "lib%s.dylib"; if (kernel & TARGET_KERNEL_WINDOWS_DEVICES) return "lib%s.dylib"; return NULL; } //---------------------------------------------------------------------------- // Returns target on which fpc is being run // // For targets such as i386, i486, i586 //---------------------------------------------------------------------------- Target_t Target_t::HostTarget() { ETargetKernel kernel = TARGET_KERNEL_UNDEFINED; #if defined(__linux__) kernel = TARGET_KERNEL_LINUX; #elif defined(__APPLE__) kernel TARGET_KERNEL_DARWIN; #endif ETargetCPU cpu = TARGET_CPU_UNDEFINED; #if defined(__x86_64__) cpu = TARGET_CPU_AMD64; #endif #if defined(__i386__) cpu = TARGET_CPU_80386; #endif // POSIX doesn't know about these // use uname to get them #if defined(__i386__) && defined(POSIX) if (!V_strcmp("i486", s_uname.machine)) cpu = TARGET_CPU_80486; if (!V_strcmp("i586", s_uname.machine)) cpu = TARGET_CPU_80586; if (!V_strcmp("i686", s_uname.machine)) cpu = TARGET_CPU_80686; #endif ETargetABI abi = TARGET_ABI_GNU; #ifdef FPC_ARCH cpu = CPUFromString(FPC_ARCH); #endif #ifdef FPC_OS kernel = KernelFromString(FPC_OS); #endif #ifdef FPC_ABI abi = ABIFromString(FPC_ABI); #endif return { .kernel = kernel, .cpu = cpu, .abi = abi, .optimization = TARGET_DEBUG, }; }; //----------------------------------------------------------------------------- // Returns default target for build, by default it will be host target //----------------------------------------------------------------------------- Target_t Target_t::DefaultTarget() { CUtlString szDevice = CommandLine()->ParamValue("-device"); CUtlString szOS = CommandLine()->ParamValue("-os"); CUtlString szArch = CommandLine()->ParamValue("-arch"); CUtlString szAbi = CommandLine()->ParamValue("-abi"); ETargetKernel kernel = KernelFromString(szOS); ETargetCPU cpu = CPUFromString(szArch); ETargetABI abi = ABIFromString(szAbi); if (cpu == TARGET_CPU_UNDEFINED) cpu = HostTarget().cpu; if (kernel == TARGET_KERNEL_UNDEFINED) kernel = HostTarget().kernel; if (abi == TARGET_ABI_UNDEFINED) abi = HostTarget().abi; return { .kernel = kernel, .cpu = cpu, .abi = abi, .optimization = TARGET_DEBUG, }; } ETargetCPU Target_t::CPUFromString( const char *szName ) { CUtlString szUtlName = szName; if ( szUtlName == "x86_64" ) return TARGET_CPU_AMD64; else if ( szUtlName == "i386" ) return TARGET_CPU_80386; else if ( szUtlName == "i486" ) return TARGET_CPU_80486; else if ( szUtlName == "i586" ) return TARGET_CPU_80586; else if ( szUtlName == "i686" ) return TARGET_CPU_80686; else if ( szUtlName == "aarch64" ) return TARGET_CPU_AARCH64; else if ( szUtlName == "wasm32" ) return TARGET_CPU_WASM32; return TARGET_CPU_UNDEFINED; } ETargetKernel Target_t::KernelFromString( const char *szName ) { CUtlString szUtlName = szName; if ( szUtlName == "unknown" ) return TARGET_KERNEL_UNKNOWN; else if ( szUtlName == "windows" ) return TARGET_KERNEL_WINDOWS; else if ( szUtlName == "linux" ) return TARGET_KERNEL_LINUX; else if ( szUtlName == "unknown-linux" ) return TARGET_KERNEL_UNKNOWN_LINUX; else if ( szUtlName == "pc-linux" ) return TARGET_KERNEL_PC_LINUX; else if ( szUtlName == "alpine-linux" ) return TARGET_KERNEL_ALPINE_LINUX; else if ( szUtlName == "macos" ) return TARGET_KERNEL_DARWIN; else if ( szUtlName == "ios" ) return TARGET_KERNEL_IOS; else if ( szUtlName == "android" ) return TARGET_KERNEL_ANDROID; return TARGET_KERNEL_UNDEFINED; } ETargetABI Target_t::ABIFromString( const char *szName ) { CUtlString szUtlName = szName; if ( szUtlName == "gnu" ) return TARGET_ABI_GNU; else if ( szUtlName == "musl" ) return TARGET_ABI_MUSL; return TARGET_ABI_UNDEFINED; }