Skip to content

Commit 426f901

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 426f901

File tree

4 files changed

+143
-4
lines changed

4 files changed

+143
-4
lines changed

clang_installer.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
self._default_sig_handlers = {
34+
signal.SIGINT: signal.getsignal(signal.SIGINT),
35+
signal.SIGTSTP: signal.getsignal(signal.SIGTSTP)
36+
}
37+
38+
def exit_handler(signal_received, frame):
39+
self.clear()
40+
default_sig_handler = self._default_sig_handlers[signal_received]
41+
signal.signal(signal_received, default_sig_handler)
42+
default_sig_handler(signal_received, frame)
43+
44+
# run exit_handler() function when CTRL-C or CTRL-Z is received
45+
signal.signal(signal.SIGINT, exit_handler)
46+
signal.signal(signal.SIGTSTP, exit_handler)
47+
48+
@staticmethod
49+
def orig_postfix():
50+
return ".compatsuite.orig"
51+
52+
def install(self):
53+
for clang_path in self.clang_paths:
54+
clang_orig_path = clang_path + self.orig_postfix()
55+
if os.path.isfile(clang_orig_path):
56+
if os.path.islink(clang_path):
57+
common.check_execute(['rm', clang_path])
58+
elif os.path.isfile(clang_path):
59+
continue
60+
else:
61+
common.check_execute(['mv', clang_path, clang_orig_path])
62+
63+
common.check_execute(['ln', '-s', self.local_clang_path, clang_path])
64+
65+
def clear(self):
66+
if not self.clang_paths:
67+
return
68+
print('Restoring swapped clang binaries.')
69+
for clang_path in self.clang_paths:
70+
clang_orig_path = clang_path + self.orig_postfix()
71+
if not os.path.isfile(clang_orig_path):
72+
continue
73+
74+
if os.path.isfile(clang_path):
75+
if os.path.islink(clang_path):
76+
common.check_execute(['rm', clang_path])
77+
else:
78+
continue
79+
80+
common.check_execute(['mv', clang_orig_path, clang_path])
81+
self.clang_paths = []
82+
83+
def __del__(self):
84+
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)