HomeBlogsDeveloper Skill SprintsDeveloper Skill Sprint: Effective IfDef Usage for Cross Platform Development
Developer Skill Sprint: Effective IfDef Usage for Cross Platform Development
Learn about how to use conditional compilation and platform services to accurately target your code for cross platform development.
Platforms and Delphi Compilers
- Windows
- 32-bit DCC32
- 64-bit DCC64
- OS X
- 32-bit DCCOSX
- iOS
- 32-bit DCCIOSARM
- 64-bit DCCIOSARM64
- 32-bit simulator DCCIOS32
- Android
- ARM DCCAARM
- Works on x86 via libHoudini
- (Not an officially supported platform)
- ARM DCCAARM
Platforms and C++ Compilers
- 32-bit Windows
- BCC32C.EXE (Clang)
- BCC32.EXE
- 64-bit Windows
- BCC64.EXE (Clang)
- OS X
- BCCOSX.EXE
- 32-bit iOS
- BCCIOSARM.EXE (Clang)
- 64-bit iOS
- BCCIOSARM64.EXE (Clang)
- Android
- BCCAARM.EXE (Clang)
- (also x86 Android via libHoudini)
- BCCAARM.EXE (Clang)
- More information http://embt.co/cpp-compilers
FireMonkey Platform Services
- Discover and access functionality that may or may not be available on current run-time platform.
- Discover
- TPlatformServices.Current.SupportsPlatformService
- Access
- TPlatformServices.Current.GetPlatformService
- Can also replace built-in services with your own implementation.
- More information: http://embt.co/platform-services
Conditional Compilation
- Use of IFDEF, IF, etc. compiler directives to optionally compile selected code branches
- Check Predefined Conditionals for compiler features
- Completely removes branches of code
- Useful when linking against platform API calls
- Overuse introduces complexity to code
- For Delphi "{$IF Defined(conditional)}" = "{$IFDEF conditional}"
- More information: http://embt.co/conditional-compilation
- For C++ "#if defined macro" = "#ifdef macro"
- More information: http://embt.co/conditional-compilation-cpp
Predefined Conditionals & Macros
- Set by the compiler
- Used to determine
- CPU architecture
- Platform
- Compiler features
- Compiler version
- etc.
- Delphi Conditionals: http://embt.co/predefined-conditionals
- See also user defined symbols
- C++Builder Predefined Macros: http://embt.co/predefined-macros
FMX & RTL Examples
- FMX.Memo.pas
- Implements interfaces, base classes and common behaviors
- Only uses uses IFDEFs in implementation Uses statement for platform implementations
- FMX.Memo.iOS
- FMX.Memo.Win
- FMX.WebBrowser.pas
- Uses compiler directives in Uses
- Calls RegisterWebBrowserService in platform specific implementations
- System.Notification.pas
- Uses compiler directives in Uses
- Platform specific implementations implement TPlatformNotificationCenter based on TBaseNotificationCenter
- TBaseNotificationCenter instantiates TPlatformNotificationCenter internally
Best Usage Strategies
- Use Platform services when possible
- Keep conditional defines in “library” code
- Have project use high level units
- Defines interfaces, base classes and common code
- Unit uses clause has conditional defines to platform specific implementation units
- Keep platform specific code in its own unit
- e.g. Don’t put iOS and Android code in same unit
- Create unit with useful constants
Delphi Code Samples
Conditional compilation samples
uses FMX.Types; { TIfDefTest } procedure TIfDefTest.IfDefTest; begin {$IFDEF MSWINDOWS} Assert.Pass('On Windows'); {$ELSE} // optional Assert.Fail('Not windows'); {$ENDIF} end; procedure TIfDefTest.IfTest1; begin {$IF Defined(MSWindows) and (CompilerVersion = 30)} Assert.Pass('Seattle for Windows'); {$ELSE} // optional Assert.Fail('Not Seattle for Windows'); {$IFEND} // or endif end; procedure TIfDefTest.IfTest2; begin {$IF (CompilerVersion >= 30) and (RTLVersion >= 30) and (FireMonkeyVersion >= 23)} Assert.Pass('Seattle'); {$ELSE} // optional Assert.Fail('Not Seattle'); {$ENDIF} // or ifend end;
Platform Services Samples
uses FMX.Platform; // Defines IFMXClipboardService { TPlatformServicesTest } procedure TPlatformServicesTest.LongWay; var clipboard: IFMXClipboardService; begin // Just check if TPlatformServices.Current.SupportsPlatformService(IFMXClipboardService) then begin // only executed when Clipboard Service is supported // Need instance of clipboard service before we can use it clipboard := IFMXClipboardService( TPlatformServices.Current.GetPlatformService(IFMXClipboardService)); clipboard.SetClipboard(TestValue); Assert.AreEqual(clipboard.GetClipboard.AsString, TestValue); end else Assert.Fail('Clipboard service not supported.'); end; procedure TPlatformServicesTest.ShortWay; var clipboard: IFMXClipboardService; begin // Just check if TPlatformServices.Current.SupportsPlatformService(IFMXClipboardService, clipboard) then begin // only executed when Clipboard Service is supported // Already has instance to Clipboard service clipboard.SetClipboard(TestValue); Assert.AreEqual(clipboard.GetClipboard.AsString, TestValue); end else Assert.Fail('Clipboard service not supported.'); end;
The code samples were built with DUnitX and ran with TestInsight - free add-in by Stefan Glienke.
C++Builder Code Samples
Conditional Compilation samples built with DUnitX.
void __fastcall TestConditionals::WindowsTest() { #if (_Windows) Dunitx::Testframework::Assert::Pass("This is Windows."); #else Dunitx::Testframework::Assert::Fail("NOT Windows."); #endif } void __fastcall TestConditionals::SeattleTest() { #if (__CODEGEARC__ >= 0x0710) Dunitx::Testframework::Assert::Pass("This is 10 Seattle."); #elif (__CODEGEARC__ >= 0x0700) Dunitx::Testframework::Assert::Pass("This is XE8."); #else Dunitx::Testframework::Assert::Fail("NOT Seattle"); #endif } void __fastcall TestConditionals::Win32Test() { #if (__WIN32__) Dunitx::Testframework::Assert::Pass("This is Win32."); #else Dunitx::Testframework::Assert::Fail("NOT Win32."); #endif } void __fastcall TestConditionals::NotTest() { #if (!__ANDROID__) Dunitx::Testframework::Assert::Pass("This is not Android."); #else Dunitx::Testframework::Assert::Fail("This is ANDROID!"); #endif } void __fastcall TestConditionals::TestiOS() { #if (__APPLE__ && (__arm__ || __arm64__)) Dunitx::Testframework::Assert::Fail("This would be iOS."); #else Dunitx::Testframework::Assert::Pass("This is not iOS"); #endif }
Conditional compilation sample written with DUnitX
String TestValue = "{BD1A7EB6-C8F6-4561-94AF-3B6F93594F3F}"; #include <FMX.Platform.hpp> void __fastcall TestPlatformServices::LongWayTest() { if (TPlatformServices::Current->SupportsPlatformService (__uuidof(IFMXClipboardService))) { // Only executed if platform supports specified service // Need instance of service _di_IFMXClipboardService ClipboardService = (_di_IFMXClipboardService)TPlatformServices::Current->GetPlatformService (__uuidof(IFMXClipboardService)); ClipboardService->SetClipboard(TValue::From<String>(TestValue)); Dunitx::Testframework::Assert::AreEqual(TestValue, ClipboardService->GetClipboard().AsString()); } else { Dunitx::Testframework::Assert::Fail("Service not supported."); } } void __fastcall TestPlatformServices::ShortWayTest() { _di_IFMXClipboardService ClipboardService; if (TPlatformServices::Current->SupportsPlatformService (__uuidof(IFMXClipboardService), &ClipboardService)) { // Only executed if platform supports specified service // already have instance to service ClipboardService->SetClipboard(TValue::From<String>(TestValue)); Dunitx::Testframework::Assert::AreEqual(TestValue, ClipboardService->GetClipboard().AsString()); } else { Dunitx::Testframework::Assert::Fail("Service not supported."); } }
Delphi Learning Resources
- Conditional Compilation (Predefined Conditionals & Predefined Constants)
- FireMonkey Platform Services
- See also:
- Use the source: C:\Program Files (x86)\EmbarcaderoStudio\17.0\source
C++Builder Learning Resources
- FireMonkey Platform Services
- Conditional Compilation in C++Builder
- Predefined Macros
- The 7 C++Builder Compilers
Delphi Replay
Video not found or Youtube service not available
C++Builder Replay
Video not found or Youtube service not available


This latest season of Developer Skill Sprints focuses on programming tips and techniques most requested by attendees of the past 72 skill sprints we’ve already presented. This quarter we’ll take your
Comments
-
Please login first in order for you to submit comments