blob: 440ab29a7bfee7d217b865263baef8353161d68b [file] [log] [blame]
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for building Swift toolchain."""
from contextlib import contextmanager
from recipe_engine.config import Enum, ReturnSchema, Single
from recipe_engine.recipe_api import Property
import re
DEPS = [
'infra/cipd',
'infra/git',
'infra/gitiles',
'infra/goma',
'infra/gsutil',
'infra/jiri',
'recipe_engine/context',
'recipe_engine/json',
'recipe_engine/path',
'recipe_engine/platform',
'recipe_engine/properties',
'recipe_engine/python',
'recipe_engine/raw_io',
'recipe_engine/file',
'recipe_engine/step',
'recipe_engine/url',
]
SWIFT_FUCHSIA_GIT = 'https://fuchsia.googlesource.com/third_party/swift'
PROPERTIES = {
'url': Property(kind=str, help='Git repository URL', default=SWIFT_FUCHSIA_GIT),
'ref': Property(kind=str, help='Git reference', default='refs/heads/upstream/fuchsia_release'),
'revision': Property(kind=str, help='Revision', default=None),
'goma_dir': Property(kind=str, help='Path to goma', default=None),
}
MANIFEST_FILE = """lib/libswiftCore.so=libswiftCore.so
lib/libswiftGlibc.so=libswiftGlibc.so
lib/libswiftSwiftOnoneSupport.so=libswiftSwiftOnoneSupport.so
lib/libswiftRemoteMirror.so=libswiftRemoteMirror.so
"""
PRESET_FILE = """
#===------------------------------------------------------------------------===#
# Fuchsia Mixins
#===------------------------------------------------------------------------===#
[preset: mixin_fuchsia_build]
fuchsia
extra-stdlib-deployment-targets=fuchsia-aarch64,fuchsia-x86_64
fuchsia-toolchain-path=%(clang_path)s
fuchsia-icu-uc-include=%(fuchsia_icu_uc)s
fuchsia-icu-i18n-include=%(fuchsia_icu_i18n)s
fuchsia-x86_64-sysroot=%(x86_64_sysroot)s
fuchsia-aarch64-sysroot=%(aarch64_sysroot)s
fuchsia-x86_64-libs=%(x64_shared)s
fuchsia-aarch64-libs=%(arm64_shared)s
host-cc=%(clang_path)s/bin/clang
host-cxx=%(clang_path)s/bin/clang++
use-lld-linker
build-swift-static-stdlib=true
build-runtime-with-host-compiler=true
build-swift-static-sdk-overlay=true
xctest=false
foundation=false
libdispatch=false
libicu=false
build-ninja=false
dash-dash
skip-build-foundation
skip-build-libdispatch
skip-build-xctest
skip-build-swiftpm
skip-build-lldb
skip-build-llbuild
[preset: mixin_fuchsia_release_Os]
mixin-preset=mixin_fuchsia_build
no-swift-stdlib-assertions
no-swift-assertions
no-llvm-assertions
release
dash-dash
swift-stdlib-build-type=MinSizeRel
swift-stdlib-enable-assertions=false
swift-enable-ast-verifier=0
[preset: mixin_fuchsia_release_debuginfo]
mixin-preset=mixin_fuchsia_build
no-swift-stdlib-assertions
release-debuginfo
assertions
dash-dash
swift-stdlib-build-type=RelWithDebInfo
swift-stdlib-enable-assertions=false
swift-enable-ast-verifier=0
# We will re-enable these when tests work
[preset: mixin_fuchsia_disable_testing]
dash-dash
skip-test-cmark
skip-test-lldb
skip-test-swift
skip-test-llbuild
skip-test-swiftpm
skip-test-xctest
skip-test-foundation
skip-test-libdispatch
skip-test-playgroundlogger
skip-test-playgroundsupport
skip-test-libicu
skip-test-fuchsia-host
[preset: mixin_fuchsia_install]
dash-dash
swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;swift-remote-mirror;sdk-overlay;license;editor-integration;tools;dev;sourcekit-inproc
install-swift
install-prefix=/
install-destdir=%(install_destdir)s
install-symroot=%(install_symroot)s
reconfigure
#===------------------------------------------------------------------------===#
# Fuchsia Targets
#===------------------------------------------------------------------------===#
[preset: fuchsia_release]
mixin-preset=
mixin_fuchsia_release_Os
mixin_fuchsia_disable_testing
[preset: fuchsia_release_debuginfo]
mixin-preset=
mixin_fuchsia_release_debuginfo
mixin_fuchsia_disable_testing
[preset: fuchsia_release_install]
mixin-preset=
fuchsia_release
mixin_fuchsia_install
[preset: fuchsia_release_debuginfo_install]
mixin-preset=
fuchsia_release_debuginfo
mixin_fuchsia_install
#===------------------------------------------------------------------------===#
# Linux Extra Targets
#===------------------------------------------------------------------------===#
# We build this after doing a regular build to get the additional depedencies
# for just Linux that don't work on Fuchsia yet.
[preset: linux_extras_install]
no-swift-stdlib-assertions
no-swift-assertions
no-llvm-assertions
host-cc=%(clang_path)s/bin/clang
host-cxx=%(clang_path)s/bin/clang++
use-lld-linker
build-swift-static-stdlib=true
build-runtime-with-host-compiler=true
build-swift-static-sdk-overlay=true
llbuild
swiftpm
xctest
foundation
libdispatch
release
dash-dash
build-ninja
install-swift
install-lldb
install-llbuild
install-swiftpm
install-xctest
install-foundation
install-libdispatch
swift-stdlib-build-type=MinSizeRel
swift-stdlib-enable-assertions=false
swift-enable-ast-verifier=0
skip-test-xctest
skip-test-foundation
skip-test-libdispatch
skip-test-playgroundlogger
skip-test-playgroundsupport
skip-test-libicu
swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;swift-remote-mirror;sdk-overlay;license;editor-integration;tools;dev;sourcekit-inproc;swift-remote-mirror-headers
llvm-install-components=libclang;libclang-headers
install-prefix=/
install-destdir=%(install_destdir)s
install-symroot=%(install_symroot)s
reconfigure
"""
# TODO(zbowling): we need to move all of these repos to checkout the
# Google github or some googlesource.com mirrors.
UPDATE_CHECKOUT_CONFIG = """
{
"https-clone-pattern": "https://fuchsia.googlesource.com/third_party/%s",
"ssh-clone-pattern": "git@github.com:google/%s.git",
"repos": {
"compiler-rt": {
"remote": {
"id": "swift-compiler-rt"
}
},
"llvm": {
"remote": {
"id": "swift-llvm"
}
},
"swift-corelibs-foundation": {
"remote": {
"id": "swift-corelibs-foundation"
}
},
"clang": {
"remote": {
"id": "swift-clang"
}
},
"llbuild": {
"remote": {
"id": "swift-llbuild"
}
},
"cmark": {
"remote": {
"id": "swift-cmark"
}
},
"lldb": {
"remote": {
"id": "swift-lldb"
}
},
"swift-corelibs-xctest": {
"remote": {
"id": "swift-corelibs-xctest"
}
},
"ninja": {
"remote": {
"id": "ninja"
}
},
"swift-integration-tests": {
"remote": {
"id": "swift-integration-tests"
}
},
"swiftpm": {
"remote": {
"id": "swift-package-manager"
}
},
"swift": {
"remote": {
"id": "swift"
}
},
"swift-corelibs-libdispatch": {
"remote": {
"id": "swift-corelibs-libdispatch"
}
}
},
"branch-schemes": {
"fuchsia": {
"repos": {
"compiler-rt": "61fa9e3fd80fb9c2abc71e34b254c1c8b12c9c71",
"llvm": "cf0f1343596c56da3cbf3e98900b0402248d1c61",
"swift-corelibs-foundation": "ad2f29b446c6aba991f250500d2e6f3a8706c6fa",
"clang": "ef223bbbebb24d836334f2712d9ca68ff265269b",
"llbuild": "473365152503f0fce2cde3be7f7dcb9699fdca87",
"cmark": "d875488a6a95d5487b7c675f79a8dafef210a65f",
"lldb": "14981bfc6cb9a482e729d6411b6be1ac5d8a12e4",
"swiftpm": "0297d83f1c991ae7e5e74fa39849b0b70b9f387f",
"swift-corelibs-xctest": "732d9533c70dca9ede2c745b64a11f8c7dc7f824",
"ninja": "253e94c1fa511704baeb61cf69995bbf09ba435e",
"swift-integration-tests": "01eecd5a83279635823e78101a538132784bc628",
"swift": "6058ffab78270a048e27047292becc847fbc0184",
"swift-corelibs-libdispatch": "e52c174b1f1883eebad6ba7bdd54edbd4736617e"
},
"aliases": [
"fuchsia"
]
}
}
}
"""
# TODO(zbowling): We are building packages for all of garnet. This is overkill.
def BuildFuchsia(api, target_cpu, zircon_project, fuchsia_out_dir):
fuchsia_build_dir = fuchsia_out_dir.join('release-%s' % target_cpu)
with api.step.nest('build fuchsia ' + target_cpu):
gen_cmd = [
api.path['start_dir'].join('build', 'gn', 'gen.py'),
'--target_cpu=%s' % target_cpu,
'--packages=garnet/packages/default',
'--platforms=%s' % zircon_project,
]
gen_cmd.append('--goma=%s' % api.goma.goma_dir)
# Build Fuchsia for release.
# In theory, we shouldn't be statically linking anything from Fuchsia.
gen_cmd.append('--release')
api.step('gen fuchsia', gen_cmd)
ninja_cmd = [
api.path['start_dir'].join('buildtools', 'ninja'),
'-C', fuchsia_build_dir,
]
ninja_cmd.extend(['-j', api.goma.recommended_goma_jobs])
api.step('ninja', ninja_cmd)
def RunSteps(api, url, ref, revision, goma_dir):
api.gitiles.ensure_gitiles()
api.gsutil.ensure_gsutil()
api.jiri.ensure_jiri()
if goma_dir:
api.goma.set_goma_dir(goma_dir)
api.goma.ensure_goma()
api.cipd.set_service_account_credentials(
api.cipd.default_bot_service_account_credentials)
if not revision:
revision = api.gitiles.refs(url).get(ref, None)
cipd_pkg_name = 'fuchsia/swift/' + api.cipd.platform_suffix()
step = api.cipd.search(cipd_pkg_name, 'git_revision:' + revision)
if step.json.output['result']:
api.step('Package is up-to-date', cmd=None)
return
swift_source_dir = api.path['start_dir'].join('swift-source')
swift_dir = swift_source_dir.join('swift')
api.file.ensure_directory('swift-source', swift_source_dir)
with api.context(infra_steps=True):
api.jiri.init()
# TODO(zbowling): we are pulling in a garnet manifest now, but eventually
# Swift will be included in the garnet manfiest itself, so we will instead
# to pull manifest that that is just:
# zircon + clang toolchain + third_party/icu.
api.jiri.import_manifest(
'manifest/garnet',
'https://fuchsia.googlesource.com/garnet',
'garnet'
)
api.jiri.update()
api.git.checkout(url, swift_dir, ref=revision)
with api.step.nest('ensure_packages'):
with api.context(infra_steps=True):
cipd_dir = api.path['start_dir'].join('cipd')
api.cipd.ensure(cipd_dir, {
'infra/cmake/${platform}': 'version:3.9.2',
'infra/ninja/${platform}': 'version:1.8.2',
'fuchsia/clang/${platform}': 'latest',
})
# Build zircon for both x86 and arm64
zircon_dir = api.path['start_dir'].join('zircon')
for project in ['x86', 'arm64']:
build_zircon_cmd = [
api.path['start_dir'].join('scripts', 'build-zircon.sh'),
'-H',
'-v',
'-p', project,
]
api.step('build zircon '+ project, build_zircon_cmd)
goma_env = {}
fuchsia_out_dir = api.path['start_dir'].join('out')
with api.goma.build_with_goma():
BuildFuchsia(api, "aarch64", "arm64", fuchsia_out_dir)
BuildFuchsia(api, "x86-64", "x86", fuchsia_out_dir)
# build swift
staging_dir = api.path.mkdtemp('swift')
build_dir = staging_dir.join('build')
swift_install_dir = build_dir.join("swift_toolchain")
swift_symbols = build_dir.join("swift_symbols")
api.file.ensure_directory('build', build_dir)
zircon_dir = api.path['start_dir'].join('out', 'build-zircon')
x86_64_sysroot = zircon_dir.join('build-user-x86-64', 'sysroot')
aarch64_sysroot = zircon_dir.join('build-user-arm64', 'sysroot')
clang_path = api.path['start_dir'].join('buildtools')
fuchia_x64_shared = fuchsia_out_dir.join('release-x86-64','x64-shared')
fuchia_arm64_shared = fuchsia_out_dir.join('release-aarch64','arm64-shared')
presets_file = build_dir.join('presets.ini')
checkout_config = build_dir.join('update-checkout.json')
env_prefixes = {'PATH': [cipd_dir, cipd_dir.join('bin')]}
with api.context(cwd=build_dir, env_prefixes=env_prefixes):
# Update checkout
api.file.write_text('writing checkout config', checkout_config,
UPDATE_CHECKOUT_CONFIG)
api.python(
'checkout swift depedencies',
swift_dir.join('utils', 'update-checkout'),
args=[
'--skip-repository', 'swift', # we manage the swift repo ourselves
'--skip-repository', 'swift-xcode-playground-support', # no mirror
'--config', checkout_config,
'--scheme', 'fuchsia',
'-j5', '--clone',
])
# Build swift for Linux and Fuchsia targets without Linux extras
api.file.write_text('writing build presets', presets_file, PRESET_FILE)
api.python(
'build swift fuchsia components',
swift_dir.join('utils', 'build-script'),
args=[
'--preset-file', presets_file,
'--jobs', api.platform.cpu_count,
'--preset=fuchsia_release_install',
'clang_path=%s' % cipd_dir,
'fuchsia_icu_uc=%s' % api.path['start_dir'].join(
"third_party", "icu", "source", "common"),
'fuchsia_icu_i18n=%s' % api.path['start_dir'].join(
"third_party", "icu", "source", "i18n"),
'x86_64_sysroot=%s' % x86_64_sysroot,
'aarch64_sysroot=%s' % aarch64_sysroot,
'x64_shared=%s' % fuchia_x64_shared,
'arm64_shared=%s' % fuchia_arm64_shared,
'install_destdir=%s' % swift_install_dir,
'install_symroot=%s' % swift_symbols,
])
# HACK: Build swift again but with extras for Linux that do not work on
# on Fuchsia yet (swiftpm, libdispatch, foundation, etc)
api.python(
'build swift linux extras',
swift_dir.join('utils', 'build-script'),
args=[
'--preset-file', presets_file,
'--jobs', api.platform.cpu_count,
'--preset=linux_extras_install',
'clang_path=%s' % cipd_dir,
'fuchsia_icu_uc=%s' % api.path['start_dir'].join(
"third_party", "icu", "source", "common"),
'fuchsia_icu_i18n=%s' % api.path['start_dir'].join(
"third_party", "icu", "source", "i18n"),
'x86_64_sysroot=%s' % x86_64_sysroot,
'aarch64_sysroot=%s' % aarch64_sysroot,
'x64_shared=%s' % fuchia_x64_shared,
'arm64_shared=%s' % fuchia_arm64_shared,
'install_destdir=%s' % swift_install_dir,
'install_symroot=%s' % swift_symbols,
])
# TODO(zbowling): remove this in favor of doing it similar to the way
# clang_path does it below.
swift_install_lib = swift_install_dir.join('lib','swift','fuchsia')
api.file.write_text('writing x86_64 manifest',
swift_install_lib.join("x86_64","toolchain.manifest"), MANIFEST_FILE)
api.file.write_text('writing aarch64 manifest',
swift_install_lib.join("aarch64", "toolchain.manifest"), MANIFEST_FILE)
install_lib = swift_install_dir.join('lib')
api.file.write_text('writing x86_64 manifest',
install_lib.join("x86_64-fuchsia.manifest"), MANIFEST_FILE)
api.file.write_text('writing aarch64 manifest',
install_lib.join("aarch64-fuchsia.manfiest"), MANIFEST_FILE)
cipd_pkg_file = staging_dir.join('swift.cipd')
step_result = api.step(
'swift version', [swift_install_dir.join('bin', 'swift'), '--version'],
stdout=api.raw_io.output())
m = re.search(r'version ([0-9a-z.-]+)', step_result.stdout)
assert m, 'Cannot determine Swift version'
swift_version = m.group(1)
api.cipd.build(
input_dir=swift_install_dir,
package_name=cipd_pkg_name,
output_package=cipd_pkg_file,
install_mode='copy',
)
step_result = api.cipd.register(
package_name=cipd_pkg_name,
package_path=cipd_pkg_file,
refs=['latest'],
tags={
'version': swift_version,
'git_repository': SWIFT_FUCHSIA_GIT,
'git_revision': revision,
},
)
api.gsutil.upload(
'fuchsia',
cipd_pkg_file,
api.gsutil.join('swift', api.cipd.platform_suffix(),
step_result.json.output['result']['instance_id']),
unauthenticated_url=True)
def GenTests(api):
revision = '85bce8d910db00261b4844f784dca1a8e322b7e0'
version = "Swift version 4.1-dev (LLVM 7959c1098f, Clang dff0a814ae, Swift 6058ffab78)"
for platform in ('linux','mac'):
yield (api.test(platform + "_existing") +
api.platform.name(platform) +
api.properties(goma_dir='/goma') +
api.gitiles.refs('refs', ('refs/heads/upstream/fuchsia_release', revision)) +
api.step_data('cipd search fuchsia/swift/' + platform + '-amd64 ' +
'git_revision:' + revision, api.json.output({
'result': ["something"]
})))
yield (api.test(platform) +
api.platform.name(platform) +
api.gitiles.refs('refs', ('refs/heads/upstream/fuchsia_release', revision)) +
api.step_data('swift version', api.raw_io.stream_output(version)) +
api.step_data('cipd search fuchsia/swift/' + platform + '-amd64 ' +
'git_revision:' + revision, api.json.output({
'result': []
})))