The answers to this question aren't quite correct. The question of the platform and hardware vs Simulator is orthogonal.
Do not use architecture as a shortcut for platform or simulator detection! This kind of sloppy thinking has caused many, many programmers a great deal of heartburn and headache over the years.
Here is an ASCII chart of the conditionals. The names don't necessarily make sense for historical reasons:
+--------------------------------------+
| TARGET_OS_MAC |
| +---+ +---------------------------+ |
| | | | TARGET_OS_IPHONE | |
| |OSX| | +-----+ +----+ +-------+ | |
| | | | | IOS | | TV | | WATCH | | |
| | | | +-----+ +----+ +-------+ | |
| +---+ +---------------------------+ |
+--------------------------------------+
Devices: TARGET_OS_EMBEDDED
Simulators: TARGET_OS_SIMULATOR
TARGET_OS_MAC is true for all Apple platforms.
TARGET_OS_OSX is true only for macOS
TARGET_OS_IPHONE is true for iOS, watchOS, and tvOS (devices & simulators)
TARGET_OS_IOS is true only for iOS (devices & simulators)
TARGET_OS_WATCH is true only for watchOS (devices & simulators)
TARGET_OS_TV is true only for tvOS (devices & simulators)
TARGET_OS_EMBEDDED is true only for iOS/watchOS/tvOS hardware
TARGET_OS_SIMULATOR is true only for the Simulator.
I'll also note that you can conditionalize settings in xcconfig
files by platform:
//macOS only
SOME_SETTING[sdk=macosx] = ...
//iOS (device & simulator)
SOME_SETTING[sdk=iphone*] = ...
//iOS (device)
SOME_SETTING[sdk=iphoneos*] = ...
//iOS (simulator)
SOME_SETTING[sdk=iphonesimulator*] = ...
//watchOS (device & simulator)
SOME_SETTING[sdk=watch*] = ...
//watchOS (device)
SOME_SETTING[sdk=watchos*] = ...
//watchOS (simulator)
SOME_SETTING[sdk=watchsimulator*] = ...
//tvOS (device & simulator)
SOME_SETTING[sdk=appletv*] = ...
//tvOS (device)
SOME_SETTING[sdk=appletvos*] = ...
//tvOS (simulator)
SOME_SETTING[sdk=appletvsimulator*] = ...
// iOS, tvOS, or watchOS Simulator
SOME_SETTING[sdk=embeddedsimulator*] = ...