#guard or #exit that abandons compilation of file

I've got a common package with code for multiple platforms. Sometimes a file is only useful on a single platform (say a category on NSViewController). The only way (I know of) to exclude this is surronding the entire file with a if os() or canImport() call. This causes an editor to indent all the code in the file.

I think it would be useful (and more swifty) to have a conditional that exits evaluation of the file if such a check fails.

Or a "#exit" (name doesn't matter) that ends compilation of the file. Then it can be included in a #if !os(macOS).

2 Likes

There is a build setting called INCLUDED_SOURCE_FILE_NAMES (and an EXCLUDED_* version) that lets you conditionally add and remove files for compilation from a target. Maybe that could help? I use it when building cross-platform frameworks: I have an "iOS" subfolder, a "macOS" subfolder, etc, and then put macOS/*.swift into the INCLUDED_SOURCE_FILE_NAMES[sdk=mac*] build setting.

This isn't quite what you're asking, but it's an alternative that works now.

The thought of an #exit compiler directive is interesting though.

2 Likes

When I first read this, I had a kneejerk "no" reaction. The more I thought about it, the more I liked the idea that it would be detached from any IDE, and apply cross-platform. The result would be succinct, cleaner code with less indentation.

I lean towards #guard os/#guard platform or any other condition that applies to the entire file from the guard statement forward. Update: I like Wux's approach with #exit a lot.

For consistency with guard, we'd need both #guard and #exit, I think:

#guard os(macOS) else
  #exit
#endguard

[What else could you put inside #guard and #endguard, you might ask: our newly minted #error, of course--and ordinary, compiled code: this would avoid pyramid-of-doom indented code with nested #if just like guard does for if.]

10 Likes

Sounds interesting, but cross-platform for me is macOS and Linux using SPM (which reads all source files in the Sources directory).

1 Like

Take in account that in Xcode 9.3 / Swift 4.1 using if #endif blocks do not indent to contained text.

1 Like

I like this idea. While the problem can already be solved, this solution feels a lot more "swifty", which is probably the right direction. Additionally, compiler controls being so limited in Swift, adding a few more feels as though it provides (at least a feeling) of more control to Swift users.

I see how #exit may be useful, but I'm don't see much value in #guard. guard was introduced to limit the pyramid of doom issue, which does not really exists when using "preprocessor" conditions (they are very rarely nested in Swift). The if variant is even shorter.

#if !os(macOS)
#exit
#endif
1 Like