-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[SR-11760] SwiftPM builds inside Docker do not re-use existing build artifacts #4651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Comment by Eric Stern (JIRA) As a small (or maybe not so small) addition - support for something along the lines of `swift build --dependencies-only` would be hugely beneficial inside of Dockerized builds once this is resolved, in order to maximize the effect of layer caching. It's quite clumsy and counterintuitive to make "dummy files" (as shown in the linked discussion) just to overwrite them with actual source code later. |
Comment by Daniel Alm (JIRA) Fully agree with Firehed (JIRA User). Creating the dummy files is only a workaround; having an option to build only the dependencies would be a much better solution in the long term. |
Comment by Daniel Alm (JIRA) I have investigated a bit more and found the following:
File: .build/debug/CNIOBoringSSL.build/module.modulemap
Size: 163 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 426531 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:13:29.897272000 +0000
Modify: 2019-11-19 11:13:29.517272000 +0000
Change: 2019-11-19 11:13:29.517272000 +0000
Birth: -
File: .build/debug/CNIOBoringSSL.build/crypto/crypto.c.d
Size: 4546 Blocks: 16 IO Block: 4096 regular file
Device: 801h/2049d Inode: 427653 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:13:48.345814000 +0000
Modify: 2019-11-19 11:13:48.335814000 +0000
Change: 2019-11-19 11:13:48.335814000 +0000
Birth: -
File: .build/debug/CNIOBoringSSL.build/crypto/crypto.c.o
Size: 8664 Blocks: 24 IO Block: 4096 regular file
Device: 801h/2049d Inode: 427635 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:13:48.285814000 +0000
Modify: 2019-11-19 11:13:48.335814000 +0000
Change: 2019-11-19 11:13:48.335814000 +0000
Birth: - And from a "later" layer: File: .build/debug/CNIOBoringSSL.build/module.modulemap
Size: 163 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 2930655 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:13:29.000000000 +0000
Modify: 2019-11-19 11:13:29.000000000 +0000
Change: 2019-11-19 11:14:10.058600000 +0000
Birth: -
File: .build/debug/CNIOBoringSSL.build/crypto/crypto.c.d
Size: 4546 Blocks: 16 IO Block: 4096 regular file
Device: 801h/2049d Inode: 2930545 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:13:48.000000000 +0000
Modify: 2019-11-19 11:13:48.000000000 +0000
Change: 2019-11-19 11:14:09.948600000 +0000
Birth: -
File: .build/debug/CNIOBoringSSL.build/crypto/crypto.c.o
Size: 8664 Blocks: 24 IO Block: 4096 regular file
Device: 801h/2049d Inode: 2930546 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:13:48.000000000 +0000
Modify: 2019-11-19 11:13:48.000000000 +0000
Change: 2019-11-19 11:14:09.948600000 +0000
Birth: - Unfortunately, even packaging the build archive in a POSIX tar which is supposed to fully preserves timestamps yields different timestamps, as well as causing a rebuild of all non-Swift dependencies: File: .build/debug/CNIOBoringSSL.build/module.modulemap
Size: 163 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 428027 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:14:15.888600000 +0000
Modify: 2019-11-19 11:13:29.517272000 +0000
Change: 2019-11-19 11:14:15.888600000 +0000
Birth: -
File: .build/debug/CNIOBoringSSL.build/crypto/crypto.c.d
Size: 4546 Blocks: 16 IO Block: 4096 regular file
Device: 801h/2049d Inode: 696234 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:14:15.958600000 +0000
Modify: 2019-11-19 11:13:48.335814000 +0000
Change: 2019-11-19 11:14:15.958600000 +0000
Birth: -
File: .build/debug/CNIOBoringSSL.build/crypto/crypto.c.o
Size: 8664 Blocks: 24 IO Block: 4096 regular file
Device: 801h/2049d Inode: 697210 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2019-11-19 11:14:16.008600000 +0000
Modify: 2019-11-19 11:13:48.335814000 +0000
Change: 2019-11-19 11:14:16.008600000 +0000
Birth: -
@aciidb0mb3r I would really appreciate if you could take a look. Thanks! |
Thanks for the investigation! If the timestamp is changing then I suspect we'll have to use file hashing to determine if the manifest changed. |
Comment by Daniel Alm (JIRA) @aciidb0mb3r another option might be to use only the integer part of the timestamp, dropping the fractional part. |
Comment by Pierpaolo Frasa (JIRA) Is there any update on this issue? |
Comment by Will Lisac (JIRA) Something like `swift build --dependencies-only` would be a great addition. I'm also using the dummy files technique and it becomes increasingly tedious as the number of targets grows. |
Comment by Bridger Maxwell (JIRA) Would it be appropriate to round the timestamp here in the Swift Package Manager source? |
Comment by Daniel Alm (JIRA) This might help, provided it also gains support for Linux: #2774 |
I think one cause of detecting artifacts as "stale" is that llbuild looks at the inode number. There is an open PR to change this algorithm swiftlang/swift-llbuild#641 I believe that separately, there is a way to adjust llbuild behavior by supplying a key to the right location. According to the documentation > A file-system field may be supplied that toggles how the build system handles file system use. The default mode uses detailed stat information for detecting file changes. The device-agnostic mode will ignore device and inode values. |
Comment by Bridger Maxwell (JIRA) The blog post for Swift 5.3 mentions better caching https://swift.org/blog/swift-5-3-released :
I can't find any other information about this change. Any chance it relates to this bug? Lately I'm desperate for something to speed up my Swift builds. |
Comment by Daniel R (JIRA) +1 on something like `swift build --dependencies-only` I'm also creating dummy files as a workaround. |
@swift-ci create |
My colleague Euan Harris just made me aware of a new (experimental) Docker feature in BuildKit which can alleviate this problem. If you create your
then it will rebuild fast. You will need to use As an explainer, the Long story short, if you can, use BuildKit. If for whatever reason you cannot use BuildKit, you can contact me directly, I have a hack that lets you use cached builds with plain old stuff (no BuildKit). |
Comment by ML (JIRA) I ran into the same problem with aws codebuild which uses a buildspec.yml for the build commands. @weissi would you be so kind and share your "hack" as buildkit is not suitable in codebuild(as far as I know). Thanks! |
Comment by spk (JIRA) @weissi using CircleCI here. Could you please share your "hack" ? Thanks! |
spk (JIRA User) Sure, I used this C file that I compiled into a dynamic library ( |
Oh, with "this file" I mean the now attached Again, the right solution is to use this docker feature:
which instructs docker to mount a volume instead of copying in the files. That'll make everything work without hacks. |
Comment by spk (JIRA) Thanks so much! 🙂 |
@weissi, it looks like the hack you provided in the original JIRA ticket is gone. Could you please attach that file again? Also is there any chance this issue will be resolved without making a switch to the BuildKit? |
@Terky there you go. You'd need to compile But really, you should switch to BuildKit with cache layers. BuildKit is now enabled by default in |
BuildKit with cache mount is still no full solution: IMHO there is no way around detecting code changes without Inode checks. |
Yes, alas, I think this is true at the moment. I couldn't immediately find a way to turn off the inode number comparisons (https://github.com/apple/swift-llbuild/blob/b7b4c5eaa798708d6233ca07908a7cab75620040/products/llbuildSwift/BuildValue.swift#L59). @dmbryson any thoughts? |
@tomerd do you think you would consider a |
We have rdar://96403757 (SwiftPM - consider setting file-system: device-agnostic in build manifest) which may resolve this? I'm not sure we even need an option, I think passing |
I still have this issue. Is there an approach to build it. Is the option to ignore the inode numbers added? Could somebody with more knowledge then me create some documentation on recommended setup of a swiftpm build for CI? Or does the latter exist already? |
sets file-system as device-agnostic in build manifest ### Motivation: This is the default mode in XCBuild, and allows incremental builds to work across reboots on APFS. It would also likely address #4651. ### Modifications: sets file-system as device-agnostic in build manifest ### Result: Restarting your system (or inode changes) doesn't invoke unnecessary builds Related to rdar://96403757.
sets file-system as device-agnostic in build manifest ### Motivation: This is the default mode in XCBuild, and allows incremental builds to work across reboots on APFS. It would also likely address #4651. ### Modifications: sets file-system as device-agnostic in build manifest ### Result: Restarting your system (or inode changes) doesn't invoke unnecessary builds Related to rdar://96403757.
Cherry-pick of #7052. ### Motivation: This is the default mode in XCBuild, and allows incremental builds to work across reboots on APFS. It would also likely address #4651. ### Modifications: Set `file-system` as `device-agnostic` in the generated build manifest ### Result: Restarting your system (or inode changes) doesn't invoke unnecessary builds Related to rdar://96403757. Co-authored-by: Kishore Pusukuri <kishoreguptaos@gmail.com>
@doozMen is this issue reproducible for you with latest 5.10 development snapshots? |
Hmm sorry I had a look at your fix in #7189 and that seams like the valid thing to do to solve the issue. But installing a development snapshot to verify this seams like something I do not have the time for right now. I would love to test it with 5.10 do. |
The PR linked should address the issue in 5.10 and |
Goodmorning to everybody, |
We are also experiencing problems with C dependencies not being properly cached from a previous build when running builds or tests in gitlab-ci for a simple Vapor app. I set up a simple test project with pipeline here. You can see the output of a job where the build should have been cached entirely here. When producing release builds these build times naturally increase even a bit more as you can see here. Is there any recommended way to deal with this or anything spm can do about it? |
@fred-sch have you tried the cache mentioned above using So far, I have not found a configuration that properly reuses cached dependency build results on GitHub CI, even though it works with local docker builds. |
@maerki, I can confirm that Unfortunately, it would complicate our pipelines a bit to execute everything in dind in gitlab-ci. Particularly, I don't think unit tests should be executed during a docker build stage. Since I have not found a really satisfying solution to make something like |
Attachment: Download
Environment
Swift 4.2 all the way till Swift 5.2.4.
Additional Detail from JIRA
md5: 6c4efa086896ce15ed52fa119adc9b54
Issue Description:
See https://forums.swift.org/t/incremental-builds-with-swift-package-manager-and-linux-docker/26538 for a full description. @aciidb0mb3r has asked to file a Jira ticket about this issue.
My suspicion is that SwiftPM for some reason considers build artifacts in lower Docker layers stale and thinks that it needs to rebuild them.
The text was updated successfully, but these errors were encountered: