How to install Swift once it's built?

So I built Swift from source on Linux with utils/build-script --release-debuginfo --install-swiftpm true -j8 but after it finished, it had not installed swift into /usr/bin or anything else. Instead everything was nested in a build folder.

How can I install it into the base directories of Linux? Is there a script included in the Swift repo to do that, or an argument I need to pass to the build script?


It's not well-documented, but adding --install-destdir will do what you want. The README notes that you can learn a lot by running utils/build-script -h, it's listed in there. You may need to patch the install a bit based on your distro layout and installed packages though, as the Fedora packager had to.

Alternately, the --install-swiftpm flag will have already put everything in a build/Ninja-Release/toolchain-linux-x86_64 directory, from which you can just manually copy all non-conflicting files to /usr.

It isn't an easy process yet, given that Swift builds its own clang that could conflict with an installed clang, so you're probably best off using the Swift toolchain you built from your home directory, by adding that toolchain folder to your path.

1 Like

I'm the person who packages Swift for Fedora/RHEL/CentOS and if you're building it yourself, I recommend installing swift in /usr/local/swift and adding /usr/local/swift/bin/ to your path, after /usr/bin. The reason, as @Finagolfin mentions, is that, since you built your own copy of Swift, you already have clang installed, probably in /usr/bin and you don't want the Swift-specific version to override the system one.

One thing I have come to appreciate, after fighting it so hard for a very long time (also mentioned by Buttaface), is that the Swift toolchain/directory is completely self-contained, executables look for other executables in the same directory so it's completely valid to put the swift directory (comprised of bin, lib, etc.) anywhere you like and so long as the path is set, you can build Swift apps, use the REPL, etc.

In Fedora I ended up installing the Swift toolchain under /usr/libexec/swift with symlinks of swift, swiftc, and sourcekit-lsp in /usr/bin and it works great, especially using SourceKit with Vim/VS Code.

1 Like

Great, thanks for all the info. I built it on CentOS 7, and it's been quite the adventure! It's reassuring to hear I'm not the only one who might describe it as, "fighting it so hard for a very long time" :sweat_smile:.

So to be clear @Ron_Olson, you added --install-dest-dir /usr/libexec/swift to the build-script args?

You can take whatever you need (if anything now :joy:) from; it’s all my scripts and patches and random stuff to make Swift work; there’s a swift-5.3 branch that I’m working with now in case you’d like to use any of that.

I don't see anything helpful at the link you sent.

I'm still having trouble to understand the difference between the following options:

  --install-prefix PATH
                        The installation prefix. This is where built Swift
                        products (like bin, lib, and include) will be
  --install-destdir PATH
                        the path to use as the filesystem root for the

I added --install-destdir to my build-script command and literally it did nothing at all differently than before.

Please advise.

I don't see anything helpful at the link you sent.

That's probably because he uses a build preset.

I'm still having trouble to understand the difference

The second is the sysroot, usually / but could be /opt or whatever, and the first is an optional prefix within the sysroot, usually /usr. If simply adding destdir to the build command you had before, I'm guessing you need to --reconfigure also.

You're probably best off using one of the build presets detailed in that second doc link, as most people do. At the very least, the list of build presets give you common flag bundles to try out and customize, if you really need to.

Ah, sweet! Thanks @Finagolfin that cleared it up for me!

Happy to report a working Swift build on CentOS 7.

One question for @Ron_Olson: your repo specifies "buildbot_linux"--where is that defined? Can't seem to find the definition in your repo, and when I try this command it fails.

It's actually a preset in swift/utils/build-presets.ini. It defines what actually gets built and tested (e.g. no point trying to test Swift for WatchOS on Linux :rofl:).

I wonder why it's not working for me... hmm. Which line is it declared on? And is it in Swift 5.2.4?

For 5.2.4 buildbot_linux is declared on line 772 in build-presets.ini

OK maybe I had a typo, will try the buildbot_linux and see if that works...

... because oddly, this command does not result in the build products being installed at the prefix:

utils/build-script --release-debuginfo \
     --install-swiftpm true \
     --install-destdir / \
     --install-prefix /usr \
     --reconfigure -j8

I wonder if perhaps it needs to be:

utils/build-script --release-debuginfo \
     --install-swiftpm=true \
     --install-destdir="/" \
     --install-prefix="/usr" \
     --reconfigure -j8


The documentation doesn't specify that the = sign is required for setting parameters but, it's the only reason I can think of why the commands wouldn't work.

So I tried this command:

utils/build-script --preset=buildbot_linux,no_test install_destdir=/usr -j8

But I get this error:

utils/build-script: fatal error: no value found for installable_package in "%(installable_package)s"

I noticed in @Ron_Olson's script a value is given for installable_package... but for my use case, I'm not trying to create an "installable package"—I'm just trying to build and install Swift compiler and Swift package manager on the same system that I'm building on.

Is there an existing script command will automatically install Swift using /usr as the root of the installation, so that for example, we will have /usr/bin/swift etc.? Sorry I'm asking so many questions but I can't get the buildbot to work, and none of the commands listed above seem to do the trick either.

If the only way to install Swift is to write a secondary script that runs after the build process, which manually copies it out of the build folders, then I'll do that. But I guess I was expecting to be able to do something like "make install" and it would "just work".

Thanks for any help.

It cannot "just work" because Swift builds specific versions, sometimes locally forked, of ICU, lldb, clang, and so on. Many people have those already installed in /usr/bin, so it is up to you to decide how to resolve those conflicts, if they exist.

If you don't want an installable package, simply build it but don't use it or you can modify build-presets.ini to not require it, as Ben mentioned in another thread.

Most of your questions are answered by carefully looking at the examples and config files in the documentation links I've linked you above. There are some aspects that are unintuitive, so you can ask about those here.