Skip to content
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

[SR-648] swift package manager should have the option to produce statically linked binaries #5432

Open
swift-ci opened this issue Jan 30, 2016 · 41 comments

Comments

@swift-ci
Copy link
Contributor

Previous ID SR-648
Radar rdar://problem/32618121
Original Reporter jaybuff (JIRA User)
Type Improvement
Additional Detail from JIRA
Votes 34
Component/s Package Manager
Labels Improvement
Assignee None
Priority Medium

md5: a97136565bbf5fd9b15515ab552f61b8

is blocked by:

  • SR-2280 swiftc -static-stdlib option fails on Ubuntu 14.04 & 15.10

is duplicated by:

  • SR-727 (emscripten support) Compile Swift code with statically linked stdlib
  • SR-10624 SwiftPM doesn't hand --swift-static-stdlib through

relates to:

  • SR-2280 swiftc -static-stdlib option fails on Ubuntu 14.04 & 15.10
  • SR-10625 tests for -static-*
  • SR-730 Flag to statically link Swift standard library

Issue Description:

When I do swift build for a simple hello world swift program it ldd tells me that it is linked against libstdc++.so.6, libswiftCore.so and other .so files. I would like to ask swift build to produce a single file that is not dynamically linked against any shared objects.

@swift-ci
Copy link
Contributor Author

swift-ci commented Feb 1, 2016

Comment by Kostiantyn Koval (JIRA)

can you please provide your build output, and your "Hello world" program. Are you running it on Linux or Mac OS ?
I dont see that "libstdc" is included in my examples (not for exe or lib)

Example:

//Exe target
print("Hi Main")

//Lib target
func a() {
  print("Hi Main")
}

//Exe target 
swift build -vv
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swiftc --driver-mode=swift -I /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/lib/swift/pm -L /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/lib/swift/pm -lPackageDescription -target x86_64-apple-macosx10.10 /Users/konstantin/Work/spmExample/Simple/Package.swift
/usr/bin/xcrun --sdk macosx --show-sdk-path
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swift-build-tool -v -f /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/llbuild.yaml
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swiftc -module-name Simple -incremental -emit-dependencies -emit-module -emit-module-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.swiftmodule -output-file-map /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/output-file-map.json -c /Users/konstantin/Work/spmExample/Simple/main.swift -I /Users/konstantin/Work/spmExample/Simple/.build/debug -j8 -Onone -g -v -target x86_64-apple-macosx10.10 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I /usr/local/include -D SWIFT_PACKAGE
Apple Swift version 3.0-dev (LLVM f95d47afa7, Clang f66c5bb67b, Swift b745691a38)
Target: x86_64-apple-macosx10.10
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swift -frontend -c -primary-file /Users/konstantin/Work/spmExample/Simple/main.swift -target x86_64-apple-macosx10.10 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I /Users/konstantin/Work/spmExample/Simple/.build/debug -I /usr/local/include -g -D SWIFT_PACKAGE -emit-module-doc-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/main~partial.swiftdoc -Onone -module-name Simple -emit-module-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/main~partial.swiftmodule -emit-dependencies-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/main.d -emit-reference-dependencies-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/main.swiftdeps -o /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/main.swift.o
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swift -frontend -emit-module /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/main~partial.swiftmodule -parse-as-library -target x86_64-apple-macosx10.10 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I /Users/konstantin/Work/spmExample/Simple/.build/debug -I /usr/local/include -g -D SWIFT_PACKAGE -emit-module-doc-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.swiftdoc -module-name Simple -o /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.swiftmodule
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swiftc -o /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/main.swift.o -target x86_64-apple-macosx10.10 -Xlinker -all_load -g -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -L/usr/local/lib


//lib target 
swift build -vv
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swiftc --driver-mode=swift -I /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/lib/swift/pm -L /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/lib/swift/pm -lPackageDescription -target x86_64-apple-macosx10.10 /Users/konstantin/Work/spmExample/Simple/Package.swift
/usr/bin/xcrun --sdk macosx --show-sdk-path
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swift-build-tool -v -f /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/llbuild.yaml
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swiftc -module-name Simple -incremental -emit-dependencies -emit-module -emit-module-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.swiftmodule -output-file-map /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/output-file-map.json -parse-as-library -c /Users/konstantin/Work/spmExample/Simple/A.swift -I /Users/konstantin/Work/spmExample/Simple/.build/debug -j8 -Onone -g -v -target x86_64-apple-macosx10.10 -enable-testing -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I /usr/local/include -D SWIFT_PACKAGE
Apple Swift version 3.0-dev (LLVM f95d47afa7, Clang f66c5bb67b, Swift b745691a38)
Target: x86_64-apple-macosx10.10
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swift -frontend -c -primary-file /Users/konstantin/Work/spmExample/Simple/A.swift -target x86_64-apple-macosx10.10 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I /Users/konstantin/Work/spmExample/Simple/.build/debug -I /usr/local/include -enable-testing -g -D SWIFT_PACKAGE -emit-module-doc-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/A~partial.swiftdoc -Onone -parse-as-library -module-name Simple -emit-module-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/A~partial.swiftmodule -emit-dependencies-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/A.d -emit-reference-dependencies-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/A.swiftdeps -o /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/A.swift.o
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a.xctoolchain/usr/bin/swift -frontend -emit-module /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/Simple/A~partial.swiftmodule -parse-as-library -target x86_64-apple-macosx10.10 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I /Users/konstantin/Work/spmExample/Simple/.build/debug -I /usr/local/include -enable-testing -g -D SWIFT_PACKAGE -emit-module-doc-path /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.swiftdoc -module-name Simple -o /Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.swiftmodule
/bin/sh -c "rm -f '/Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.a'; ar cr '/Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.a' '/Users/konstantin/Work/spmExample/Simple/.build/debug/Simple.o/A.swift.o'" 

@swift-ci
Copy link
Contributor Author

swift-ci commented Feb 1, 2016

Comment by Kostiantyn Koval (JIRA)

Also I've verified that generated `Simple.a` static library don't have any dynamic loaded dependencies

otool -L Simple.a
Archive : Simple.a
Simple.a(A.swift.o): 

@swift-ci
Copy link
Contributor Author

swift-ci commented Feb 1, 2016

Comment by Jay Buffington (JIRA)

This is in Ubuntu 15.10

$ ls -la
total 20
drwxrwxr-x   4 501 dialout  136 Feb  1 19:31 .
drwxr-xr-x 292 501 dialout 9928 Feb  1 19:28 ..
-rw-rw-r--   1 501 dialout    0 Feb  1 19:28 Package.swift
drwxrwxr-x   3 501 dialout  102 Feb  1 19:29 Sources

$ cat Sources/main.swift
print("hello world")

$ swift build
Compiling Swift Module 'swiftstatic' (1 sources)
Linking Executable:  .build/debug/swift-static

$ ldd  .build/debug/swift-static
    linux-vdso.so.1 =>  (0x00007fff3fb40000)
    libswiftCore.so => /home/jaybuff/swift-2.2-SNAPSHOT-2016-01-11-a-ubuntu15.10/usr/lib/swift/linux/libswiftCore.so (0x00007fa3b782e000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa3b74a2000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa3b719a000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa3b6f83000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa3b6bb8000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa3b699a000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa3b6796000)
    libicuuc.so.55 => /usr/lib/x86_64-linux-gnu/libicuuc.so.55 (0x00007fa3b6401000)
    libicui18n.so.55 => /usr/lib/x86_64-linux-gnu/libicui18n.so.55 (0x00007fa3b5f9e000)
    libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fa3b5d8e000)
    /lib64/ld-linux-x86-64.so.2 (0x000055e1b014c000)
    libicudata.so.55 => /usr/lib/x86_64-linux-gnu/libicudata.so.55 (0x00007fa3b42d6000)

@swift-ci
Copy link
Contributor Author

swift-ci commented Feb 3, 2016

Comment by Kostiantyn Koval (JIRA)

Here is the output I get for the MacOS. It includes 3 dynamic libraries.

otool -L .build/debug/Simple
.build/debug/Simple:
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
    @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)

Also the package manager doesn't control this behaviour. I think it's more related to the LLBD (the build system).

@mxcl
Copy link
Contributor

mxcl commented Feb 19, 2016

Discussion of this on the lists suggests this isn't yet possible, so we need to open a bug on Swift itself so that it gains the option to link statically on Linux.

@ddunbar
Copy link
Member

ddunbar commented Jun 9, 2016

This should be unblocked, it would be great to get this in the Swift 3.0 timeframe.

@abertelrud
Copy link
Contributor

I'm checking to see if this is working now (this issue hasn't been updated for a while now). If it works, great, but if not, it seems to me that we are out of time for Swift 3 for this.

@abertelrud
Copy link
Contributor

When I try `swift build -Xswiftc -static-stdlib` on Ubuntu 14.0.4, I get this:

/usr/bin/ld: cannot find -lbsd
/usr/bin/ld: cannot find -licui18n
/usr/bin/ld: cannot find -licuuc
clang: error: linker command failed with exit code 1 (use -v to see invocation)
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)
<unknown>:0: error: build had 1 command failures
error: exit(1): /home/user/Documents/usr/bin/swift-build-tool -f /home/user/Documents/SR648/.build/debug.yaml -v
user@ubuntu:~/Documents/SR648$ gedit /home/user/Documents/SR648/.build/debug.yaml

@abertelrud
Copy link
Contributor

It isn't that clear to me where this comes from. SwiftPM doesn't seem to be passing it down.

@abertelrud
Copy link
Contributor

On macOS it works, so this might be a toolchain incompatibility with Ubuntu 14.0.4. I will try on Ubuntu 15.10 and file a JIRA if it's incompatible.

@abertelrud
Copy link
Contributor

I can reproduce this in a small test case, and I have filed SR-2280.

@abertelrud
Copy link
Contributor

I am removing the swift-3.0 label from this, since it is blocked by SR-2280.

@spevans
Copy link

spevans commented Sep 12, 2016

Should a static executable option be added to swiftc or the swift-build-tool? I think an `-emit-static-executable' or '-emit-executable -static' option added to swiftc might be the best approach rather than the package manager so it can be used directly

I have a solution for this for Linux/ELF which uses a small stub to fix up the linker issues which I can turn into a PR

static_stub.c

#if defined(__LINUX__) && defined(__ELF__)
#error "This only works on Linux/ELF"  // Needs testing on other ELF platforms
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define __USE_GNU
#include <link.h>

// This forces resolving of these weak symbols but keeps them hidden
// externally
const void *unused1 __attribute__ ((unused, visibility("internal"))) = pthread_self;
const void *unused2 __attribute__ ((unused, visibility("internal"))) = pthread_key_create;
const void *unused3 __attribute__ ((unused, visibility("internal"))) = pthread_once;


// libdl emulation to load the protocol and metadata sections, these get fixed
// using the --defsym linker commands below
extern void *__swift2_protocol_conformances_start;
extern void *__swift2_type_metadata_start;


// Fake a handle if opening NULL (this binary) else abort
void *
dlopen(const char *filename, int flag)
{
    if (filename != NULL) {
        fprintf(stderr, "dlopen called with filename=%s\n", filename);
        abort();
    }
    return (void *)1;
}


// Hardcoded to allow lookup of 2 known symbols, enough for now
void *
dlsym(void *handle, const char *symbol)
{
    if (handle != (void *)1) {
        fprintf(stderr, "dlsym(): bad handle: %p\n", handle);
        abort();
    }
    if (!strcmp(symbol, ".swift2_protocol_conformances_start")) {
        return &__swift2_protocol_conformances_start;
    } else if (!strcmp(symbol, ".swift2_type_metadata_start")) {
        return &__swift2_type_metadata_start;
    } else {
        return NULL;
    }
}


int
dladdr(const void *addr, Dl_info *info)
{
    // FIXME: Dummy implementation for now, returns `not found'
    fprintf(stderr, "dladdr() required for %p\n", addr);

    // info declared as nonnull in dlfcn.h
    info->dli_fname = NULL;
    info->dli_fbase = NULL;
    info->dli_sname = NULL;
    info->dli_saddr = NULL;
    
    return 0;
}


int
dlclose(void *handle)
{
    if (handle != (void *)1) {
        fprintf(stderr, "dlclose(): bad handle: %p", handle);
    }
    return 0;
}


// Hardcoded to return an empty structure, the caller of this only
// cares about the filename anyway and can deal with it being NULL
int
dl_iterate_phdr(int (*callback) (struct dl_phdr_info *info,
                                 size_t size, void *data), void *data)
{
    // Dummy empty structure for dl_iterate_phdr
    struct dl_phdr_info phdr_info = { .dlpi_addr = 0 };

    return callback(&phdr_info, sizeof(struct dl_phdr_info), data);
}


// These commands will get extracted by `swift-autolink-extract'
// and passed to clang++
#define AUTOLINK_ENTRY(x) asm(".asciz \"" x "\"")

asm(".section .swift1_autolink_entries");
AUTOLINK_ENTRY("-static");
AUTOLINK_ENTRY("-Xlinker --defsym=__swift2_protocol_conformances_start=.swift2_protocol_conformances_start");
AUTOLINK_ENTRY("-Xlinker --defsym=__swift2_type_metadata_start=.swift2_type_metadata_start");
AUTOLINK_ENTRY("-licui18n");
AUTOLINK_ENTRY("-licuuc");
AUTOLINK_ENTRY("-licudata");
AUTOLINK_ENTRY("-lpthread");

#endif // linux && ELF
$ clang -O -Wall -Werror -c static_stub.c -o static_stub.o
$ swiftc -static-stdlib -emit-executable -o main main.swift static_stub.o
$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=41e9e4c815e695b8369a03239db50e06d4f00085, not stripped
$ ldd main
    not a dynamic executable
$ ./main
Hello there

This method takes advantage of the auto link section so the static_stub can provide its own linker commands
$ swift-autolink-extract static_stub.o 
-static
-Xlinker --defsym=__swift2_protocol_conformances_start=.swift2_protocol_conformances_start
-Xlinker --defsym=__swift2_type_metadata_start=.swift2_type_metadata_start
-licui18n
-licuuc
-licudata
-lpthread

I have a slightly different solution that patches swift/stdlib which reduces the size of the libdl emulation code and makes it simpler to understand which might be a better approach if its decided to add the option to swiftc rather than swiftpm

@spevans
Copy link

spevans commented Sep 14, 2016

Proposed fix https:// github.com/apple/swift/pull/4754

Updated fix that doesnt use any libdl hacks but instead builds its own version of libicu:
apple/swift#5394

@ddunbar
Copy link
Member

ddunbar commented Nov 30, 2016

Is this done now?

@ddunbar
Copy link
Member

ddunbar commented Nov 30, 2016

Let me clarify, is the swiftc side of this done now?

@spevans
Copy link

spevans commented Dec 1, 2016

It should be done for swiftc and libswiftCore however the other corelibs will need fixing to produce static libraries (that dont use libdl)

@spevans
Copy link

spevans commented May 27, 2017

Ive created a partial solution in apple/swift#9958 It gets the build command down to:

swift build -Xswiftc -static-stdlib -Xlinker -lcurl -Xlinker -lxml2 -Xlinker -lbsd -Xlinker --allow-multiple-definition

Some further work is required to eliminate the ' -Xlinker --allow-multiple-definition' option and a bit more will be needed to automatically generate the list of libs to link.

@spevans
Copy link

spevans commented May 31, 2017

Just a small update:

Currently have 3 PRs to implement the solution in the previous comment:

apple/swift#9958
apple/swift-corelibs-xctest#190
apple/swift-corelibs-foundation#1011

Once that is done I will open a PR adding a `test_static` target to Foundation to create TestFoundationStatic binary as a test.

Then need to remove the duplicate

@ddunbar
Copy link
Member

ddunbar commented Jun 7, 2017

Thanks @spevans!

@ddunbar
Copy link
Member

ddunbar commented Jun 7, 2017

@swift-ci create

@ankitspd
Copy link
Member

SwiftPM will link stdlib statically by default on macOS after #1246

@swift-ci
Copy link
Contributor Author

swift-ci commented Jul 3, 2018

Comment by Frank Langel (JIRA)

Awesome endeavor. With this feature, Swift will adopt the killer feature that made GOlang so successful, the deployment of executables as ONE file and will strengthen its ability as a server side language.

There hasn't been much progress in a while. Any ETA?

@swift-ci
Copy link
Contributor Author

Comment by Nader Rahimizad (JIRA)

This would be a fantastic feature. Any ETA?

@swift-ci
Copy link
Contributor Author

Comment by Alexis Gallagher (JIRA)

Also, are there any resources or links, besides Simon Evans’s comments in this thread in 2017, which describe what work would be needed to complete this?

Just to provide a bit of context, every few months I need to write a command line tool for colleagues who are not developers. I get excited and think “maybe I should use Swift!” Then I think of the deployment downsides, and I end up writing it in python 2.7, restricting myself to python standard libraries, and it makes me sad.

It would change everything if Swift let you just ship a single executable, which would work and keep working on a foreign system. I believe rust and go can do this, fwiw.

@ddunbar
Copy link
Member

ddunbar commented Sep 23, 2018

We actually do have fully static executables working on macOS with SwiftPM, just not on Linux.

IIUC, the difficulty on Linux comes to dealing with the other dependencies Swift and in particular Foundation bring in (libcurl, libatomic, libicu). I don't really have the context on which of these are hard to deal with, and which are not. I don't know why we can't just try and get static versions of each of the libraries built in, for example.

It would be awesome if someone who understands the issue could at least comment on the current status. @spevans are you able to describe where we are currently?

@swift-ci
Copy link
Contributor Author

Comment by Alexis Gallagher (JIRA)

Static executables are already working on macOS? That's great!

So it seems like, if I am only shipping my command line executables to colleagues on Macs, then I can already use Swift as long as I rely on pure Swift code, Foundation (and presumably other macOS Frameworks), and Swift packages with a similar dependency profile. (I suppose it would need special handling of an external Swift package itself relied on a C library, but was not already configured to build it for static linking.)

I'll wait for news on what needs doing for Linux. If there's some grunt work I can help with, I'd like to, but I'm no expert on linking.

@spevans
Copy link

spevans commented Sep 24, 2018

The issue with libicu on Linux is that it is built by Ubuntu with some parts compiled as a .so file so can only be used in a dynamic executable. The best solution would be to always build libicu as part of the Swift toolchain build. This would also allow building the latest version of ICU (or even Apple's fork) which would solve numerous other ICU issues on Linux.

Foundation on Linux has the problem that libcurl relies on about 25 other libraries and some of these are only supplied as .so files. The solution here would be to build a version of libcurl as part of the swift-corelibs-foundation build that disables much of the extra unused functionality. This will then allow creating a `lib curl.a` file.

@ddunbar
Copy link
Member

ddunbar commented Sep 24, 2018

alexis@alexisgallagher.com (JIRA User) yup! --static-swift-stdlib to SwiftPM.

@spevans makes sense, thanks for the information. While those seem cumbersome and painstaking, they don't seem insurmountable I think we just need to find someone willing to do the work.

I would be happy to help review/mentor this project, for any future readers of this bug.

@spevans
Copy link

spevans commented Sep 24, 2018

@ddunbar For the ICU part, it just requires agreement from Apple/core team to go ahead with building it as part of the toolchain, creating the repo and then deciding which version to use. I can update the ICU work I did for building the library to solve that part.

@ankitspd
Copy link
Member

@spevans We should probably get a thread going on forums for including ICU in the toolchain process.

Also, I remember there was some talk of separating URLSession from Foundation to isolate the libcurl dependency. /cc @parkera @weissi

@parkera
Copy link
Member

parkera commented Sep 24, 2018

@swift-ci
Copy link
Contributor Author

Comment by Alexis Gallagher (JIRA)

I would be happy to help review/mentor this project, for any future readers of this bug.

Just to follow up on your note @ddunbar, I wanted to ask, is there anything that I myself could do that would help move this long? Based on Simon's and Ankit's comment above, it sounds as if the next steps are at least as much procedural as technical:

1. Apple/core team agrees to include a clone or fork of ICU, and build it as part of building Swift.

2. Similarly, Apple/core team agrees to include a clone or fork of a stripped-down version of libcurl, which contains only what is needed to support Foundation's networking requirements on Linux.

So as regards item 2, there's probably some technical work to figure out how to build the stripped down libcurl on Ubuntu that would meet Foundation's needs. With a bit of help, I could probably figure that out, and would be glad to do so.

But as regards the procedural work, who is the right person to explain and plan for these changes in how Swift is built? I doubt it's me, since it seems like a core team issue. Or is this a feature that realistically is at a stage where it first needs to be "pitched" for, because many folks won't think that the benefit (easily deployable executables for language users) is worth the cost (a more complicated language build system)?

@krzyzanowskim
Copy link
Contributor

@ddunbar We actually do have fully static executables working on macOS with SwiftPM, just not on Linux

we... don't as of Swift 5
It looks to me that static linking doesn't work on Linux nor macOS any longer. According to SR-9946 "Swift on macOS isn't going to support static linking at all", and static linking is disabled for Linux in SPM.

It's painful especially on Linux though.

@swift-ci
Copy link
Contributor Author

Comment by Gilles Magalhaes (JIRA)

Would it make sense to disable the command line `--static-swift-stdlib` option in the `swift build` command for the time being? Statically linking binaries doesn't work right now on Linux. On macOS, it also doesn't make sense to have that option, since statically linking binaries is not possible anymore (if I understand correctly).

I think it's confusing for Linux users that calling `swift build` with the `--static-swift-stdlib` option doesn't actually produce the desired result and does not produce a warning like on macOS. If disabling that option is not favourable, I would propose that we at least add a warning.

As a side note, what would it take to get statically linked binaries working on Linux? I would be interested in working on this issue if someone could mentor me.

@swift-ci
Copy link
Contributor Author

Comment by Mickaël Rémond (JIRA)

I agree it would be best to disable the option if it does not work.
That said, being able to distribute stand-alone CLI tools would still be pretty handy on Linux.

@fabianfett
Copy link
Member

Hi, just wanted to mention that I've just been able to produce a binary with statically linked stdlibs with the latest 5.3 nightly docker image.

docker run --rm -v $(pwd):/src -w /src swiftlang/swift:nightly-5.3-bionic swift build --enable-test-discovery --product MyProduct -c release -Xswiftc -static-stdlib

In other words: Using -Xswiftc -static-stdlib instead of --static-swift-stdlib provides the wanted functionality. Many thanks to @drexin for making this possible.

apple/swift#33678

@keith
Copy link
Collaborator

keith commented Sep 11, 2020

I've submitted #2921 which enables --static-swift-stdlib with SwiftPM

@norio-nomura
Copy link
Contributor

I tried swift build --configuration release --static-swift-stdlib to build sourcekitten on swift-5.3.1-RELEASE, but it failed with a link error like:

/usr/lib/swift_static/linux/libFoundation.a(Bridging.swift.o):Bridging.swift.o:function $s10Foundation12__SwiftValueC5fetch11nonOptionalypyXl_tFZ: error: undefined reference to 'kCFBooleanTrue'

full build log

After investigation, the link error was avoided with the following changes:

  • Add apt-get update && apt-get install -y libxml2-dev

  • Use -Xswiftc -static-stdlib instead of --static-swift-stdlib

@spevans
Copy link

spevans commented Nov 13, 2020

I think -static-stdlib is still broken for some uses of FoundationNetworking especially methods that are in Foundation but call into FoundationNetworking eg String(contentsOf..) where the url is an http one, although it should be noted this is a swift-corelibs-foundation issue, not a swiftpm bug.

@norio-nomura
Copy link
Contributor

* Use -Xswiftc -static-stdlib instead of --static-swift-stdlib

Since #3048 has been merged, --static-swift-stdlib option now works properly on swift-DEVELOPMENT-SNAPSHOT-2020-11-16-a.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests