Skip to content

[static][stdlib] Any ELF platform can build static binaries. #32736

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions cmake/modules/FindICU.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ foreach(MODULE ${ICU_FIND_COMPONENTS})
HINTS ${PC_ICU_${MODULE}_INCLUDE_DIRS})
find_library(ICU_${MODULE}_LIBRARIES NAMES icu${module} ${ICU_${MODULE}_LIB_NAME}
HINTS ${PC_ICU_${MODULE}_LIBRARY_DIRS})
find_library(ICU_${MODULE}_LIBRARIES_STATIC NAMES libicu${module}.a ${ICU_${MODULE}_LIB_NAME}
HINTS ${PC_ICU_${MODULE}_LIBRARY_DIRS})
endforeach()

foreach(sdk ANDROID;FREEBSD;OPENBSD;LINUX;WINDOWS;HAIKU)
Expand All @@ -33,6 +35,9 @@ foreach(sdk ANDROID;FREEBSD;OPENBSD;LINUX;WINDOWS;HAIKU)
if("${SWIFT_${sdk}_${SWIFT_HOST_VARIANT_ARCH}_ICU_${MODULE}}" STREQUAL "")
set(SWIFT_${sdk}_${SWIFT_HOST_VARIANT_ARCH}_ICU_${MODULE} ${ICU_${MODULE}_LIBRARIES} CACHE STRING "" FORCE)
endif()
if("${SWIFT_${sdk}_${SWIFT_HOST_VARIANT_ARCH}_ICU_${MODULE}_STATIC}" STREQUAL "")
set(SWIFT_${sdk}_${SWIFT_HOST_VARIANT_ARCH}_ICU_${MODULE}_STATIC ${ICU_${MODULE}_LIBRARIES_STATIC} CACHE STRING "" FORCE)
endif()
endforeach()
endforeach()

Expand Down
2 changes: 2 additions & 0 deletions cmake/modules/SwiftConfigureSDK.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ function(_report_sdk prefix)
foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES})
message(STATUS " ${arch} ICU i18n INCLUDE: ${SWIFT_${prefix}_${arch}_ICU_I18N_INCLUDE}")
message(STATUS " ${arch} ICU i18n LIB: ${SWIFT_${prefix}_${arch}_ICU_I18N}")
message(STATUS " ${arch} ICU i18n static LIB: ${SWIFT_${prefix}_${arch}_ICU_I18N_STATIC}")
message(STATUS " ${arch} ICU unicode INCLUDE: ${SWIFT_${prefix}_${arch}_ICU_UC_INCLUDE}")
message(STATUS " ${arch} ICU unicode LIB: ${SWIFT_${prefix}_${arch}_ICU_UC}")
message(STATUS " ${arch} ICU unicode static LIB: ${SWIFT_${prefix}_${arch}_ICU_UC_STATIC}")
endforeach()
endif()
endif()
Expand Down
71 changes: 38 additions & 33 deletions stdlib/public/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,26 @@ set(swift_runtime_library_compile_flags ${swift_runtime_compile_flags})
list(APPEND swift_runtime_library_compile_flags -DswiftCore_EXPORTS)
list(APPEND swift_runtime_library_compile_flags -I${SWIFT_SOURCE_DIR}/stdlib/include/llvm/Support -I${SWIFT_SOURCE_DIR}/include)

set(sdk "${SWIFT_HOST_VARIANT_SDK}")
if(SWIFT_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH}_ICU_STATICLIB)
set(libicu_i18n_a -licui18nswift)
set(libicu_uc_a -licuucswift)
set(libicu_data_a -licudataswift)
else()
find_package(ICU REQUIRED COMPONENTS uc i18n data)
set(libicu_i18n_a ${SWIFT_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH}_ICU_I18N_STATIC})
set(libicu_uc_a ${SWIFT_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH}_ICU_UC_STATIC})
set(libicu_data_a ${SWIFT_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH}_ICU_DATA_STATIC})
endif()

# TODO: Put the logic for finding libdl in a module, similar to ICU.
set(libdl)
if(SWIFT_BUILD_STATIC_STDLIB AND "${sdk}" STREQUAL "LINUX")
set(libdl -ldl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh; I really wish that we could use CMAKE_DL_LIBS, unfortunately, the custom cross-compilation build system in Swift doesn't support that. We already have the special handling for dl in _add_target_variant_link_flags, can we re-use that rather than duplicate knowledge of libdl here? Alternatively, perhaps we should consider creating a SWIFT_DL_LIBS_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH} variable to indicate if/when libdl is needed on a platform?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one's a little more complex, since it appears (to me) that _add_target_variant_link_flags works with a CMake target, and maybe there's a way to create a dummy target and pull the link libraries. The latter is probably simpler, but I'll probably need to spin up a Linux build to do this properly.

Added a TODO and I'll take a look at this in a later PR. Does that sound reasonable?

endif()


set(sdk "${SWIFT_HOST_VARIANT_SDK}")
if(SWIFT_BUILD_STATIC_STDLIB AND ${SWIFT_SDK_${sdk}_OBJECT_FORMAT} STREQUAL ELF)
list(REMOVE_ITEM swift_runtime_sources ImageInspectionELF.cpp)
set(static_binary_lnk_file_list)
string(TOLOWER "${sdk}" lowercase_sdk)
Expand Down Expand Up @@ -121,22 +139,30 @@ if(SWIFT_BUILD_STATIC_STDLIB AND "${sdk}" STREQUAL "LINUX")

# Generate the static-executable-args.lnk file used for ELF systems (eg linux)
set(linkfile "${lowercase_sdk}/static-executable-args.lnk")
add_custom_command_target(swift_static_binary_${sdk}_args
COMMAND
"${CMAKE_COMMAND}" -E copy
"${SWIFT_SOURCE_DIR}/utils/static-executable-args.lnk"
"${SWIFTSTATICLIB_DIR}/${linkfile}"
OUTPUT
"${SWIFTSTATICLIB_DIR}/${linkfile}"
DEPENDS
"${SWIFT_SOURCE_DIR}/utils/static-executable-args.lnk")
file(WRITE "${SWIFTSTATICLIB_DIR}/${linkfile}" "
-static
-lswiftCore
-lswiftImageInspectionShared
-Xlinker
--defsym=__import_pthread_self=pthread_self
-Xlinker
--defsym=__import_pthread_once=pthread_once
-Xlinker
--defsym=__import_pthread_key_create=pthread_key_create
-lpthread
${libicu_i18n_a}
${libicu_uc_a}
${libicu_data_a}
${libdl}
-lstdc++
-lm")

list(APPEND static_binary_lnk_file_list ${swift_static_binary_${sdk}_args})
swift_install_in_component(FILES "${SWIFTSTATICLIB_DIR}/${linkfile}"
DESTINATION "lib/swift_static/${lowercase_sdk}"
COMPONENT stdlib)
add_custom_target(static_binary_magic ALL DEPENDS ${static_binary_lnk_file_list})
foreach(arch IN LISTS SWIFT_SDK_LINUX_ARCHITECTURES)
foreach(arch IN LISTS SWIFT_SDK_${sdk}_ARCHITECTURES)
add_dependencies(static_binary_magic ${swift_image_inspection_${arch}_static})
endforeach()
add_dependencies(static_binary_magic ${swift_image_inspection_static_primary_arch})
Expand Down Expand Up @@ -254,30 +280,9 @@ foreach(sdk ${SWIFT_CONFIGURED_SDKS})
# 'GenericUnix' (eg linux)
if(${SWIFT_SDK_${sdk}_OBJECT_FORMAT} STREQUAL ELF)
string(TOLOWER "${sdk}" lowercase_sdk)
if(SWIFT_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH}_ICU_STATICLIB)
set(libicu_i18n_a -licui18nswift)
set(libicu_uc_a -licuucswift)
set(libicu_data_a -licudataswift)
else()
find_package(ICU REQUIRED COMPONENTS uc i18n)
get_filename_component(ICU_UC_LIBDIR "${ICU_UC_LIBRARIES}" DIRECTORY)
get_filename_component(ICU_I18N_LIBDIR "${ICU_I18N_LIBRARIES}" DIRECTORY)

set(libicu_i18n_a -licui18n)
set(libicu_uc_a -licuuc)
set(libicu_data_a)
if(EXISTS ${ICU_I18N_LIBDIR}/libicui18n.a AND
EXISTS ${ICU_UC_LIBDIR}/libicuuc.a AND
EXISTS ${ICU_UC_LIBDIR}/libicudata.a)
set(libicu_i18n_a ${ICU_I18N_LIBDIR}/libicui18n.a)
set(libicu_uc_a ${ICU_UC_LIBDIR}/libicuuc.a)
set(libicu_data_a ${ICU_UC_LIBDIR}/libicudata.a)
endif()
endif()

set(linkfile ${lowercase_sdk}/static-stdlib-args.lnk)
file(WRITE "${SWIFTSTATICLIB_DIR}/${linkfile}" "
-ldl
${libdl}
-lpthread
-lswiftCore
-lswiftImageInspectionShared
Expand Down
1 change: 1 addition & 0 deletions test/Driver/static-executable.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Create a self contained binary
// REQUIRES: OS=linux-gnu
// REQUIRES: static_stdlib
// XFAIL: OS=openbsd
print("hello world!")
// RUN: %empty-directory(%t)
// RUN: %target-swiftc_driver -static-executable -o %t/static-executable %s
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Statically link a "hello world" program
// REQUIRES: OS=linux-gnu
// REQUIRES: OS=linux-gnu || OS=openbsd
// REQUIRES: static_stdlib
print("hello world!")
// RUN: %empty-directory(%t)
Expand Down
2 changes: 2 additions & 0 deletions test/Frontend/crash-in-user-code.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// See SR-13165
// UNSUPPORTED: static_stdlib
Copy link
Contributor

@gribozavr gribozavr Jul 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not obvious, could you add a comment explaining why it is not supported? (Here and in every other test, please.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Since the explanation is somewhat wordy, I've created a Jira bug for the UNSUPPORTED annotations and referenced to the bug.

Do you think the (unrelated) XFAIL elsewhere needs a comment as well?


// RUN: echo %s > %t.filelist.txt
// RUN: not --crash %target-swift-frontend -interpret -filelist %t.filelist.txt 2>&1 | %FileCheck %s
Expand Down
2 changes: 2 additions & 0 deletions test/Interpreter/enforce_exclusive_access.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// See SR-13165
// UNSUPPORTED: static_stdlib
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -swift-version 4 %s -o %t/a.out -enforce-exclusivity=checked -Onone
//
Expand Down
2 changes: 2 additions & 0 deletions test/Runtime/backtrace.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// See SR-13165
// UNSUPPORTED: static_stdlib
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -o %t/a.out
// RUN: %{python} %S/../Inputs/not.py "%target-run %t/a.out" 2>&1 | %{python} %utils/backtrace-check
Expand Down
3 changes: 2 additions & 1 deletion unittests/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND
endif()

set(swift_runtime_test_extra_libraries)
if(SWIFT_BUILD_STATIC_STDLIB AND "${SWIFT_HOST_VARIANT_SDK}" STREQUAL "LINUX")
if(SWIFT_BUILD_STATIC_STDLIB AND
${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_OBJECT_FORMAT} STREQUAL ELF)
list(APPEND swift_runtime_test_extra_libraries
$<TARGET_FILE:swiftImageInspectionShared-${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}-${SWIFT_HOST_VARIANT_ARCH}>)
endif()
Expand Down
16 changes: 0 additions & 16 deletions utils/static-executable-args.lnk

This file was deleted.