Compilation extremely slow since macros adoption

Yep, the package is mine and the more I use macros the more I struggle with weird compilation errors in other packages (and I see and share more rage about swift macros in the community), probably gonna update everything by extracting all macros in separate packages until it becomes a binary and linker issues are fixed ;-;

Didn’t notice any difference in compilation time since I use TCA which already had macros :sweat_smile:

However adding macros was a breaking change and was handled accordingly to the semver, the package should be imported as .upToNextMinor(from:) as told in readme to avoid unexpected updates :new_moon_with_face:

IMO macros is a language feature so it should be a part of the toolchain, it’ll be weird if usage of some basic library will require downloading some additional cli :alien:

Want to add that — even if caching were only possible for pre-defined configurations (e.g. using swift-syntax 5.9.0 with swiftc 5.9.0 on macOS) — this would IMO alleviate 80% of the concerns that so many folks have. Really hoping this can be addressed sooner rather than later. Speaking for myself and others I've worked with, the cost has been viscerally tangible due to the significant increase in CI minutes and squandered development time.

5 Likes

@johnno1962's cooking something here:

Very much a work in progress but I think I've reached the point where I can say it's not impossible. Watch this space...

1 Like

Yes, thank you.

@John_McCall @ahoppen While it’s nice to have some compiler team presence here, your responses do have me wondering if the Swift team understands the problem folks are running into, and unfortunately we haven’t been given any insight into whether Swift is looking into solving it.

Folks adopting libraries with macros are seeing a significant impact to compile times due to SwiftSyntax regardless of macro usage. I've seen folks mention that they are banning libraries that use macros from their code bases for this reason.

While I share the team’s enthusiasm for Swift macros, and have already adopted a few of them in our libraries despite the cost, the cost still does weigh on us and our library users. I would like to maintain a positive outlook on their future, but I think it would put some of us at a bit more ease to know that Apple recognizes that there is a problem and is working on a solution.

Perhaps this could be a topic at the next workgroup meeting?

26 Likes

It doesn't seem that there is a viable way to isolate the impact of macros. The tiniest change to my Package.swift, triggers a complete recompile of SwiftSyntax each time.

1 Like

I agree with this. I think people are focusing on the amount of code being generated or compiling libraries in debug vs. release mode. On the other hand, the issue is macros are not going to be adoptable if the users have to compile SwiftSytanx on every build which adds ~5 minutes to the build time (more on CI).

Could macros use SwiftSyntax via. standard library (pre-compiled version)?

3 Likes

Echoing @stephencelis, @DandyLyons and @shahzadmajeed's points, it is highly concerning that this issue needs to be spelt out at all.

I'd expect a responsible maintainer to disclose these severe caveats in bold. That this thread exists where people are meekly chiming in day over day to no real acknowledgement should be seen as a massive failure.

7 Likes

I think I'm finally ready to release this project to get a bit more feedback. It contains pre-compiled 509.1.1 versions of the main swift-syntax modules for macOS, iOS simulator and device in a form that you can add to a project using macros to avoid excessive recompiles. It didn't quite turn out as I expected as you don't subscribe to it directly from a macro package but drag the repo onto your app project using macros so it takes the place of anything named swift-syntax in the macro packages you are importing.

In this way it acts as a firewall between your project and the 38,000 line swift-syntax source repo and hopefully will go a bit easier on Xcode. It also means macro developers don't have to subscribe to the binary repo directly which would create versioning nightmares. For details on how to adopt it consult the README of the project. For some reason your project needs to have built without the package override before you add it but perhaps even that will get solved eventually. Right at the end I discovered someone else had made a start on this back in November. This repo is very much the same idea with a few gnarly technical kinks related to sandboxing straightened out.

Ultimately the place for these binaries is either on swift.org or in a toolchain but I can understand they don't want to declare ABI stability on swift-syntax just yet. Hopefully this provides a solution (for Xcode) in the meantime. Feel free to raise any issues you come up against on the repo.

4 Likes

any chance this can help those of us on linux facing the same problem?

1 Like

I'm afraid not, nor does it help slowdowns in CI but some inventive soul might find a solution on Linux where you won't come up against the many sandboxing "challenges" I encountered. Just to be clear, macros execute in a heavily protected environment and I haven't changed that. The macro "plugin" is just statically linked to swift-syntax as the frameworks can't dynamically load. So the package contains binary frameworks for the .swiftinterface files and, a static library. It's all in the Package.swift.

2 Likes

I’m sorry if my response gave the wrong impression. I do not personally work on the macros feature, and I have not been following this thread for the last few months.

The LSG is aware that there are build-system issues causing a lot of pain for macro adopters and their downstreams. From an abstract language perspective, I don’t think any of those problems are particularly challenging to the point of requiring an overall design change to macros; the project just needs to put in the work to fix them. I can’t tell you when that will happen, though, which I know is not a satisfying answer.

23 Likes

This may have been premature. I'll have to provide my own feedback and downgrade this repo from being a "solution" to a "proof of concept". Further testing has shown that you get duplicate copying errors when you are importing more than one macro package and for an iOS project while your project builds and previews, the source editor is flakey (I was doing my testing with a macOS project).

My impression is still the solution to these problems lies in some form of binary distribution even if that doesn't provide a solution for Linux. If using a macro is going to add 38,000 lines of code to your project it's going to be difficult for even the best build system in the world to be performant.

2 Likes

Does anyone know if this slowness applies to SwiftUI’s @Observable and the new SwiftData macros?

Im hesitant to adopt these macros for my projects if compile times are orders of magnitude slower.

No, all of Apple's macros are blessed with being pre-compiled and so do not incur the cost of building SwiftSyntax. There is no slowdown to using @Observable, @Model, etc. Only third party macros have this problem.

5 Likes

There's some compile-time overhead since they do generate a nontrivial amount of code and add an extra build step, but unless your project is 100% @Model types and nothing actually using the models it's negligible.

After @vatsal jumped the gun and my own premature evolution I think I've been able to wrangle my ducks in order with the binary framework project and release it for general use. It took quite a while to get the holy trinity working (building, source editor and previews) and then there are all the platforms you need to build and package – but we should be there now. All the information you need about how to use it should be in the README

I consider the concept well and truly proven now but it won't become a solution until people use it. If your boss is worried about downloading random binary distributions they should remember macros execute in a very restrictive sandbox. Perhaps Apple will come up with something similar in the future or distribute frozen versions of swift-syntax with their toolchains but the approach of dragging the repo onto your project to override all references to the swift-syntax package in macro packages has its own merits which may avoid a good deal of versioning conflicts in the future.

Enjoy.

20 Likes

@johnno1962 this is absolutely incredible, thank you so much!

2 Likes