PSA: Swift 6.4.0 breaks non-inlined macros from reading from disk on linux

As the title states, I am observing my macros that read from disk to no longer work as expected on Linux using the 6.4.0 toolchain. However, they do work as expected if I inline the macro and when expanding it.

Is this change documented somewhere or is it a bug with the new build system? I know this behavior isn't officially supported, but it has worked with toolchains before 6.4.0.

Hey Evan,

This isn't a space I'm personally familiar with, but the way you're describing it certainly sounds like you might have stumbled into a regression. I didn't spot any existing issues reporting anything like this, but I only did a quick overview.

If you've got a simple repro, definitely open an issue with the details, and reference it here - the forums are kind of a lousy place to formally report a bug, but great to ask "if it's a bug" when there's sufficient detail.

The closest thing I was able to repro that might be what you're talking about is a dead simple example of

 #embed("Resources/hello.txt")

Which works and prints "hello" (the contents of that brilliantly named file) with 6.3.3 but fails to build with 6.4. I was using Swift from Xcode 27.2 beta and this is what I stumbled into:

/work/Sources/App/main.swift:3:7: error: cannot read Resources/hello.txt (cwd: /):
Error Domain=NSCocoaErrorDomain Code=260 "The file doesn't exist."
UserInfo={NSUnderlyingError=Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory",
NSURL=Resources/hello.txt -- file:///, NSFilePath=Resources/hello.txt} (from macro 'embed')

I did spot a reference to swiftlang/swift#87180, which looks like it could be related? I'm uncertain if this is what you're running into or not.

More detail and a full on bug report would be ideal.

1 Like

I think I found the source: for some reason the current working directory path changed in 6.4.0 (at least on linux in my use case), where the project's name is no longer added at the end, e.g., for a project named swift-project, here are the current working directories when running an executable target:

  • Pre 6.4.0: /home/user/git/swift-project/
  • 6.4.0: /home/user/git/

In my project specifically, I use the DirectoryConfiguration directly from Vapor using version 4.121.4.

Also made this reproducer: GitHub - RandomHashTags/swift-six-dot-four-dot-zero-macro-regression-cwd: Swift CWD (current working directory) problem on Linux reproducer comparing 6.3.2 & 6.4.0 (with a macro reading from disk) · GitHub

I suspect this effects all Swift projects on Linux, not just macros, but I haven't verified it apart from successfully creating a reproducer. Should I open an issue under swift-build, swift or somewhere else?

Apologies for the delay - I was off on vacation for a bit. I'd recommend opening a new issue on swift-package-manager with the details of the regression, providing that repro sample either as link or as a zipped example in the issue itself, which can make it easier to see and check.

1 Like

I don't think it can be considered a regression. There's no way to correctly support incremental builds and side effects in macros at the same time.

By side effects I mean file system and networking access, any kind of I/O, uses of Date.now, randomness etc.

The build system will not rebuild a file in incremental builds if such file hasn't changed on the file system. Since there's no way for macros to communicate their side effects to the build system, macros should not have side effects in the first place. You shouldn't expect that your macros will behave correctly if they do.

See also:

4 Likes

I thought allowing for side effects was entirely why macros aren't cached right now? I mean, I agree that they shouldn't be supported, or perhaps should be a special opt into behavior, but I thought I read that such support was the reason why macros get reexpanded on every build.