Support for disabling ARC

I have a library where I use -fno-objc-arc to disable automatic reference counting. However, I don't see an option in SwiftPM to put this flag in (aside from unsafeFlags which defeats the purpose of the library). I have benchmarked it, and this flag improves the performance, so I would really like to continue using it.

On a side note, it seems that not very many of the flags that clang/swiftc has are supported by SwiftPM. This means that many projects will need to make forum posts like this to get them sorted out, which is a cumbersome process for both the project maintainers and the SwiftPM devs. I imagine it hurts adoption, e.g. the Firebase project has the same issue. It seems like SwiftPM should proactively create either a blacklist or a large whitelist of flags, rather than just waiting for devs to create forum threads.

1 Like

This seems like a strange complaint to me. Disabling ARC is the definition of an unsafe optimisation: your library will trivially leak memory, and the odds of your users correctly handling this are approximately zero. If you're the only user, you can add this flag at build time by using the SwiftPM support for passing build flags on the command line. If you have third-party users, you should not be enabling this flag anyway.

3 Likes

Consumers don't have to do any memory management themselves, everything comes into and goes out of the library as expected. Manual memory management isn't even possible for the consumer when they're using ARC. Internally, however, memory management is done manually. Did you know that adding trivial helper functions can cause extra retain/releases? This sort of thing causes a significant slowdown. Whether I should do this or not is like asking whether I should write C/C++ or not. It's a tradeoff of speed vs. safety. You can see plenty of C/C++ code in big projects like Texture, Yoga, etc.. And this is for a library, so I can't use unsafeFlags.

1 Like

How are you manually managing the memory of Swift objects?

I do. We work with the Swift team to help provide these as test cases to improve Swift performance. :smile:

This is for Objective-C code

1 Like

Ah, sorry, I forgot that you are manually managing the memory of Objective-C objects, not Swift ones. My mistake.

SwiftPM is generally planning to add flags only as they seem necessary. I can't speak for them, but I doubt this is going to be high up their list.

What makes something necessary? Is performance necessary? Surely they wouldn't reject something on the grounds that it can be used unsafely. SwiftPM already supports unsafe code in the form of C, C++, calls from Swift into libc, that one unowned unsafe flag, etc..

Protobuf is an example of a library used by both Objective C and Swift users that requires disabling ARC for the library build. Note, there is no request that I can tell, to make the library consumer code less safe.

To take a step back, what is the reason that SwiftPM is so prescriptive about how library producers and consumers work together? This prescriptiveness will increase the challenge of migrating many CocoaPods and Carthage libraries to SwiftPM.

3 Likes

That is a matter for the Swift community in the form of enhancement proposals, pitches, forum discussion, and code review.

If you want to propose adding the flag, that's a proposal that can be made. The original build settings proposal envisions adding further settings, and considers the unsafeFlags to be an escape hatch for things SwiftPM does not currently understand the semantics for. Reproducing that section of the proposal for clarity:

This is an escape hatch that will allow targets to pass arbitrary command-line flags to the corresponding build tool. The "unsafe" here implies that SwiftPM can't safely determine if the build flags will have any negative side-effect to the build since certain flags can change the behavior of how a build is performed. It is similar to how the -Xcc , -Xswiftc , -Xlinker option work in the command-line SwiftPM tools.

The primary purpose of this escape hatch is to enable experimentation and exploration for packages that currently use a makefile or script to pass the -X* flags.

As with all open source projects, the easiest way to get SwiftPM support is to write a patch that would add the support you want, and then open that as a pull request and write a forum pitch explaining your rationale.

I am not a SwiftPM developer so I don't have a definite answer here (cc @aciid). However, my guess is that the paragraph above explains the thinking: SwiftPM wants to feel confident that it understands the effects various settings have on builds and how they affect the way that build happens. This requires a semantic understanding of how the flags operate.

3 Likes

Agreed. SwiftPM is not friendly for system library author who port to iOS, like libwebp, protobuf, yoga. Those are all daily iOS App’s core dependency, which hard to get same performance and maintained integration as CocoaPods or Carthage.

5 Likes
#if __has_feature(objc_arc)
    #error PerformanceCriticalFramework has to be compiled without ARC. Add -fno-objc-arc to unsafeFlags in your Package.swift
#endif

And if you ever decide to turn ARC back on, you can just negate the check and error when it's off.

You can also create macros for release/retain, so this is the only error when compiling. (But you probably already have that for easy benchmarking)

This won't be really useful because our problem is having some frameworks that uses ARC and we need distribute them as Swift Packages.