Skip to content

Commit e49379a

Browse files
committed
Add clangc flag to runner.py
'--clangc' provides a way to build projects with a custom clang binary. With '--clang-source-path', the 'run' script builds clang binary from the clang source in the path and provides this binary path to 'runner.py' using the '--clangc' flag.
1 parent 36d3a10 commit e49379a

File tree

4 files changed

+136
-4
lines changed

4 files changed

+136
-4
lines changed

clang_installer.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env python
2+
# ===--- clang_installer.py --------------------------------------------------------===
3+
#
4+
# This source file is part of the Swift.org open source project
5+
#
6+
# Copyright (c) 2021 Apple Inc. and the Swift project authors
7+
# Licensed under Apache License v2.0 with Runtime Library Exception
8+
#
9+
# See https://swift.org/LICENSE.txt for license information
10+
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
#
12+
# ===----------------------------------------------------------------------===
13+
14+
import common
15+
import os
16+
import signal
17+
18+
class ClangInstaller(object):
19+
def __init__(self, prebuilt):
20+
self.clang_paths = []
21+
for sdk in ['macosx']:
22+
try:
23+
sdk_clang_path = common.check_execute_output(['xcrun', '--sdk', sdk, '--find', 'clang']).strip()
24+
except:
25+
pass
26+
else:
27+
self.clang_paths.append(sdk_clang_path)
28+
29+
self.local_clang_path = prebuilt
30+
self.root_path = common.private_workspace('project_cache')
31+
self.source_path = os.path.join(self.root_path, 'llvm-project')
32+
33+
def exit_handler(signal_received, frame):
34+
self.clear()
35+
exit(signal_received)
36+
37+
# run exit_handler() function when CTRL-C or CTRL-Z is received
38+
signal.signal(signal.SIGINT, exit_handler)
39+
signal.signal(signal.SIGTSTP, exit_handler)
40+
41+
@staticmethod
42+
def orig_postfix():
43+
return ".compatsuite.orig"
44+
45+
def install(self):
46+
for clang_path in self.clang_paths:
47+
clang_orig_path = clang_path + self.orig_postfix()
48+
if os.path.isfile(clang_orig_path):
49+
if os.path.islink(clang_path):
50+
common.check_execute(['rm', clang_path])
51+
elif os.path.isfile(clang_path):
52+
continue
53+
else:
54+
common.check_execute(['mv', clang_path, clang_orig_path])
55+
56+
common.check_execute(['ln', '-s', self.local_clang_path, clang_path])
57+
58+
def clear(self):
59+
if not self.clang_paths:
60+
return
61+
print('Restoring swapped clang binaries.')
62+
for clang_path in self.clang_paths:
63+
clang_orig_path = clang_path + self.orig_postfix()
64+
if not os.path.isfile(clang_orig_path):
65+
continue
66+
67+
if os.path.isfile(clang_path):
68+
if os.path.islink(clang_path):
69+
common.check_execute(['rm', clang_path])
70+
else:
71+
continue
72+
73+
common.check_execute(['mv', clang_orig_path, clang_path])
74+
self.clang_paths = []
75+
76+
def __del__(self):
77+
self.clear()

project_future.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,9 @@ def add_arguments(parser):
583583
parser.add_argument("--report-time-path",
584584
help='export time for building each xcode build target to the specified json file',
585585
type=os.path.abspath)
586+
parser.add_argument("--clangc",
587+
help='clang executable to temporarily be swapped with the clang in the toolchain',
588+
type=os.path.abspath)
586589

587590
def add_minimal_arguments(parser):
588591
"""Add common arguments to parser."""

run

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,19 @@ def main():
3737
if not args.skip_build:
3838
build_swift_toolchain(workspace, args)
3939

40+
clang_flag = []
41+
if args.clang_source_path or args.clangc:
42+
clangc = args.clangc
43+
if args.clang_source_path:
44+
clangc = build_clang(workspace, args.clang_source_path)
45+
if clangc:
46+
clang_flag = ['--clangc', clangc]
47+
4048
if not args.skip_runner:
4149
if args.test_incremental:
42-
execute_build_incremental(workspace, args)
50+
execute_build_incremental(workspace, args, clang_flag)
4351
else:
44-
execute_runner(workspace, args)
52+
execute_runner(workspace, args, clang_flag)
4553

4654
return 0
4755

@@ -74,6 +82,15 @@ def parse_args():
7482
parser.add_argument('--swiftc',
7583
metavar='PATH',
7684
help='swiftc executable')
85+
clang_arguments = parser.add_mutually_exclusive_group()
86+
clang_arguments.add_argument('--clang-source-path',
87+
metavar="PATH",
88+
help='path to llvm-project to build',
89+
type=os.path.abspath)
90+
clang_arguments.add_argument('--clangc',
91+
metavar="PATH",
92+
help='clang executable',
93+
type=os.path.abspath)
7794
parser.add_argument('--skip-build',
7895
action='store_true')
7996
parser.add_argument('--skip-ci-steps',
@@ -161,7 +178,7 @@ def get_sandbox_profile_flags_test():
161178
return sandbox_flags
162179

163180

164-
def execute_runner(workspace, args):
181+
def execute_runner(workspace, args, clang_flag):
165182
swiftc_path = get_swiftc_path(workspace, args.swiftc)
166183
if args.test:
167184
action_filter = 'action.startswith("TestSwiftPackage")'
@@ -193,10 +210,12 @@ def execute_runner(workspace, args):
193210
if args.build_config:
194211
runner_command += ['--build-config=%s' % args.build_config]
195212

213+
runner_command += clang_flag
214+
196215
common.check_execute(runner_command, timeout=9999999)
197216

198217

199-
def execute_build_incremental(workspace, args):
218+
def execute_build_incremental(workspace, args, clang_flag):
200219
swiftc_path = get_swiftc_path(workspace, args.swiftc)
201220
runner_command = [
202221
'./build_incremental.py',
@@ -211,6 +230,7 @@ def execute_build_incremental(workspace, args):
211230
]
212231
if args.sandbox:
213232
runner_command += get_sandbox_profile_flags()
233+
runner_command += clang_flag
214234
common.check_execute(runner_command, timeout=9999999)
215235

216236
def get_preset_name(args):
@@ -270,6 +290,28 @@ def build_swift_toolchain(workspace, args):
270290
raise common.UnsupportedPlatform
271291
common.check_execute(build_command, timeout=9999999)
272292

293+
def build_clang(workspace, source_path):
294+
build_path = os.path.join(workspace, 'build_clang_source_compat')
295+
source_path = os.path.join(source_path, 'llvm')
296+
common.check_execute(['mkdir', '-p', build_path])
297+
298+
with common.DirectoryContext(build_path):
299+
try:
300+
ninja_path = common.check_execute_output(['xcrun', '--find', 'ninja']).strip().decode("utf-8")
301+
cmake_command = [
302+
'xcrun', 'cmake', '-G', 'Ninja',
303+
'-DCMAKE_MAKE_PROGRAM={}'.format(ninja_path),
304+
'-DLLVM_ENABLE_PROJECTS=clang;llvm',
305+
'-DCMAKE_BUILD_TYPE=Release',
306+
'-DCLANG_APPLE_BUILD_VERSION_STRING=13000000',
307+
'-DLLVM_TARGETS_TO_BUILD=X86;AArch64;ARM',
308+
source_path]
309+
common.check_execute(cmake_command)
310+
common.check_execute(['xcrun', 'ninja'])
311+
except:
312+
raise
313+
314+
return os.path.join(build_path, 'bin', 'clang')
273315

274316
if __name__ == '__main__':
275317
sys.exit(main())

runner.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import common
2121
import project_future
22+
import clang_installer
2223

2324

2425
def parse_args():
@@ -48,6 +49,11 @@ def main():
4849
if args.report_time_path:
4950
time_reporter = project_future.TimeReporter(args.report_time_path)
5051

52+
clangc_installer = None
53+
if args.clangc:
54+
clangc_installer = clang_installer.ClangInstaller(args.clangc)
55+
clangc_installer.install()
56+
5157
index = json.loads(open(args.projects).read())
5258
result = project_future.ProjectListBuilder(
5359
args.include_repos,
@@ -81,6 +87,10 @@ def main():
8187
index
8288
).build()
8389
common.debug_print(str(result))
90+
91+
if clangc_installer:
92+
clangc_installer.clear()
93+
8494
return 0 if result.result in [project_future.ResultEnum.PASS,
8595
project_future.ResultEnum.XFAIL] else 1
8696

0 commit comments

Comments
 (0)