Skip to content

Commit 6807ef6

Browse files
committed
[build-script] LLVM Python builder + infrastructure.
LLVM builder and all the surrounding necessary infrastructure. Because other builders make use of some pieces of LLVM, LLVM should be the first builder available. - Add new options to the Python arguments which were part of the build-script-impl and not of build-script. Where the options have been used in presets, the naming has been maintained, but in some cases the naming of the underlaying variables should explain better what the arguments do. The descriptions have been copied where possible. - Added functionality in the CMake type to generate and build targets. The generation uses the source and build directories, and the given options, while the building generates CMake arguments and build arguments depending on the build variant. The targets will be modified for Xcode in all cases (in build-script-impl this step wasn't doing uniformily). - BuilderHostInstallMixin is a mixin for different builder (here it is only used in the CMake builder), but contains pieces of code that are shared between different builder. It deals with paths when doing cross-compiled targets. - CMakeProductBuilder is a builder that uses CMake to build the given product. Subclasses are supposed to customize this builder with their own pieces (usually the protected methods). The do_build implementation does the generation of the CMake build directory and the build; do_test is supposed to build the test targets and execute them; while do_install will invoke the install target. For most templated methods I found good defaults or common values, but there are pieces that are abstract (like build_variant). - LLVMBase is a mixin for product builders that hold pieces of code used from several different builders, but related to LLVM. The Swift product will use the values of LTO defined for LLVM, and other products like libcxx use the same CMake options as LLVM. - LLVMBuilder is an specialization of CMakeProductBuilder for LLVM. Most of the builders will have to specialize the initializer (to provide its product to CMakeProductBuilder and the initial CMake options), and some of the template methods. However LLVMBuilder also overrides the do_build because it needs to symlink the C++ headers into the build directory. The builder also offers a series of public read-only properties to recover some of the interesting paths of the results. - The shell module gets a new helper function to get the SDK path, which is used by several products.
1 parent f08f723 commit 6807ef6

File tree

8 files changed

+766
-11
lines changed

8 files changed

+766
-11
lines changed

utils/build_swift/driver_arguments.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ def create_argument_parser():
341341
help='the path to install debug symbols into')
342342
option('--install-destdir', store_path,
343343
help='the path to use as the filesystem root for the installation')
344+
option('--build-toolchain-only', toggle_true,
345+
help='Only build the necessary tools to build an external toolchain')
344346

345347
option(['-j', '--jobs'], store_int('build_jobs'),
346348
default=multiprocessing.cpu_count(),
@@ -568,12 +570,25 @@ def create_argument_parser():
568570
option(['--build-libparser-only'], store_true('build_libparser_only'),
569571
help='build only libParser for SwiftSyntax')
570572

573+
option('--build-llvm', toggle_false('clean_llvm'),
574+
default=False,
575+
help='If set to false, cleans the LLVM build result.')
576+
577+
option('--skip-build-llvm', store_false('build_llvm'),
578+
help='Skip building LLVM/Clang')
579+
580+
option('--skip-build-compiler-rt', store_false('build_compiler_rt'),
581+
help='Skip building Compiler-RT')
582+
571583
# -------------------------------------------------------------------------
572584
in_group('Extra actions to perform before or in addition to building')
573585

574586
option(['-c', '--clean'], store_true,
575587
help='do a clean build')
576588

589+
option('--reconfigure', store_true,
590+
help='force a CMake configuration run even if CMakeCache.txt already exists')
591+
577592
option('--export-compile-commands', toggle_true,
578593
help='generate compilation databases in addition to building')
579594

@@ -924,6 +939,10 @@ def create_argument_parser():
924939
default='X86;ARM;AArch64;PowerPC;SystemZ;Mips',
925940
help='LLVM target generators to build')
926941

942+
option('--llvm-include-tests', toggle_true,
943+
default=True,
944+
help='Generate testing targets for LLVM. Set to true by default.')
945+
927946
# -------------------------------------------------------------------------
928947
in_group('Build settings for Android')
929948

utils/build_swift/tests/expected_options.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
'build_android': False,
5757
'build_args': [],
5858
'build_benchmarks': True,
59+
'build_compiler_rt': True,
5960
'build_cygwin': True,
6061
'build_external_benchmarks': False,
6162
'build_foundation': False,
@@ -69,6 +70,7 @@
6970
'build_linux': True,
7071
'build_llbuild': False,
7172
'build_lldb': False,
73+
'build_llvm': True,
7274
'build_libcxx': False,
7375
'build_ninja': False,
7476
'build_osx': True,
@@ -88,6 +90,7 @@
8890
'build_swiftevolve': False,
8991
'build_indexstoredb': False,
9092
'build_sourcekitlsp': False,
93+
'build_toolchain_only': False,
9194
'build_tvos': True,
9295
'build_tvos_device': False,
9396
'build_tvos_simulator': False,
@@ -102,6 +105,7 @@
102105
'clang_profile_instr_use': None,
103106
'clang_user_visible_version': defaults.CLANG_USER_VISIBLE_VERSION,
104107
'clean': False,
108+
'clean_llvm': False,
105109
'cmake': None,
106110
'cmake_generator': 'Ninja',
107111
'cmark_assertions': True,
@@ -154,11 +158,13 @@
154158
'lldb_build_with_xcode': '1',
155159
'llvm_assertions': True,
156160
'llvm_build_variant': 'Debug',
161+
'llvm_include_tests': True,
157162
'llvm_max_parallel_lto_link_jobs':
158163
host.max_lto_link_job_counts()['llvm'],
159164
'llvm_targets_to_build': 'X86;ARM;AArch64;PowerPC;SystemZ;Mips',
160165
'long_test': False,
161166
'lto_type': None,
167+
'reconfigure': False,
162168
'show_sdks': False,
163169
'skip_build': False,
164170
'stdlib_deployment_targets': None,
@@ -397,6 +403,9 @@ class IgnoreOption(_BaseOption):
397403
SetOption('--skip-tvos', dest='tvos', value=False),
398404
SetOption('--skip-watchos', dest='watchos', value=False),
399405

406+
SetFalseOption('--skip-build-compiler-rt', dest='build_compiler_rt'),
407+
SetFalseOption('--skip-build-llvm', dest='build_llvm'),
408+
400409
SetTrueOption('--benchmark'),
401410
SetTrueOption('--clean'),
402411
SetTrueOption('--dry-run'),
@@ -408,6 +417,7 @@ class IgnoreOption(_BaseOption):
408417
SetTrueOption('--lldb', dest='build_lldb'),
409418
SetTrueOption('--libcxx', dest='build_libcxx'),
410419
SetTrueOption('--playgroundsupport', dest='build_playgroundsupport'),
420+
SetTrueOption('--reconfigure'),
411421
SetTrueOption('--skip-build'),
412422
SetTrueOption('--swiftpm', dest='build_swiftpm'),
413423
SetTrueOption('--swiftsyntax', dest='build_swiftsyntax'),
@@ -434,6 +444,7 @@ class IgnoreOption(_BaseOption):
434444
EnableOption('--build-swift-static-sdk-overlay'),
435445
EnableOption('--build-swift-static-stdlib'),
436446
EnableOption('--build-swift-stdlib-unittest-extra'),
447+
EnableOption('--build-toolchain-only'),
437448
EnableOption('--distcc'),
438449
EnableOption('--enable-asan'),
439450
EnableOption('--enable-lsan'),
@@ -446,6 +457,7 @@ class IgnoreOption(_BaseOption):
446457
EnableOption('--host-test'),
447458
EnableOption('--libdispatch', dest='build_libdispatch'),
448459
EnableOption('--libicu', dest='build_libicu'),
460+
EnableOption('--llvm-include-tests'),
449461
EnableOption('--indexstore-db', dest='build_indexstoredb'),
450462
EnableOption('--sourcekit-lsp', dest='build_sourcekitlsp'),
451463
EnableOption('--long-test'),
@@ -461,6 +473,7 @@ class IgnoreOption(_BaseOption):
461473
EnableOption('--watchos'),
462474
EnableOption('--xctest', dest='build_xctest'),
463475

476+
DisableOption('--build-llvm', dest='clean_llvm'),
464477
DisableOption('--skip-build-android', dest='build_android'),
465478
DisableOption('--skip-build-benchmarks', dest='build_benchmarks'),
466479
DisableOption('--skip-build-cygwin', dest='build_cygwin'),

utils/swift_build_support/swift_build_support/cmake.py

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
from __future__ import absolute_import
1818

19+
import itertools
20+
import os
1921
from numbers import Number
2022

2123
from . import shell
@@ -128,7 +130,7 @@ def common_options(self):
128130
define("CMAKE_CXX_COMPILER:PATH", toolchain.cxx)
129131
define("CMAKE_LIBTOOL:PATH", toolchain.libtool)
130132

131-
if args.cmake_generator == 'Xcode':
133+
if self.__is_xcode_generator:
132134
define("CMAKE_CONFIGURATION_TYPES",
133135
"Debug;Release;MinSizeRel;RelWithDebInfo")
134136

@@ -142,9 +144,8 @@ def common_options(self):
142144
define("CLANG_VERSION_MINOR:STRING", minor)
143145
define("CLANG_VERSION_PATCH:STRING", patch)
144146

145-
if args.build_ninja and args.cmake_generator == 'Ninja':
146-
define('CMAKE_MAKE_PROGRAM', toolchain.ninja)
147-
elif args.cmake_generator == 'Ninja' and toolchain.ninja is not None:
147+
if self.__is_ninja_generator and \
148+
(args.build_ninja or toolchain.ninja is not None):
148149
define('CMAKE_MAKE_PROGRAM', toolchain.ninja)
149150

150151
return options
@@ -161,18 +162,109 @@ def build_args(self):
161162

162163
build_args = list(args.build_args)
163164

164-
if args.cmake_generator == 'Ninja':
165+
if self.__is_ninja_generator:
165166
build_args += ['-j%s' % jobs]
166167
if args.verbose_build:
167168
build_args += ['-v']
168169

169-
elif args.cmake_generator == 'Unix Makefiles':
170+
elif self.__is_makefile_generator:
170171
build_args += ['-j%s' % jobs]
171172
if args.verbose_build:
172173
build_args += ['VERBOSE=1']
173174

174-
elif args.cmake_generator == 'Xcode':
175+
elif self.__is_xcode_generator:
175176
build_args += ['-parallelizeTargets',
176177
'-jobs', str(jobs)]
177178

178179
return build_args
180+
181+
def generate(self, source_dir, build_dir, cmake_options=None):
182+
cmake_options = [] if cmake_options is None else cmake_options
183+
shell.makedirs(build_dir)
184+
extra_environment = {}
185+
if self.args.distcc:
186+
extra_environment['DISTCC_HOSTS'] = 'localhost,lzo,cpp'
187+
with shell.pushd(build_dir):
188+
shell.call([self.toolchain.cmake] + self.common_options() +
189+
cmake_options + self.args.extra_cmake_options +
190+
[source_dir],
191+
env=extra_environment)
192+
193+
def generate_if_needed(self, source_dir, build_dir, cmake_options=None):
194+
# Compute the generator output file to check for, to determine if we
195+
# must reconfigure. We only handle Ninja for now.
196+
#
197+
# This is important for ensuring that if a Cmake configuration fails in
198+
# CI, that we will still be willing to rerun the configuration process.
199+
cmake_options = [] if cmake_options is None else cmake_options
200+
generator_output_path = None
201+
if self.__is_ninja_generator:
202+
generator_output_path = os.path.join(build_dir, 'build.ninja')
203+
204+
# Configure if necessary
205+
cmake_cache_path = os.path.join(build_dir, 'CMakeCache.txt')
206+
if self.args.reconfigure or \
207+
not os.path.exists(cmake_cache_path) or \
208+
(generator_output_path is not None and
209+
not os.path.exists(generator_output_path)):
210+
self.generate(source_dir, build_dir, cmake_options)
211+
212+
def build_targets(self, build_dir, build_variant, targets=None):
213+
targets = ['all'] if targets is None else targets
214+
self.__cmake_build(build_dir,
215+
cmake_arguments=self.__cmake_config(build_variant),
216+
build_arguments=self.build_args(),
217+
targets=targets)
218+
219+
def install_targets(self, build_dir, targets=None, environment=None):
220+
targets = [] if targets is None else targets
221+
self.__cmake_build(build_dir,
222+
targets=targets,
223+
environment=environment)
224+
225+
def __cmake_build(self, build_dir, cmake_arguments=None,
226+
build_arguments=None, targets=None, environment=None):
227+
cmake_arguments = [] if cmake_arguments is None else cmake_arguments
228+
build_arguments = [] if build_arguments is None else build_arguments
229+
targets = [] if targets is None else targets
230+
distcc_pump = []
231+
if self.args.distcc:
232+
distcc_pump = [self.toolchain.distcc_pump]
233+
234+
if self.__is_xcode_generator:
235+
targets = self.__transform_targets_for_xcode(targets)
236+
237+
shell.call(distcc_pump + [self.toolchain.cmake, '--build', build_dir] +
238+
cmake_arguments + ['--'] + build_arguments + targets,
239+
env=environment)
240+
241+
def __cmake_config(self, build_variant):
242+
if self.__is_xcode_generator:
243+
return [
244+
'--target', 'ZERO_CHECK',
245+
'--config', build_variant
246+
]
247+
else:
248+
return []
249+
250+
@property
251+
def __is_xcode_generator(self):
252+
return self.args.cmake_generator == 'Xcode'
253+
254+
@property
255+
def __is_ninja_generator(self):
256+
return self.args.cmake_generator == 'Ninja'
257+
258+
@property
259+
def __is_makefile_generator(self):
260+
return self.args.cmake_generator == 'Unix Makefiles'
261+
262+
def __transform_targets_for_xcode(self, targets):
263+
# Xcode generator uses "ALL_BUILD" instead of "all".
264+
# Also, xcodebuild uses -target instead of bare names.
265+
targets = ['ALL_BUILD'
266+
if t == 'all' else t
267+
for t in targets]
268+
targets = itertools.chain.from_iterable(
269+
[['-target', t] for t in targets])
270+
return targets

utils/swift_build_support/swift_build_support/products/build_script_impl_builder.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ def __convert_to_impl_arguments(self):
141141
pipes.quote(arg) for arg in cmake.build_args()),
142142
]
143143

144+
if args.reconfigure:
145+
impl_args += ['--reconfigure']
146+
144147
# Compute any product specific cmake arguments.
145148
for product_class in self.__product_classes:
146149
if not product_class.is_build_script_impl_product():
@@ -183,6 +186,8 @@ def __convert_to_impl_arguments(self):
183186
if args.cross_compile_hosts:
184187
impl_args += [
185188
"--cross-compile-hosts", " ".join(args.cross_compile_hosts)]
189+
if args.build_toolchain_only:
190+
impl_args += ['--build-toolchain-only']
186191

187192
if args.test_paths:
188193
impl_args += ["--test-paths", " ".join(args.test_paths)]
@@ -227,7 +232,6 @@ def __convert_to_impl_arguments(self):
227232

228233
if args.skip_build:
229234
impl_args += ["--skip-build-cmark",
230-
"--skip-build-llvm",
231235
"--skip-build-swift"]
232236
if not args.build_benchmarks:
233237
impl_args += ["--skip-build-benchmarks"]
@@ -238,6 +242,11 @@ def __convert_to_impl_arguments(self):
238242
impl_args += ["--skip-build-foundation"]
239243
if not args.build_xctest:
240244
impl_args += ["--skip-build-xctest"]
245+
if not args.build_llvm:
246+
impl_args += ['--skip-build-llvm']
247+
impl_args += ['--build-llvm=%s' % args.clean_llvm]
248+
if not args.build_compiler_rt:
249+
impl_args += ["--skip-build-compiler-rt"]
241250
if not args.build_lldb:
242251
impl_args += ["--skip-build-lldb"]
243252
if not args.build_llbuild:
@@ -425,6 +434,8 @@ def __convert_to_impl_arguments(self):
425434
os.path.abspath(args.clang_profile_instr_use)
426435
]
427436

437+
impl_args += ['--llvm-include-tests=%s' % args.llvm_include_tests]
438+
428439
if args.lit_args:
429440
impl_args += ["--llvm-lit-args=%s" % args.lit_args]
430441

0 commit comments

Comments
 (0)