[swift-evolution] [swift-build-dev] [Proposal] Lock file for Swift Package Manager

Ankit Agarwal ankit at ankit.im
Wed Dec 23 10:02:51 CST 2015

Thank you all for the valuable feedback I have updated the proposal to
reflect the changes which are agreed upon by majority. Please go through
the updated proposal below and provide more feedback.

Lock File for Swift Package ManagerIntroduction

A Package.lock file containing list of resolved dependencies generated by

Package.lock file can be helpful in situations like :
Reproduce exact versions of dependencies on different machine

   - Multiple developers working on a package would want to use the exact
   versions(including minor and patch) of the dependencies declared in the
   manifest file
   - When a build is being performed on a remote machine eg CI

Pointing a dependency to an untagged commit

Sometimes it might be helpful to lock a dependency to a particular commit
ref for which a tagged version is unavailable in cases such as :

   - Forking a 3rd party library and making it swiftpm compatible for
   temporary use until officially supported by the author
   - Package is in active development and not ready for a release tag

Proposed Solution

swiftpm generates a simple Package.lock file after resolving the dependency
graph for that package in some simple format.
Detailed DesignPackage.lock aka the lock file

Package.lock is a plain text auto-generated file containing list of
resolved dependencies: one line per dependency in format

 <gitURL> <resolvedVersion>

"github.com/foo/bar" "v1.1"
"../mygitdir" "v2.3"
"github.com/my/forked/dep" "8b3989be184375ae6e84e8a0254e5258789b23e5"

   - Package.lock will always contain the exact version of the dependency
   resolved by SPM
   - User is expected to commit the lock file into the git repo for others
   to reproduce the exact versions of dependencies on their system
   - lock file of dependencies are ignored and only their Package.swift is
   taken into consideration for resolving all the dependencies

User is not expected to interact with this file as it'll always be
generated by SPM so it might make sense to:

   - not to use swift syntax in this file.
   - keep it seperate from Package.swift to avoid confusion for new users.

Another option could be using very minimal valid swift syntax for eg :

 ("github.com/foo/bar", "v1.1"),

Workflow$ swift build :


   Dependencies declared in Package.swift and Package.lock is not present :

   Resolves Package.swift and generates Package.lock; uses the generated
   Package.lock to fetch and build the dependencies

   Package.lock already present :

   Uses the generated Package.lock to fetch and build the dependencies.

   if Package.swift has been modified SPM generates a warning for user to
   consider updating the lock file using $ swift build --update (explained

   Packages/ is out of sync with lock file :

   *Uncommited changes in Packages/* : User is probably trying to modify
   the dep so suggest him to use the $ swift build --ignore-lock command
   (explained below)

   *Commited changes in Packages/* : User is done making changes in the
   dependency but forgot to lock them so HEADs don't match, suggest
him to use $
   swift build --lock command (explained below)

$ swift build --update :

   - Remove current Package.lock if present and re-resolve Package.swift to
   generate a new Package.lock file for all the deps.
   - To update only one dependency use $ swift build --update=<dep_name>

$ swift build --lock :

   - Locks the current HEAD packages in Packages/ and writes them into the
   lock file uses tags where available otherwise refs
   - To lock only one dependency use $ swift build --lock=<dep_name>

$ swift build --ignore-lock :

   - Ignores the lock file and use HEAD of Package/ to build the deps
   without writing to lock file
   - Useful for development

Workflow for Pointing a dependency to an untagged commit

   - Create Package.swift and declare dependencies
   - Run $ swift build to resolve and build the Package
   - Modify and play with the checkedout dependencies in Packages/
   - Commit and push the changes to the git remote mentioned in
   - Once satisfied with the current state of a package lock it using $
   swift build --lock=<dep_name>
   - Commit the lock file and push for others to use

If a dependency(foo) is using a dependency(bar) with an untagged commit

   - Author of foo mentions in their readme that they're using bar on an
   untagged commit
   - Package(baz) wanting to use foo and bar both will need to lock his bar
   package to same untagged commit

Impact on existing code

None on the code but old users will not be able to run $ swift build with
changes in their Packages/ which is possible right now, they'll need to use $
swift build --ignore-lock instead which will be communicated using warnings
as stated above.
Alternatives Considered

One alternative is to allow mentioning refs in manifest file while
declaring a dependency but as discussed in this
it might not be the best idea.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151223/2f4dac73/attachment.html>

More information about the swift-evolution mailing list