@@ -30,6 +30,10 @@ def get_swiftpm_options(args):
30
30
if args .verbose :
31
31
swiftpm_args += ['--verbose' ]
32
32
33
+ if args .sanitize :
34
+ for san in args .sanitize :
35
+ swiftpm_args += ['--sanitize=%s' % san ]
36
+
33
37
if platform .system () == 'Darwin' :
34
38
swiftpm_args += [
35
39
# Relative library rpath for swift; will only be used when /usr/lib/swift
@@ -81,6 +85,44 @@ def delete_rpath(rpath, binary):
81
85
print (' ' .join (cmd ))
82
86
subprocess .check_call (cmd )
83
87
88
+
89
+ def handle_invocation (swift_exec , args ):
90
+ swiftpm_args = get_swiftpm_options (args )
91
+
92
+ env = os .environ
93
+ # Set the toolchain used in tests at runtime
94
+ env ['SOURCEKIT_TOOLCHAIN_PATH' ] = args .toolchain
95
+ # Use local dependencies (i.e. checked out next sourcekit-lsp).
96
+ if not args .no_local_deps :
97
+ env ['SWIFTCI_USE_LOCAL_DEPS' ] = "1"
98
+
99
+ if args .ninja_bin :
100
+ env ['NINJA_BIN' ] = args .ninja_bin
101
+
102
+ if args .sanitize and 'address' in args .sanitize :
103
+ # Workaround reports in Foundation: https://bugs.swift.org/browse/SR-12551
104
+ env ['ASAN_OPTIONS' ] = 'detect_leaks=false'
105
+ if args .sanitize and 'undefined' in args .sanitize :
106
+ supp = os .path .join (args .package_path , 'Utilities' , 'ubsan_supressions.supp' )
107
+ env ['UBSAN_OPTIONS' ] = 'halt_on_error=true,suppressions=%s' % supp
108
+
109
+
110
+ if args .action == 'build' :
111
+ swiftpm ('build' , swift_exec , swiftpm_args , env )
112
+ elif args .action == 'test' :
113
+ bin_path = swiftpm_bin_path (swift_exec , swiftpm_args , env )
114
+ tests = os .path .join (bin_path , 'sk-tests' )
115
+ print ('Cleaning ' + tests )
116
+ shutil .rmtree (tests , ignore_errors = True )
117
+ swiftpm ('test' , swift_exec , swiftpm_args + ['--parallel' ], env )
118
+ elif args .action == 'install' :
119
+ bin_path = swiftpm_bin_path (swift_exec , swiftpm_args , env )
120
+ swiftpm ('build' , swift_exec , swiftpm_args , env )
121
+ install (bin_path , args .toolchain )
122
+ else :
123
+ assert False , 'unknown action \' {}\' ' .format (args .action )
124
+
125
+
84
126
def main ():
85
127
parser = argparse .ArgumentParser (description = 'Build along with the Swift build-script.' )
86
128
def add_common_args (parser ):
@@ -90,6 +132,8 @@ def add_common_args(parser):
90
132
parser .add_argument ('--build-path' , metavar = 'PATH' , default = '.build' , help = 'build in the given path' )
91
133
parser .add_argument ('--configuration' , '-c' , default = 'debug' , help = 'build using configuration (release|debug)' )
92
134
parser .add_argument ('--no-local-deps' , action = 'store_true' , help = 'use normal remote dependencies when building' )
135
+ parser .add_argument ('--sanitize' , action = 'append' , help = 'build using the given sanitizer(s) (address|thread|undefined)' )
136
+ parser .add_argument ('--sanitize-all' , action = 'store_true' , help = 'build using every available sanitizer in sub-directories of build path' )
93
137
parser .add_argument ('--verbose' , '-v' , action = 'store_true' , help = 'enable verbose output' )
94
138
95
139
subparsers = parser .add_subparsers (title = 'subcommands' , dest = 'action' , metavar = 'action' )
@@ -104,6 +148,9 @@ def add_common_args(parser):
104
148
105
149
args = parser .parse_args (sys .argv [1 :])
106
150
151
+ if args .sanitize and args .sanitize_all :
152
+ assert False , 'cannot combine --sanitize with --sanitize-all'
153
+
107
154
# Canonicalize paths
108
155
args .package_path = os .path .abspath (args .package_path )
109
156
args .build_path = os .path .abspath (args .build_path )
@@ -114,32 +161,27 @@ def add_common_args(parser):
114
161
else :
115
162
swift_exec = 'swift'
116
163
117
- swiftpm_args = get_swiftpm_options (args )
164
+ handle_invocation (swift_exec , args )
165
+ if args .sanitize_all :
166
+ base = args .build_path
118
167
119
- env = os .environ
120
- # Set the toolchain used in tests at runtime
121
- env ['SOURCEKIT_TOOLCHAIN_PATH' ] = args .toolchain
122
- # Use local dependencies (i.e. checked out next sourcekit-lsp).
123
- if not args .no_local_deps :
124
- env ['SWIFTCI_USE_LOCAL_DEPS' ] = "1"
168
+ print ('=== %s sourcekit-lsp with asan ===' % args .action )
169
+ args .sanitize = ['address' ]
170
+ args .build_path = os .path .join (base , 'test-asan' )
171
+ handle_invocation (swift_exec , args )
125
172
126
- if args .ninja_bin :
127
- env ['NINJA_BIN' ] = args .ninja_bin
173
+ print ('=== %s sourcekit-lsp with tsan ===' % args .action )
174
+ args .sanitize = ['thread' ]
175
+ args .build_path = os .path .join (base , 'test-tsan' )
176
+ handle_invocation (swift_exec , args )
177
+
178
+ # Linux ubsan disabled: https://bugs.swift.org/browse/SR-12550
179
+ if platform .system () != 'Linux' :
180
+ print ('=== %s sourcekit-lsp with ubsan ===' % args .action )
181
+ args .sanitize = ['undefined' ]
182
+ args .build_path = os .path .join (base , 'test-ubsan' )
183
+ handle_invocation (swift_exec , args )
128
184
129
- if args .action == 'build' :
130
- swiftpm ('build' , swift_exec , swiftpm_args , env )
131
- elif args .action == 'test' :
132
- bin_path = swiftpm_bin_path (swift_exec , swiftpm_args , env )
133
- tests = os .path .join (bin_path , 'sk-tests' )
134
- print ('Cleaning ' + tests )
135
- shutil .rmtree (tests , ignore_errors = True )
136
- swiftpm ('test' , swift_exec , swiftpm_args + ['--parallel' ], env )
137
- elif args .action == 'install' :
138
- bin_path = swiftpm_bin_path (swift_exec , swiftpm_args , env )
139
- swiftpm ('build' , swift_exec , swiftpm_args , env )
140
- install (bin_path , args .toolchain )
141
- else :
142
- assert False , 'unknown action \' {}\' ' .format (args .action )
143
185
144
186
if __name__ == '__main__' :
145
187
main ()
0 commit comments