Skip to content

[WIP][SR-648] Add option to create statically linked binaries #4754

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ def no_static_stdlib: Flag<["-"], "no-static-stdlib">,
Flags<[HelpHidden]>,
HelpText<"Don't statically link the Swift standard library">;

def static_executable : Flag<["-"], "static-executable">,
HelpText<"Statically link the executable">;
def no_static_executable : Flag<["-"], "no-static-executable">,
Flags<[HelpHidden]>,
HelpText<"Don't statically link the executable">;

def use_ld : Joined<["-"], "use-ld=">,
Flags<[DoesNotAffectIncrementalBuild]>,
HelpText<"Specifies the linker to be used">;
Expand Down
41 changes: 38 additions & 3 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,12 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
assert(context.Output.getPrimaryOutputType() == types::TY_Image &&
"Invalid linker output type.");

if (context.Args.hasFlag(options::OPT_static_executable,
options::OPT_no_static_executable,
false)) {
llvm::report_fatal_error("-static-executable is not supported on Darwin");
}

const Driver &D = getDriver();
const llvm::Triple &Triple = getTriple();

Expand Down Expand Up @@ -1353,9 +1359,38 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,

// Link the standard library.
Arguments.push_back("-L");
if (context.Args.hasFlag(options::OPT_static_stdlib,
options::OPT_no_static_stdlib,
false)) {
if (context.Args.hasFlag(options::OPT_static_executable,
options::OPT_no_static_executable,
false)) {
SmallString<128> StaticRuntimeLibPath;
getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);
Arguments.push_back(context.Args.MakeArgString(StaticRuntimeLibPath));

SmallString<128> StaticStubObjectPath = StaticRuntimeLibPath;
llvm::sys::path::append(StaticStubObjectPath, "static_stub.o");
auto ObjectPath = StaticStubObjectPath.str();

if (llvm::sys::fs::is_regular_file(ObjectPath)) {
// FIXME: It would be better if these were extracted from static_stub.o
// using `swift-autolink-extract'
Arguments.push_back(context.Args.MakeArgString(ObjectPath));
Arguments.push_back("-static");
Arguments.push_back("-Xlinker");
Arguments.push_back("--defsym=__swift2_protocol_conformances_start=.swift2_protocol_conformances_start");
Arguments.push_back("-Xlinker");
Arguments.push_back("--defsym=__swift2_type_metadata_start=.swift2_type_metadata_start");
Arguments.push_back("-lswiftCore");
Arguments.push_back("-licui18n");
Arguments.push_back("-licuuc");
Arguments.push_back("-licudata");
Arguments.push_back("-lpthread");
} else {
llvm::report_fatal_error("-static-executable not supported on this platform");
}
}
else if (context.Args.hasFlag(options::OPT_static_stdlib,
options::OPT_no_static_stdlib,
false)) {
SmallString<128> StaticRuntimeLibPath;
getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);
Arguments.push_back(context.Args.MakeArgString(StaticRuntimeLibPath));
Expand Down
14 changes: 14 additions & 0 deletions stdlib/public/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ set(swift_runtime_sources
ProtocolConformance.cpp
ReflectionNative.cpp
RuntimeEntrySymbols.cpp
SectionData.cpp
SwiftObjectNative.cpp)

# Acknowledge that the following sources are known.
Expand All @@ -64,6 +65,7 @@ set(LLVM_OPTIONAL_SOURCES
MutexPThread.cpp
MutexWin32.cpp
CygwinPort.cpp
static_stub.c
${swift_runtime_sources}
${swift_runtime_objc_sources}
${swift_runtime_leaks_sources})
Expand Down Expand Up @@ -130,3 +132,15 @@ foreach(sdk ${ELFISH_SDKS})
endforeach()

add_custom_target(section_magic ALL DEPENDS ${object_target_list})

if(SWIFT_BUILD_STATIC_STDLIB)
foreach(sdk ${SWIFT_SDKS})
if("${sdk}" STREQUAL "LINUX")
add_library(static_stub OBJECT static_stub.c)
swift_install_in_component(stdlib
FILES "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/static_stub.dir/static_stub.c${CMAKE_C_OUTPUT_EXTENSION}"
RENAME "static_stub.o"
DESTINATION "lib/swift_static/linux")
endif()
endforeach()
endif()
76 changes: 17 additions & 59 deletions stdlib/public/runtime/MetadataLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,8 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringExtras.h"
#include "Private.h"
#include "SectionData.h"

#if defined(__APPLE__) && defined(__MACH__)
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
#elif defined(__ELF__) || defined(__ANDROID__)
#include <elf.h>
#include <link.h>
#endif

using namespace swift;
using namespace Demangle;
Expand All @@ -43,14 +37,6 @@ using namespace Demangle;
#include <objc/objc.h>
#endif

#if defined(__APPLE__) && defined(__MACH__)
#define SWIFT_TYPE_METADATA_SECTION "__swift2_types"
#elif defined(__ELF__)
#define SWIFT_TYPE_METADATA_SECTION ".swift2_type_metadata_start"
#elif defined(__CYGWIN__) || defined(_MSC_VER)
#define SWIFT_TYPE_METADATA_SECTION ".sw2tymd"
#endif

// Type Metadata Cache.

namespace {
Expand Down Expand Up @@ -89,17 +75,22 @@ namespace {
};
}

#if defined(__APPLE__) && defined(__MACH__)
static void _initializeCallbacksToInspectDylib();
#else
namespace swift {
void _swift_initializeCallbacksToInspectDylib(
void (*fnAddImageBlock)(const uint8_t *, size_t),
const char *sectionName);
}

static void _addImageTypeMetadataRecordsBlock(const uint8_t *records,
size_t recordsSize);

static InspectArgs metadataSectionArgs = {
_addImageTypeMetadataRecordsBlock,
SWIFT_TYPE_METADATA_SECTION,
#if defined(SUPPORTS_STATIC_BINARIES)
&__swift2_type_metadata_start
#endif
};

#if defined(__APPLE__) && defined(__MACH__)
static void
_addImageTypeMetadataRecords(const mach_header *mh, intptr_t vmaddr_slide) {
_swift_readSectionData(mh, &metadataSectionArgs);
}
#endif

struct TypeMetadataState {
Expand All @@ -110,14 +101,11 @@ struct TypeMetadataState {
TypeMetadataState() {
SectionsToScan.reserve(16);
#if defined(__APPLE__) && defined(__MACH__)
_initializeCallbacksToInspectDylib();
_swift_initializeCallbacksForSectionData(_addImageTypeMetadataRecords);
#else
_swift_initializeCallbacksToInspectDylib(
_addImageTypeMetadataRecordsBlock,
SWIFT_TYPE_METADATA_SECTION);
_swift_initializeCallbacksForSectionData(&metadataSectionArgs);
#endif
}

};

static Lazy<TypeMetadataState> TypeMetadataRecords;
Expand Down Expand Up @@ -147,36 +135,6 @@ static void _addImageTypeMetadataRecordsBlock(const uint8_t *records,
recordsBegin, recordsEnd);
}

#if defined(__APPLE__) && defined(__MACH__)
static void _addImageTypeMetadataRecords(const mach_header *mh,
intptr_t vmaddr_slide) {
#ifdef __LP64__
using mach_header_platform = mach_header_64;
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
#else
using mach_header_platform = mach_header;
#endif

// Look for a __swift2_types section.
unsigned long recordsSize;
const uint8_t *records =
getsectiondata(reinterpret_cast<const mach_header_platform *>(mh),
SEG_TEXT, SWIFT_TYPE_METADATA_SECTION,
&recordsSize);

if (!records)
return;

_addImageTypeMetadataRecordsBlock(records, recordsSize);
}

static void _initializeCallbacksToInspectDylib() {
// Install our dyld callback.
// Dyld will invoke this on our behalf for all images that have already
// been loaded.
_dyld_register_func_for_add_image(_addImageTypeMetadataRecords);
}
#endif

void
swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
Expand Down
Loading