Skip to content

Commit 5dc6f21

Browse files
committed
separate out Swift package resolution from build tasks
Separate out Swift package resolutions into a new do_swift_package_resolve() task. Ensure the ambient SSH_AUTH_SOCK is available to this task in order to support resolution of package dependencies in private repositories. Rewrite do_compile() task in Python, adding support for building Swift tests.
1 parent e0a3df9 commit 5dc6f21

File tree

1 file changed

+114
-9
lines changed

1 file changed

+114
-9
lines changed

classes/swift.bbclass

Lines changed: 114 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,21 @@ B ?= "${S}/.build"
1212
EXTERNALSRC_BUILD ?= "${EXTERNALSRC}/.build"
1313

1414
BUILD_MODE = "${@['release', 'debug'][d.getVar('DEBUG_BUILD') == '1']}"
15+
BUILD_DIR = "${B}/${BUILD_MODE}"
1516

1617
# Additional parameters to pass to SPM
1718
EXTRA_OESWIFT ?= ""
1819

1920
SWIFT_TARGET_NAME = "${@oe.utils.conditional('TARGET_ARCH', 'arm', 'armv7-unknown-linux-gnueabihf', 'aarch64-unknown-linux-gnu', d)}"
21+
SWIFT_TARGET_ARCH = "${@oe.utils.conditional('TARGET_ARCH', 'arm', 'armv7', 'aarch64', d)}"
22+
23+
do_fix_gcc_install_dir() {
24+
# symbolic links do not work, will not be found by Swift clang driver
25+
# this is necessary to make the libstdc++ location heuristic work, necessary for C++ interop
26+
(cd ${STAGING_DIR_TARGET}/usr/lib && rm -rf gcc && mkdir -p gcc && cp -rp ${SWIFT_TARGET_ARCH}-oe-linux gcc)
27+
}
28+
29+
addtask fix_gcc_install_dir before do_configure after do_prepare_recipe_sysroot
2030

2131
# Workaround complex macros that cannot be automatically imported by Swift.
2232
# https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_macros_in_swift
@@ -41,6 +51,37 @@ def fix_socket_header(filename):
4151
else:
4252
f.write(line)
4353

54+
# Support for SwiftPM fetching packages and their GitHub submodules
55+
do_swift_package_resolve[depends] += "unzip-native:do_populate_sysroot swift-native:do_populate_sysroot"
56+
do_swift_package_resolve[network] = "1"
57+
do_swift_package_resolve[vardepsexclude] = "BB_ORIGENV"
58+
59+
python do_swift_package_resolve() {
60+
import subprocess
61+
import os
62+
63+
s = d.getVar('S')
64+
b = d.getVar('B')
65+
66+
env = os.environ.copy()
67+
68+
ssh_auth_sock = d.getVar('BB_ORIGENV').get('SSH_AUTH_SOCK')
69+
if ssh_auth_sock:
70+
env['SSH_AUTH_SOCK'] = ssh_auth_sock
71+
72+
ret = subprocess.call(['swift', 'package', 'resolve', '--package-path', s, '--build-path', b], env=env)
73+
if ret != 0:
74+
bb.fatal('swift package resolve failed')
75+
76+
# note: --depth 1 requires git version 2.43.0 or later
77+
for package in os.listdir(path=f'{b}/checkouts'):
78+
package_dir = f'{b}/checkouts/{package}'
79+
ret = subprocess.call(['git', 'submodule', 'update', '--init', '--recursive', '--depth', '1'], cwd=package_dir, env=env)
80+
if ret != 0:
81+
bb.fatal('git submodule update failed')
82+
}
83+
84+
addtask swift_package_resolve after do_unpack before do_compile
4485

4586
python swift_do_configure() {
4687
import os
@@ -62,6 +103,8 @@ python swift_do_configure() {
62103
# This is used to determine necessary include paths
63104
cxx_include_base = recipe_sysroot + "/usr/include/c++"
64105
cxx_include_list = os.listdir(cxx_include_base)
106+
if 'current' in cxx_include_list:
107+
cxx_include_list.remove('current')
65108
if len(cxx_include_list) != 1:
66109
bb.fatal("swift bbclass detected more than one c++ runtime, unable to determine which one to use")
67110
cxx_version = cxx_include_list[0]
@@ -71,22 +114,26 @@ python swift_do_configure() {
71114
swift_destination_template = """{
72115
"version":1,
73116
"sdk":"${STAGING_DIR_TARGET}/",
74-
"toolchain-bin-dir":"${STAGING_DIR_NATIVE}/opt/usr/bin",
117+
"toolchain-bin-dir":"${STAGING_DIR_NATIVE}/usr/bin",
75118
"target":"${SWIFT_TARGET_NAME}",
76119
"dynamic-library-extension":"so",
77120
"extra-cc-flags":[
78121
"-fPIC",
122+
"-I${STAGING_INCDIR}",
79123
"-I${STAGING_DIR_TARGET}/usr/include/c++/${SWIFT_CXX_VERSION}",
80124
"-I${STAGING_DIR_TARGET}/usr/include/c++/${SWIFT_CXX_VERSION}/${TARGET_SYS}",
81-
"-I${STAGING_DIR_NATIVE}/opt/usr/lib/clang/13.0.0/include",
82-
"-I${STAGING_DIR_NATIVE}/opt/usr/lib/clang/13.0.0/include-fixed"
125+
"-I${STAGING_DIR_NATIVE}/usr/lib/clang/17/include",
126+
"-I${STAGING_DIR_NATIVE}/usr/lib/clang/17/include-fixed"
83127
],
84128
"extra-swiftc-flags":[
85129
"-target",
86130
"${SWIFT_TARGET_NAME}",
87131
"-use-ld=lld",
88132
"-tools-directory",
89-
"${STAGING_DIR_NATIVE}/opt/usr/bin",
133+
"${STAGING_DIR_NATIVE}/usr/bin",
134+
135+
"-enforce-exclusivity=unchecked",
136+
"-enforce-exclusivity=none",
90137
91138
"-Xlinker", "-rpath", "-Xlinker", "/usr/lib/swift/linux",
92139
@@ -111,14 +158,16 @@ python swift_do_configure() {
111158
"-I${STAGING_INCDIR}",
112159
"-I${STAGING_DIR_TARGET}/usr/include/c++/${SWIFT_CXX_VERSION}",
113160
"-I${STAGING_DIR_TARGET}/usr/include/c++/${SWIFT_CXX_VERSION}/${TARGET_SYS}",
114-
"-I${STAGING_DIR_NATIVE}/opt/usr/lib/clang/13.0.0/include",
115-
"-I${STAGING_DIR_NATIVE}/opt/usr/lib/clang/13.0.0/include-fixed",
161+
"-I${STAGING_DIR_NATIVE}/usr/lib/clang/17/include",
162+
"-I${STAGING_DIR_NATIVE}/usr/lib/clang/17/include-fixed",
116163
117164
"-resource-dir", "${STAGING_DIR_TARGET}/usr/lib/swift",
118165
"-module-cache-path", "${B}/${BUILD_MODE}/ModuleCache",
119166
"-Xclang-linker", "-B${STAGING_DIR_TARGET}/usr/lib/${TARGET_SYS}/${SWIFT_CXX_VERSION}",
120167
"-Xclang-linker", "-B${STAGING_DIR_TARGET}/usr/lib",
121168
169+
"-Xcc", "--gcc-install-dir=${STAGING_DIR_TARGET}/usr/lib/gcc/${TARGET_SYS}/${SWIFT_CXX_VERSION}",
170+
122171
"-sdk", "${STAGING_DIR_TARGET}"
123172
],
124173
"extra-cpp-flags":[
@@ -135,10 +184,66 @@ python swift_do_configure() {
135184
configJSON.close()
136185
}
137186

138-
swift_do_compile() {
139-
swift build --package-path ${S} --build-path ${B} --skip-update -c ${BUILD_MODE} --destination ${WORKDIR}/destination.json ${EXTRA_OESWIFT}
187+
# ideally this should be handled by do_swift_package_resolve but doesn't always appear to be the case
188+
do_compile[network] = "1"
189+
swift_do_compile[vardepsexclude] = "BB_ORIGENV"
190+
191+
python swift_do_compile() {
192+
import subprocess
193+
import os
194+
import shlex
195+
196+
s = d.getVar('S')
197+
b = d.getVar('B')
198+
build_mode = d.getVar('BUILD_MODE')
199+
workdir = d.getVar("WORKDIR", True)
200+
destination_json = workdir + '/destination.json'
201+
extra_oeswift = shlex.split(d.getVar('EXTRA_OESWIFT'))
202+
ssh_auth_sock = d.getVar('BB_ORIGENV')['SSH_AUTH_SOCK']
203+
recipe_sysroot = d.getVar("STAGING_DIR_TARGET", True)
204+
205+
env = os.environ.copy()
206+
env['SSH_AUTH_SOCK'] = ssh_auth_sock
207+
env['SYSROOT'] = recipe_sysroot
208+
209+
args = ['swift', 'build', '--package-path', s, '--build-path', b, '-c', build_mode, '--destination', destination_json] + extra_oeswift
210+
211+
ret = subprocess.call(args, env=env, cwd=s)
212+
if ret != 0:
213+
bb.fatal('swift build failed')
214+
215+
if d.getVar('SWIFT_BUILD_TESTS') == '1':
216+
if d.getVar('DEBUG_BUILD') != '1':
217+
bb.warn('building Swift tests with release build, @testable imports may fail')
218+
219+
# FIXME: why do we need to specify -lXCTest and -lTesting explicitly
220+
test_args = ['--build-tests', '-Xlinker', '-lXCTest', '-Xlinker', '-lTesting']
221+
ret = subprocess.call(args + test_args + extra_oeswift, env=env, cwd=s)
222+
if ret != 0:
223+
bb.fatal('swift build --build-tests failed')
224+
}
225+
226+
do_package_update() {
227+
cd ${S}
228+
swift package update
229+
230+
# Iterate over the search dirs for this recipes' files
231+
# The first one that has a Package.resolved is the one bitbake got the file
232+
# from in the first places
233+
RESOLVED_PATH=""
234+
for i in $(echo "${FILESPATH}" | tr ':' '\n'); do
235+
if [ -r "${i}"/Package.resolved ]; then
236+
RESOLVED_PATH="${i}/Package.resolved"
237+
cp Package.resolved "${RESOLVED_PATH}"
238+
bbwarn "Replaced ${RESOLVED_PATH} with updated Package.resolved."
239+
break
240+
fi
241+
done
242+
[ -z "${RESOLVED_PATH}" ] && bbwarn "Updated Package.resolved located at ${S}/Package.resolved" || :
140243
}
244+
do_package_update[network] = "1"
245+
addtask do_package_update after do_configure
141246

142-
EXPORT_FUNCTIONS do_configure do_compile
247+
EXPORT_FUNCTIONS do_configure do_compile do_package_update
143248

144249
EXTRANATIVEPATH += "swift-tools"

0 commit comments

Comments
 (0)