Class by Platform/Target

Hi,

Perhaps I am missing something, but is it possible to have classes that are only compiled for a particular platform or target (i.e. macOS or Windows OS). Whilst lines of code can use pragmas, I need whole classes or methods that need to be selectively compiled based on platform. The issue is that using some MBS plugins, methods pass parameters of class types that are platform specific and this makes it hard to have a single code base to build for macOS and Windows OS.

Any thoughts would be appreciated.
Thanks,

Andy

On entire Methods or classes? No.
but as you mentioned you can wrap lines of code… so if you need to call one MBS or another… just make multiple calls and wrap them #IF Targetxxx

Entire classes? No. As Dave said you can wrap the contents in #if TargetXXX conditional compiler statements.

One thing that some people don’t know about is that if you look in the Inspector and switch to the Gear panel there’s an Include In section with a series of checkboxes that allow you to set if the method works in:

Desktop 32 Bit, Desktop 64 bit
Web 32/64
Console 32/64
iOS 32/64 (can you really create 32-bit iOS apps now?)

Anyway, we use these capabilities in our product BKS Shorts to great affect. Rather than creating Desktop and Web specific classes to display the report we simply mark Desktop only methods available only to desktop and Web specific only for Web.

I wish we had the ability to mark methods specific for Target Platform as that would make easier in some instances. And once you get to that point marking classes/module specific for a platform doesn’t seem a huge stretch. I’m sure there’s a Feedback report for this capability but a quick search didn’t find it.

Technically, you can by editing the project file. The fact that you can’t is merely a UI thing. I believe the setting will be preserved, until you make changes from within the IDE. It just looks like CompatibilityFlags = (TargetConsole and (Target32Bit or Target64Bit)) or (TargetWeb and (Target32Bit or Target64Bit)) or (TargetDesktop and (Target32Bit or Target64Bit)). So you could inject platform constants into it.

The only reason it wasn’t included in the inspector in the first place was UI complexity.

[quote=416465:@Thom McGrath]Technically, you can by editing the project file. The fact that you can’t is merely a UI thing. I believe the setting will be preserved, until you make changes from within the IDE. It just looks like CompatibilityFlags = (TargetConsole and (Target32Bit or Target64Bit)) or (TargetWeb and (Target32Bit or Target64Bit)) or (TargetDesktop and (Target32Bit or Target64Bit)). So you could inject platform constants into it.

The only reason it wasn’t included in the inspector in the first place was UI complexity.[/quote]
Understand though that editing the project files in this way is not supported, so if it screws up your project, it may not be retrievable.

Oh yeah. It’s a bad idea. I was just demonstrating that it isn’t a technical limitation.

I think you’ve read the answer…: no, not with a simple switch or CheckBox… but…

To add an idea… maybe the closest you can get is… well, have a look at this example project.
I try to explain it in short:

  • base class CMyClass: set Constructor to private
  • subclasses of CMyClass: CMyClassMacOS, CMyClassWindows: set Constructor to private
  • add a shared Method to CMyClassMacOS and CMyClassWindows, which instantiates the class (but using #if Target - #else raise Exception)
  • add a shared Method to CMyClass, which calls CMyClassMacOS.Create (but using #if Target - #else raise Exception)

What do you get with such an approach?

  • you can’t call by mistake Dim oMyClass As New CMyClass, as the contructor is protected and can only be called from within the class
  • you could call Dim oMyClassM As CMyClass = CMyClassMacOS.Create on TargetMacOS, but you can’t call by mistake CMyClassWindows.Create on macOS (otherwise you get an Exception) - this class can only be .Created on TargetWindows
  • since CMyClassWindows is only referenced in a Build for TargetWindows, it will be compiled (unfortunately *), but the code inside it won’t be executed in applications that you build for other build BuildTargets
    You can (or maybe better: you should) only call: Dim oMyClass As CMyClass = CMyClass.Create, which will return an instance of the appropriate Class-by-PlatformTarget subclass.

*) so you still might need #if Target inside CMyClassWindows, if you’re using OS-dependent code (e.g. Declare Function). A Soft Declare Function should not be an issue and can be used without #if Target, since the code won’t get executed on a wrong Platform (such as explained above).

Another option is to use a text-based project format, and have different project files that live in the same folder tree on a per-platform basis, e.g.:

  • myProject_windows.xojo_project
  • myProject_linux.xojo_project

And have both of the projects reference the same external items (except for the few items that are platform-specific) and each project only builds for a single platform.

[quote=416429:@Andrew Voller]Hi,

Perhaps I am missing something, but is it possible to have classes that are only compiled for a particular platform or target (i.e. macOS or Windows OS). Whilst lines of code can use pragmas, I need whole classes or methods that need to be selectively compiled based on platform. The issue is that using some MBS plugins, methods pass parameters of class types that are platform specific and this makes it hard to have a single code base to build for macOS and Windows OS.

Any thoughts would be appreciated.
Thanks,

Andy[/quote]

We do this quite a lot. Can you provide some examples of the problems you have and I will try to give you suggestions on how you might solve this?