Qt是跨平台的,从下面的编译配置选项(宏)中可以看出Qt支持的编译环境。
// qcompilerdetection.h
/*
The compiler, must be one of: (Q_CC_x)
SYM - Digital Mars C/C++ (used to be Symantec C++)
MSVC - Microsoft Visual C/C++, Intel C++ for Windows
BOR - Borland/Turbo C++
WAT - Watcom C++
GNU - GNU C++
COMEAU - Comeau C++
EDG - Edison Design Group C++
OC - CenterLine C++
SUN - Forte Developer, or Sun Studio C++
MIPS - MIPSpro C++
DEC - DEC C++
HPACC - HP aC++
USLC - SCO OUDK and UDK
CDS - Reliant C++
KAI - KAI C++
INTEL - Intel C++ for Linux, Intel C++ for Windows
HIGHC - MetaWare High C/C++
PGI - Portland Group C++
GHS - Green Hills Optimizing C++ Compilers
RVCT - ARM Realview Compiler Suite
CLANG - C++ front-end for the LLVM compiler
Should be sorted most to least authoritative.
*/
或者如下所示的Qt支持的OS。
// qsystemdetection.h
/*
The operating system, must be one of: (Q_OS_x)
DARWIN - Any Darwin system (macOS, iOS, watchOS, tvOS)
MACOS - macOS
IOS - iOS
WATCHOS - watchOS
TVOS - tvOS
MSDOS - MS-DOS and Windows
OS2 - OS/2
OS2EMX - XFree86 on OS/2 (not PM)
WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
WINRT - WinRT (Windows 8 Runtime)
CYGWIN - Cygwin
SOLARIS - Sun Solaris
HPUX - HP-UX
ULTRIX - DEC Ultrix
LINUX - Linux [has variants]
FREEBSD - FreeBSD [has variants]
NETBSD - NetBSD
OPENBSD - OpenBSD
BSDI - BSD/OS
INTERIX - Interix
IRIX - SGI Irix
OSF - HP Tru64 UNIX
SCO - SCO OpenServer 5
UNIXWARE - UnixWare 7, Open UNIX 8
AIX - AIX
HURD - GNU Hurd
DGUX - DG/UX
RELIANT - Reliant UNIX
DYNIX - DYNIX/ptx
QNX - QNX [has variants]
QNX6 - QNX RTP 6.1
LYNX - LynxOS
BSD4 - Any BSD 4.4 system
UNIX - Any UNIX BSD/SYSV system
ANDROID - Android platform
HAIKU - Haiku
The following operating systems have variants:
LINUX - both Q_OS_LINUX and Q_OS_ANDROID are defined when building for Android
- only Q_OS_LINUX is defined if building for other Linux systems
FREEBSD - Q_OS_FREEBSD is defined only when building for FreeBSD with a BSD userland
- Q_OS_FREEBSD_KERNEL is always defined on FreeBSD, even if the userland is from GNU
*/
以GNU为例,我们来看看Qt通过gcc的特性定义了那些东西,如常见的__attribute__
。
// qcompilerdetection.h
// ... other compilers
#elif defined(__GNUC__)
# define Q_CC_GNU (__GNUC__ * 100 + __GNUC_MINOR__) // gnu
# if defined(__MINGW32__)
# define Q_CC_MINGW // mingw
# endif
# if defined(__INTEL_COMPILER)
# define Q_CC_INTEL (__INTEL_COMPILER) // intel
// ... intel compiler
# else
/* Plain GCC */
# if Q_CC_GNU >= 405 // version
# define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable()
# define Q_UNREACHABLE_IMPL() __builtin_unreachable()
# define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text)))
# endif
# endif
# ifdef Q_OS_WIN // win
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
# elif defined(QT_VISIBILITY_AVAILABLE) // linux
# define Q_DECL_EXPORT __attribute__((visibility("default")))
# define Q_DECL_IMPORT __attribute__((visibility("default")))
# define Q_DECL_HIDDEN __attribute__((visibility("hidden")))
# endif
# define Q_FUNC_INFO __PRETTY_FUNCTION__
# define Q_ALIGNOF(type) __alignof__(type)
# define Q_TYPEOF(expr) __typeof__(expr)
# define Q_DECL_DEPRECATED __attribute__ ((__deprecated__))
# define Q_DECL_ALIGN(n) __attribute__((__aligned__(n)))
# define Q_DECL_UNUSED __attribute__((__unused__))
# define Q_LIKELY(expr) __builtin_expect(!!(expr), true)
# define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false)
# define Q_NORETURN __attribute__((__noreturn__))
# define Q_REQUIRED_RESULT __attribute__ ((__warn_unused_result__))
# define Q_DECL_PURE_FUNCTION __attribute__((pure))
# define Q_DECL_CONST_FUNCTION __attribute__((const))
# if !defined(QT_MOC_CPP) // no moc
# define Q_PACKED __attribute__ ((__packed__))
# ifndef __ARM_EABI__ // no arm eabi
# define QT_NO_ARM_EABI
# endif
# endif
# if Q_CC_GNU >= 403 && !defined(Q_CC_CLANG) // version && non-clang
# define Q_ALLOC_SIZE(x) __attribute__((alloc_size(x)))
# endif
下面是gcc各版本对C++11的支持所涉及的宏。
// qcompilerdetection.h
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# define Q_COMPILER_RESTRICTED_VLA
# define Q_COMPILER_THREADSAFE_STATICS
# if Q_CC_GNU >= 403
// GCC supports binary literals in C, C++98 and C++11 modes
# define Q_COMPILER_BINARY_LITERALS
# endif
# if !defined(__STRICT_ANSI__) || defined(__GXX_EXPERIMENTAL_CXX0X__) \
|| (defined(__cplusplus) && (__cplusplus >= 201103L)) \
|| (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
// Variadic macros are supported for gnu++98, c++11, C99 ... since forever (gcc 2.97)
# define Q_COMPILER_VARIADIC_MACROS
# endif
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
# if Q_CC_GNU >= 403
/* C++11 features supported in GCC 4.3: */
# define Q_COMPILER_DECLTYPE
# define Q_COMPILER_RVALUE_REFS
# define Q_COMPILER_STATIC_ASSERT
# endif
# if Q_CC_GNU >= 404
/* C++11 features supported in GCC 4.4: */
# define Q_COMPILER_AUTO_FUNCTION
# define Q_COMPILER_AUTO_TYPE
# define Q_COMPILER_EXTERN_TEMPLATES
# define Q_COMPILER_UNIFORM_INIT
# define Q_COMPILER_UNICODE_STRINGS
# define Q_COMPILER_VARIADIC_TEMPLATES
# endif
# if Q_CC_GNU >= 405
/* C++11 features supported in GCC 4.5: */
# define Q_COMPILER_EXPLICIT_CONVERSIONS
/* GCC 4.4 implements initializer_list but does not define typedefs required
* by the standard. */
# define Q_COMPILER_INITIALIZER_LISTS
# define Q_COMPILER_LAMBDA
# define Q_COMPILER_RAW_STRINGS
# define Q_COMPILER_CLASS_ENUM
# endif
# if Q_CC_GNU >= 406
/* Pre-4.6 compilers implement a non-final snapshot of N2346, hence default and delete
* functions are supported only if they are public. Starting from 4.6, GCC handles
* final version - the access modifier is not relevant. */
# define Q_COMPILER_DEFAULT_MEMBERS
# define Q_COMPILER_DELETE_MEMBERS
/* C++11 features supported in GCC 4.6: */
# define Q_COMPILER_CONSTEXPR
# define Q_COMPILER_NULLPTR
# define Q_COMPILER_UNRESTRICTED_UNIONS
# define Q_COMPILER_RANGE_FOR
# endif
# if Q_CC_GNU >= 407
/* GCC 4.4 implemented and std::atomic using its old intrinsics.
* However, the implementation is incomplete for most platforms until GCC 4.7:
* instead, std::atomic would use an external lock. Since we need an std::atomic
* that is behavior-compatible with QBasicAtomic, we only enable it here */
# define Q_COMPILER_ATOMICS
/* GCC 4.6.x has problems dealing with noexcept expressions,
* so turn the feature on for 4.7 and above, only */
# define Q_COMPILER_NOEXCEPT
/* C++11 features supported in GCC 4.7: */
# define Q_COMPILER_NONSTATIC_MEMBER_INIT
# define Q_COMPILER_DELEGATING_CONSTRUCTORS
# define Q_COMPILER_EXPLICIT_OVERRIDES
# define Q_COMPILER_TEMPLATE_ALIAS
# define Q_COMPILER_UDL
# endif
# if Q_CC_GNU >= 408
# define Q_COMPILER_ATTRIBUTES
# define Q_COMPILER_ALIGNAS
# define Q_COMPILER_ALIGNOF
# define Q_COMPILER_INHERITING_CONSTRUCTORS
# define Q_COMPILER_THREAD_LOCAL
# if Q_CC_GNU > 408 || __GNUC_PATCHLEVEL__ >= 1
# define Q_COMPILER_REF_QUALIFIERS
# endif
# endif
/* C++11 features are complete as of GCC 4.8.1 */
# endif
# if __cplusplus > 201103L
# if Q_CC_GNU >= 409
/* C++1y features in GCC 4.9 - deprecated, do not update this list */
//# define Q_COMPILER_BINARY_LITERALS // already supported since GCC 4.3 as an extension
# define Q_COMPILER_LAMBDA_CAPTURES
# define Q_COMPILER_RETURN_TYPE_DEDUCTION
# endif
# endif
#endif
下面是与C++11各关键字相关的宏,如常见的= default
、= delete
。
// qcompilerdetection.h
/*
* C++11 keywords and expressions
*/
#ifdef Q_COMPILER_NULLPTR
# define Q_NULLPTR nullptr
#else
# define Q_NULLPTR NULL
#endif
#ifdef Q_COMPILER_DEFAULT_MEMBERS
# define Q_DECL_EQ_DEFAULT = default
#else
# define Q_DECL_EQ_DEFAULT
#endif
#ifdef Q_COMPILER_DELETE_MEMBERS
# define Q_DECL_EQ_DELETE = delete
#else
# define Q_DECL_EQ_DELETE
#endif
// Don't break code that is already using Q_COMPILER_DEFAULT_DELETE_MEMBERS
#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
#endif
#if defined Q_COMPILER_CONSTEXPR
# if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304
# define Q_DECL_CONSTEXPR constexpr
# define Q_DECL_RELAXED_CONSTEXPR constexpr
# define Q_CONSTEXPR constexpr
# define Q_RELAXED_CONSTEXPR constexpr
# else
# define Q_DECL_CONSTEXPR constexpr
# define Q_DECL_RELAXED_CONSTEXPR
# define Q_CONSTEXPR constexpr
# define Q_RELAXED_CONSTEXPR const
# endif
#else
# define Q_DECL_CONSTEXPR
# define Q_DECL_RELAXED_CONSTEXPR
# define Q_CONSTEXPR const
# define Q_RELAXED_CONSTEXPR const
#endif
#ifdef Q_COMPILER_EXPLICIT_OVERRIDES
# define Q_DECL_OVERRIDE override
# define Q_DECL_FINAL final
#else
# ifndef Q_DECL_OVERRIDE
# define Q_DECL_OVERRIDE
# endif
# ifndef Q_DECL_FINAL
# define Q_DECL_FINAL
# endif
#endif
#ifdef Q_COMPILER_NOEXCEPT
# define Q_DECL_NOEXCEPT noexcept
# define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
# ifdef Q_DECL_NOTHROW
# undef Q_DECL_NOTHROW /* override with C++11 noexcept if available */
# endif
#else
# define Q_DECL_NOEXCEPT
# define Q_DECL_NOEXCEPT_EXPR(x)
#endif
#ifndef Q_DECL_NOTHROW
# define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
#endif
#if defined(Q_COMPILER_ALIGNOF)
# undef Q_ALIGNOF
# define Q_ALIGNOF(x) alignof(x)
#endif
#if defined(Q_COMPILER_ALIGNAS)
# undef Q_DECL_ALIGN
# define Q_DECL_ALIGN(n) alignas(n)
#endif
C++标准参考:https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
下面是sg10-sd6给出的一些C++特性。
// qcompilerdetection.h
#ifdef __has_builtin
# define QT_HAS_BUILTIN(x) __has_builtin(x)
#else
# define QT_HAS_BUILTIN(x) 0
#endif
#ifdef __has_attribute
# define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
# define QT_HAS_ATTRIBUTE(x) 0
#endif
#ifdef __has_cpp_attribute
# define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define QT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#ifdef __has_include
# define QT_HAS_INCLUDE(x) __has_include(x)
#else
# define QT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_include_next
# define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
#else
# define QT_HAS_INCLUDE_NEXT(x) 0
#endif
在编译代码时,常会看到一些Warning,这些Warning可以通过技术手段规避,如下的一些宏定义,将会产生警告的代码置于push
与pop
之间,或者直接disable
或ignored
会产生警告的编译规则。
// qcompilerdetection.h
#define QT_DO_PRAGMA(text) _Pragma(#text)
// ... other compilers
#elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 && !defined(Q_CC_CLANG)
# undef QT_DO_PRAGMA /* not needed */
# define QT_WARNING_PUSH __pragma(warning(push))
# define QT_WARNING_POP __pragma(warning(pop))
# define QT_WARNING_DISABLE_MSVC(number) __pragma(warning(disable: number))
# define QT_WARNING_DISABLE_INTEL(number)
# define QT_WARNING_DISABLE_CLANG(text)
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_MSVC(4996)
#elif defined(Q_CC_GNU) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
# define QT_WARNING_PUSH QT_DO_PRAGMA(GCC diagnostic push)
# define QT_WARNING_POP QT_DO_PRAGMA(GCC diagnostic pop)
# define QT_WARNING_DISABLE_GCC(text) QT_DO_PRAGMA(GCC diagnostic ignored text)
# define QT_WARNING_DISABLE_CLANG(text)
# define QT_WARNING_DISABLE_INTEL(number)
# define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
#else // All other compilers, GCC < 4.6 and MSVC < 2008
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_PUSH
# define QT_WARNING_POP
# define QT_WARNING_DISABLE_INTEL(number)
# define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_CLANG(text)
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED
#endif
下面是Qt支持的处理器类型(ARCH_PROCESSOR),如常见的i386
、x86_64
等。
// archdetect.cpp
// main part: processor type
#if defined(Q_PROCESSOR_ALPHA)
# define ARCH_PROCESSOR "alpha"
#elif defined(Q_PROCESSOR_ARM_32)
# define ARCH_PROCESSOR "arm"
#elif defined(Q_PROCESSOR_ARM_64)
# define ARCH_PROCESSOR "arm64"
#elif defined(Q_PROCESSOR_AVR32)
# define ARCH_PROCESSOR "avr32"
#elif defined(Q_PROCESSOR_BLACKFIN)
# define ARCH_PROCESSOR "bfin"
#elif defined(Q_PROCESSOR_X86_32)
# define ARCH_PROCESSOR "i386"
#elif defined(Q_PROCESSOR_X86_64)
# define ARCH_PROCESSOR "x86_64"
#elif defined(Q_PROCESSOR_IA64)
# define ARCH_PROCESSOR "ia64"
#elif defined(Q_PROCESSOR_MIPS_64)
# define ARCH_PROCESSOR "mips64"
#elif defined(Q_PROCESSOR_MIPS)
# define ARCH_PROCESSOR "mips"
#elif defined(Q_PROCESSOR_POWER_32)
# define ARCH_PROCESSOR "power"
#elif defined(Q_PROCESSOR_POWER_64)
# define ARCH_PROCESSOR "power64"
#elif defined(Q_PROCESSOR_S390_X)
# define ARCH_PROCESSOR "s390x"
#elif defined(Q_PROCESSOR_S390)
# define ARCH_PROCESSOR "s390"
#elif defined(Q_PROCESSOR_SH)
# define ARCH_PROCESSOR "sh"
#elif defined(Q_PROCESSORS_SPARC_64)
# define ARCH_PROCESSOR "sparc64"
#elif defined(Q_PROCESSOR_SPARC_V9)
# define ARCH_PROCESSOR "sparcv9"
#elif defined(Q_PROCESSOR_SPARC)
# define ARCH_PROCESSOR "sparc"
#else
# define ARCH_PROCESSOR "unknown"
#endif
处理器对应的宏有固定的格式,如下所示。
// qprocessordetection.h
Q_PROCESSOR_{FAMILY}
Q_PROCESSOR_{FAMILY}_{VARIANT}
Q_PROCESSOR_{FAMILY}_{REVISION}
// qprocessordetection.h
// ... other arches
/*
ARM family, known revisions: V5, V6, V7, V8
ARM is bi-endian, detect using __ARMEL__ or __ARMEB__
X86 family, known variants: 32- and 64-bit
X86 is little-endian
/*
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
# define Q_PROCESSOR_X86_32
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# define Q_PROCESSOR_WORDSIZE 4
# if defined(_M_IX86)
# define Q_PROCESSOR_X86 (_M_IX86/100)
# elif defined(__i686__) || defined(__athlon__) || defined(__SSE__) || defined(__pentiumpro__)
# define Q_PROCESSOR_X86 6
# elif defined(__i586__) || defined(__k6__) || defined(__pentium__)
# define Q_PROCESSOR_X86 5
# elif defined(__i486__) || defined(__80486__)
# define Q_PROCESSOR_X86 4
# else
# define Q_PROCESSOR_X86 3
# endif
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
# define Q_PROCESSOR_X86 6
# define Q_PROCESSOR_X86_64
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# define Q_PROCESSOR_WORDSIZE 8
// ... other arches
大小端字节序(ARCH_ENDIANNESS)定义如下所示。
// archdetect.cpp
// endianness
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
# define ARCH_ENDIANNESS "little_endian"
#elif Q_BYTE_ORDER == Q_BIG_ENDIAN
# define ARCH_ENDIANNESS "big_endian"
#endif
// qprocessordetection.h
/* Machine byte-order, reuse preprocessor provided macros when available */
#if defined(__ORDER_BIG_ENDIAN__)
# define Q_BIG_ENDIAN __ORDER_BIG_ENDIAN__
#else
# define Q_BIG_ENDIAN 4321
#endif
#if defined(__ORDER_LITTLE_ENDIAN__)
# define Q_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
#else
# define Q_LITTLE_ENDIAN 1234
#endif
// qprocessordetection.h
/*
NOTE:
GCC 4.6 added __BYTE_ORDER__, __ORDER_BIG_ENDIAN__, __ORDER_LITTLE_ENDIAN__
and __ORDER_PDP_ENDIAN__ in SVN r165881. If you are using GCC 4.6 or newer,
this code will properly detect your target byte order; if you are not, and
the __LITTLE_ENDIAN__ or __BIG_ENDIAN__ macros are not defined, then this
code will fail to detect the target byte order.
*/
// Some processors support either endian format, try to detect which we are using.
#if !defined(Q_BYTE_ORDER)
# if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == Q_BIG_ENDIAN || __BYTE_ORDER__ == Q_LITTLE_ENDIAN)
// Reuse __BYTE_ORDER__ as-is, since our Q_*_ENDIAN #defines match the preprocessor defaults
# define Q_BYTE_ORDER __BYTE_ORDER__
# elif defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN)
# define Q_BYTE_ORDER Q_BIG_ENDIAN
# elif defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) \
|| defined(WINAPI_FAMILY) // WinRT is always little-endian according to MSDN.
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# else
# error "Unable to determine byte order!"
# endif
#endif
指针大小(ARCH_POINTER)定义如下所示。
// archdetect.cpp
// pointer type
#if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64))
# define ARCH_POINTER "llp64"
#elif defined(__LP64__) || QT_POINTER_SIZE - 0 == 8
# define ARCH_POINTER "lp64"
#else
# define ARCH_POINTER "ilp32"
#endif
// qprocessordetection.h
/*
Size of a pointer and the machine register size. We detect a 64-bit system by:
* GCC and compatible compilers (Clang, ICC on OS X and Windows) always define
__SIZEOF_POINTER__. This catches all known cases of ILP32 builds on 64-bit
processors.
* Most other Unix compilers define __LP64__ or _LP64 on 64-bit mode
(Long and Pointer 64-bit)
* If Q_PROCESSOR_WORDSIZE was defined above, it's assumed to match the pointer
size.
Otherwise, we assume to be 32-bit and then check in qglobal.cpp that it is right.
*/
#if defined __SIZEOF_POINTER__
# define QT_POINTER_SIZE __SIZEOF_POINTER__
#elif defined(__LP64__) || defined(_LP64)
# define QT_POINTER_SIZE 8
#elif defined(Q_PROCESSOR_WORDSIZE)
# define QT_POINTER_SIZE Q_PROCESSOR_WORDSIZE
#else
# define QT_POINTER_SIZE 4
#endif
浮点数精度(ARCH_COORD_TYPE)定义如下所示。
// archdetect.cpp
// qreal type, if not double (includes the dash)
#ifdef QT_COORD_TYPE_STRING
# define ARCH_COORD_TYPE "-qreal_" QT_COORD_TYPE_STRING
#else
# define ARCH_COORD_TYPE ""
#endif
程序二进制接口相关的软、硬浮点(ARCH_ABI)定义如下所示。
// archdetect.cpp
// secondary: ABI string (includes the dash)
#if defined(__ARM_EABI__) || defined(__mips_eabi)
# define ARCH_ABI1 "-eabi"
#elif defined(_MIPS_SIM)
# if _MIPS_SIM == _ABIO32
# define ARCH_ABI1 "-o32"
# elif _MIPS_SIM == _ABIN32
# define ARCH_ABI1 "-n32"
# elif _MIPS_SIM == _ABI64
# define ARCH_ABI1 "-n64"
# elif _MIPS_SIM == _ABIO64
# define ARCH_ABI1 "-o64"
# endif
#else
# define ARCH_ABI1 ""
#endif
#if defined(__ARM_PCS_VFP) || defined(__mips_hard_float)
// Use "-hardfloat" for platforms that usually have no FPUs
// (and for the platforms which had "-hardfloat" before we established the rule)
# define ARCH_ABI2 "-hardfloat"
#elif defined(_SOFT_FLOAT)
// Use "-softfloat" for architectures that usually have FPUs
# define ARCH_ABI2 "-softfloat"
#else
# define ARCH_ABI2 ""
#endif
#define ARCH_ABI ARCH_ABI1 ARCH_ABI2