1#!/usr/bin/env python 2 3"""Ninja toolchain abstraction for Clang compiler suite""" 4 5import os 6import subprocess 7 8import toolchain 9 10class ClangToolchain(toolchain.Toolchain): 11 12 def initialize(self, project, archs, configs, includepaths, dependlibs, libpaths, variables, subninja): 13 #Local variable defaults 14 self.toolchain = '' 15 self.sdkpath = '' 16 self.includepaths = [] 17 self.libpaths = libpaths 18 self.ccompiler = 'clang' 19 self.cxxcompiler = 'clang++' 20 self.archiver = 'ar' 21 self.linker = 'clang' 22 self.cxxlinker = 'clang++' 23 if self.target.is_windows(): 24 self.archiver = 'llvm-ar' 25 26 #Default variables 27 self.sysroot = '' 28 if self.target.is_ios(): 29 self.deploymenttarget = '9.0' 30 if self.target.is_macos(): 31 self.deploymenttarget = '10.7' 32 33 #Command definitions 34 self.cccmd = '$toolchain$cc -MMD -MT $out -MF $out.d $includepaths $moreincludepaths $cflags $carchflags $cconfigflags $cmoreflags -c $in -o $out' 35 self.cxxcmd = '$toolchain$cxx -MMD -MT $out -MF $out.d $includepaths $moreincludepaths $cxxflags $carchflags $cconfigflags $cmoreflags -c $in -o $out' 36 self.ccdeps = 'gcc' 37 self.ccdepfile = '$out.d' 38 self.arcmd = self.rmcmd('$out') + ' && $toolchain$ar crsD $ararchflags $arflags $out $in' 39 self.linkcmd = '$toolchain$link $libpaths $configlibpaths $linkflags $linkarchflags $linkconfigflags -o $out $in $libs $archlibs $oslibs $frameworks' 40 41 #Base flags 42 self.cflags = ['-D' + project.upper() + '_COMPILE=1', 43 '-funit-at-a-time', '-fstrict-aliasing', '-fvisibility=hidden', '-fno-stack-protector', 44 '-fomit-frame-pointer', '-fno-math-errno','-ffinite-math-only', '-funsafe-math-optimizations', 45 '-fno-trapping-math', '-ffast-math'] 46 self.cwarnflags = ['-W', '-Werror', '-pedantic', '-Wall', '-Weverything', 47 '-Wno-padded', '-Wno-documentation-unknown-command', '-Wno-static-in-inline'] 48 self.cmoreflags = [] 49 self.mflags = [] 50 self.arflags = [] 51 self.linkflags = ['-fomit-frame-pointer'] 52 self.oslibs = [] 53 self.frameworks = [] 54 55 self.initialize_subninja(subninja) 56 self.initialize_archs(archs) 57 self.initialize_configs(configs) 58 self.initialize_project(project) 59 self.initialize_toolchain() 60 self.initialize_depends(dependlibs) 61 62 self.parse_default_variables(variables) 63 self.read_build_prefs() 64 65 if self.target.is_linux() or self.target.is_bsd() or self.target.is_raspberrypi(): 66 self.cflags += ['-D_GNU_SOURCE=1'] 67 self.linkflags += ['-pthread'] 68 if self.target.is_linux() or self.target.is_raspberrypi(): 69 self.oslibs += ['dl'] 70 if self.target.is_bsd(): 71 self.oslibs += ['execinfo'] 72 73 self.includepaths = self.prefix_includepaths((includepaths or []) + ['.']) 74 75 if self.is_monolithic(): 76 self.cflags += ['-DBUILD_MONOLITHIC=1'] 77 if self.use_coverage(): 78 self.cflags += ['--coverage'] 79 self.linkflags += ['--coverage'] 80 81 if not 'nowarning' in variables or not variables['nowarning']: 82 self.cflags += self.cwarnflags 83 else: 84 self.cflags += ['-w'] 85 self.cxxflags = list(self.cflags) 86 87 self.cflags += ['-std=gnu11'] 88 if self.target.is_macos() or self.target.is_ios(): 89 self.cxxflags += ['-std=c++14', '-stdlib=libc++'] 90 else: 91 self.cxxflags += ['-std=gnu++14'] 92 93 #Overrides 94 self.objext = '.o' 95 96 #Builders 97 self.builders['c'] = self.builder_cc 98 self.builders['cc'] = self.builder_cxx 99 self.builders['cpp'] = self.builder_cxx 100 self.builders['lib'] = self.builder_lib 101 self.builders['sharedlib'] = self.builder_sharedlib 102 self.builders['bin'] = self.builder_bin 103 if self.target.is_macos() or self.target.is_ios(): 104 self.builders['m'] = self.builder_cm 105 self.builders['multilib'] = self.builder_apple_multilib 106 self.builders['multisharedlib'] = self.builder_apple_multisharedlib 107 self.builders['multibin'] = self.builder_apple_multibin 108 else: 109 self.builders['multilib'] = self.builder_multicopy 110 self.builders['multisharedlib'] = self.builder_multicopy 111 self.builders['multibin'] = self.builder_multicopy 112 113 #Setup target platform 114 self.build_toolchain() 115 116 def name(self): 117 return 'clang' 118 119 def parse_prefs(self, prefs): 120 super(ClangToolchain, self).parse_prefs(prefs) 121 if 'clang' in prefs: 122 clangprefs = prefs['clang'] 123 if 'toolchain' in clangprefs: 124 self.toolchain = clangprefs['toolchain'] 125 if os.path.split(self.toolchain)[1] != 'bin': 126 self.toolchain = os.path.join(self.toolchain, 'bin') 127 if 'archiver' in clangprefs: 128 self.archiver = clangprefs['archiver'] 129 if self.target.is_ios() and 'ios' in prefs: 130 iosprefs = prefs['ios'] 131 if 'deploymenttarget' in iosprefs: 132 self.deploymenttarget = iosprefs['deploymenttarget'] 133 if self.target.is_macos() and 'macos' in prefs: 134 macosprefs = prefs['macos'] 135 if 'deploymenttarget' in macosprefs: 136 self.deploymenttarget = macosprefs['deploymenttarget'] 137 138 def write_variables(self, writer): 139 super(ClangToolchain, self).write_variables(writer) 140 writer.variable('toolchain', self.toolchain) 141 writer.variable('sdkpath', self.sdkpath) 142 writer.variable('sysroot', self.sysroot) 143 writer.variable('cc', self.ccompiler) 144 writer.variable('cxx', self.cxxcompiler) 145 writer.variable('ar', self.archiver) 146 writer.variable('link', self.linker) 147 if self.target.is_macos() or self.target.is_ios(): 148 writer.variable('lipo', self.lipo) 149 writer.variable('includepaths', self.make_includepaths(self.includepaths)) 150 writer.variable('moreincludepaths', '') 151 writer.variable('cflags', self.cflags) 152 writer.variable('cxxflags', self.cxxflags) 153 if self.target.is_macos() or self.target.is_ios(): 154 writer.variable('mflags', self.mflags) 155 writer.variable('carchflags', '') 156 writer.variable('cconfigflags', '') 157 writer.variable('cmoreflags', self.cmoreflags) 158 writer.variable('arflags', self.arflags) 159 writer.variable('ararchflags', '') 160 writer.variable('arconfigflags', '') 161 writer.variable('linkflags', self.linkflags) 162 writer.variable('linkarchflags', '') 163 writer.variable('linkconfigflags', '') 164 writer.variable('libs', '') 165 writer.variable('libpaths', self.make_libpaths(self.libpaths)) 166 writer.variable('configlibpaths', '') 167 writer.variable('archlibs', '') 168 writer.variable('oslibs', self.make_libs(self.oslibs)) 169 writer.variable('frameworks', '') 170 writer.newline() 171 172 def write_rules(self, writer): 173 super(ClangToolchain, self).write_rules(writer) 174 writer.rule('cc', command = self.cccmd, depfile = self.ccdepfile, deps = self.ccdeps, description = 'CC $in') 175 writer.rule('cxx', command = self.cxxcmd, depfile = self.ccdepfile, deps = self.ccdeps, description = 'CXX $in') 176 if self.target.is_macos() or self.target.is_ios(): 177 writer.rule('cm', command = self.cmcmd, depfile = self.ccdepfile, deps = self.ccdeps, description = 'CM $in') 178 writer.rule( 'lipo', command = self.lipocmd, description = 'LIPO $out' ) 179 writer.rule('ar', command = self.arcmd, description = 'LIB $out') 180 writer.rule('link', command = self.linkcmd, description = 'LINK $out') 181 writer.rule('so', command = self.linkcmd, description = 'SO $out') 182 writer.newline() 183 184 def build_toolchain(self): 185 super(ClangToolchain, self).build_toolchain() 186 if self.target.is_windows(): 187 self.build_windows_toolchain() 188 elif self.target.is_android(): 189 self.build_android_toolchain() 190 elif self.target.is_macos() or self.target.is_ios(): 191 self.build_xcode_toolchain() 192 if self.toolchain != '' and not self.toolchain.endswith('/') and not self.toolchain.endswith('\\'): 193 self.toolchain += os.sep 194 195 def build_windows_toolchain(self): 196 self.cflags += ['-U__STRICT_ANSI__', '-Wno-reserved-id-macro'] 197 self.oslibs = ['kernel32', 'user32', 'shell32', 'advapi32'] 198 199 def build_android_toolchain(self): 200 self.archiver = 'ar' 201 202 self.cccmd += ' --sysroot=$sysroot' 203 self.linkcmd += ' -shared -Wl,-soname,$liblinkname --sysroot=$sysroot' 204 self.cflags += ['-fpic', '-ffunction-sections', '-funwind-tables', '-fstack-protector', '-fomit-frame-pointer', 205 '-no-canonical-prefixes', '-Wa,--noexecstack'] 206 207 self.linkflags += ['-no-canonical-prefixes', '-Wl,--no-undefined', '-Wl,-z,noexecstack', '-Wl,-z,relro', '-Wl,-z,now'] 208 209 self.includepaths += [os.path.join('$ndk', 'sources', 'android', 'native_app_glue'), 210 os.path.join('$ndk', 'sources', 'android', 'cpufeatures')] 211 212 self.oslibs += ['log'] 213 214 self.toolchain = os.path.join('$ndk', 'toolchains', 'llvm', 'prebuilt', self.android.hostarchname, 'bin', '') 215 216 def build_xcode_toolchain(self): 217 if self.target.is_macos(): 218 sdk = 'macosx' 219 deploytarget = 'MACOSX_DEPLOYMENT_TARGET=' + self.deploymenttarget 220 self.cflags += ['-fasm-blocks', '-mmacosx-version-min=' + self.deploymenttarget, '-isysroot', '$sysroot'] 221 self.cxxflags += ['-fasm-blocks', '-mmacosx-version-min=' + self.deploymenttarget, '-isysroot', '$sysroot'] 222 self.arflags += ['-static', '-no_warning_for_no_symbols'] 223 self.linkflags += ['-isysroot', '$sysroot'] 224 elif self.target.is_ios(): 225 sdk = 'iphoneos' 226 deploytarget = 'IPHONEOS_DEPLOYMENT_TARGET=' + self.deploymenttarget 227 self.cflags += ['-fasm-blocks', '-miphoneos-version-min=' + self.deploymenttarget, '-isysroot', '$sysroot'] 228 self.cxxflags += ['-fasm-blocks', '-miphoneos-version-min=' + self.deploymenttarget, '-isysroot', '$sysroot'] 229 self.arflags += ['-static', '-no_warning_for_no_symbols'] 230 self.linkflags += ['-isysroot', '$sysroot'] 231 self.cflags += ['-fembed-bitcode-marker'] 232 233 platformpath = subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-platform-path']).strip() 234 localpath = platformpath + "/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin" 235 236 self.sysroot = subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-path']).strip() 237 238 self.ccompiler = "PATH=" + localpath + " " + subprocess.check_output(['xcrun', '--sdk', sdk, '-f', 'clang']).strip() 239 self.archiver = "PATH=" + localpath + " " + subprocess.check_output(['xcrun', '--sdk', sdk, '-f', 'libtool']).strip() 240 self.linker = deploytarget + " " + self.ccompiler 241 self.lipo = "PATH=" + localpath + " " + subprocess.check_output(['xcrun', '--sdk', sdk, '-f', 'lipo']).strip() 242 243 self.mflags += list(self.cflags) + ['-fobjc-arc', '-fno-objc-exceptions', '-x', 'objective-c'] 244 self.cflags += ['-x', 'c'] 245 self.cxxflags += ['-x', 'c++'] 246 247 self.cmcmd = self.cccmd.replace('$cflags', '$mflags') 248 self.arcmd = self.rmcmd('$out') + ' && $ar $ararchflags $arflags $in -o $out' 249 self.lipocmd = '$lipo $in -create -output $out' 250 251 if self.target.is_macos(): 252 self.frameworks = ['Cocoa', 'CoreFoundation'] 253 if self.target.is_ios(): 254 self.frameworks = ['CoreGraphics', 'UIKit', 'Foundation'] 255 256 def make_includepaths(self, includepaths): 257 if not includepaths is None: 258 return ['-I' + path for path in list(includepaths)] 259 return [] 260 261 def make_libpath(self, path): 262 return self.path_escape(path) 263 264 def make_libpaths(self, libpaths): 265 if not libpaths is None: 266 if self.target.is_windows(): 267 return ['-Xlinker /LIBPATH:' + self.path_escape(path) for path in libpaths] 268 return ['-L' + self.make_libpath(path) for path in libpaths] 269 return [] 270 271 def make_targetarchflags(self, arch, targettype): 272 flags = [] 273 if self.target.is_android(): 274 if arch == 'x86': 275 flags += ['-target', 'i686-none-linux-android'] 276 flags += ['-march=i686', '-mtune=intel', '-mssse3', '-mfpmath=sse', '-m32'] 277 elif arch == 'x86-64': 278 flags += ['-target', 'x86_64-none-linux-android'] 279 flags += ['-march=x86-64', '-msse4.2', '-mpopcnt', '-m64', '-mtune=intel'] 280 elif arch == 'arm6': 281 flags += ['-target', 'armv5te-none-linux-androideabi'] 282 flags += ['-march=armv5te', '-mtune=xscale', '-msoft-float', '-marm'] 283 elif arch == 'arm7': 284 flags += ['-target', 'armv7-none-linux-androideabi'] 285 flags += ['-march=armv7-a', '-mhard-float', '-mfpu=vfpv3-d16', '-mfpu=neon', '-D_NDK_MATH_NO_SOFTFP=1', '-marm'] 286 elif arch == 'arm64': 287 flags += ['-target', 'aarch64-none-linux-android'] 288 elif arch == 'mips': 289 flags += ['-target', 'mipsel-none-linux-android'] 290 elif arch == 'mips64': 291 flags += ['-target', 'mips64el-none-linux-android'] 292 flags += ['-gcc-toolchain', self.android.make_gcc_toolchain_path(arch)] 293 elif self.target.is_macos() or self.target.is_ios(): 294 if arch == 'x86': 295 flags += [' -arch x86'] 296 elif arch == 'x86-64': 297 flags += [' -arch x86_64'] 298 elif arch == 'arm7': 299 flags += [' -arch armv7'] 300 elif arch == 'arm64': 301 flags += [' -arch arm64'] 302 else: 303 if arch == 'x86': 304 flags += ['-m32'] 305 elif arch == 'x86-64': 306 flags += ['-m64'] 307 return flags 308 309 def make_carchflags(self, arch, targettype): 310 flags = [] 311 if targettype == 'sharedlib': 312 flags += ['-DBUILD_DYNAMIC_LINK=1'] 313 if self.target.is_linux() or self.target.is_bsd(): 314 flags += ['-fPIC'] 315 flags += self.make_targetarchflags(arch, targettype) 316 return flags 317 318 def make_cconfigflags(self, config, targettype): 319 flags = [] 320 if config == 'debug': 321 flags += ['-DBUILD_DEBUG=1', '-g'] 322 elif config == 'release': 323 flags += ['-DBUILD_RELEASE=1', '-DNDEBUG', '-O3', '-g', '-funroll-loops'] 324 elif config == 'profile': 325 flags += ['-DBUILD_PROFILE=1', '-DNDEBUG', '-O3', '-g', '-funroll-loops'] 326 elif config == 'deploy': 327 flags += ['-DBUILD_DEPLOY=1', '-DNDEBUG', '-O3', '-g', '-funroll-loops'] 328 return flags 329 330 def make_ararchflags(self, arch, targettype): 331 flags = [] 332 return flags 333 334 def make_arconfigflags(self, config, targettype): 335 flags = [] 336 return flags 337 338 def make_linkarchflags(self, arch, targettype, variables): 339 flags = [] 340 flags += self.make_targetarchflags(arch, targettype) 341 if self.target.is_android(): 342 if arch == 'arm7': 343 flags += ['-Wl,--no-warn-mismatch', '-Wl,--fix-cortex-a8'] 344 if self.target.is_windows(): 345 if arch == 'x86': 346 flags += ['-Xlinker', '/MACHINE:X86'] 347 elif arch == 'x86-64': 348 flags += ['-Xlinker', '/MACHINE:X64'] 349 if self.target.is_macos() and variables != None and 'support_lua' in variables and variables['support_lua']: 350 flags += ['-pagezero_size', '10000', '-image_base', '100000000'] 351 return flags 352 353 def make_linkconfigflags(self, config, targettype, variables): 354 flags = [] 355 if self.target.is_windows(): 356 if targettype == 'sharedlib': 357 flags += ['-Xlinker', '/DLL'] 358 elif targettype == 'bin': 359 flags += ['-Xlinker', '/SUBSYSTEM:CONSOLE'] 360 elif self.target.is_macos() or self.target.is_ios(): 361 if targettype == 'sharedlib' or targettype == 'multisharedlib': 362 flags += ['-dynamiclib'] 363 else: 364 if targettype == 'sharedlib': 365 flags += ['-shared', '-fPIC'] 366 if config == 'release': 367 flags += ['-DNDEBUG', '-O3'] 368 return flags 369 370 def make_linkarchlibs(self, arch, targettype): 371 archlibs = [] 372 if self.target.is_android(): 373 if arch == 'arm7': 374 archlibs += ['m_hard'] 375 else: 376 archlibs += ['m'] 377 archlibs += ['gcc', 'android'] 378 return archlibs 379 380 def make_libs(self, libs): 381 if libs != None: 382 return ['-l' + lib for lib in libs] 383 return [] 384 385 def make_frameworks(self, frameworks): 386 if frameworks != None: 387 return ['-framework ' + framework for framework in frameworks] 388 return [] 389 390 def make_configlibpaths(self, config, arch, extralibpaths): 391 libpaths = [self.libpath, os.path.join(self.libpath, config)] 392 if not self.target.is_macos() and not self.target.is_ios(): 393 libpaths += [os.path.join(self.libpath, arch)] 394 libpaths += [os.path.join(self.libpath, config, arch)] 395 if extralibpaths != None: 396 libpaths += [os.path.join(libpath, self.libpath) for libpath in extralibpaths] 397 libpaths += [os.path.join(libpath, self.libpath, config) for libpath in extralibpaths] 398 if not self.target.is_macos() and not self.target.is_ios(): 399 libpaths += [os.path.join(libpath, self.libpath, arch) for libpath in extralibpaths] 400 libpaths += [os.path.join(libpath, self.libpath, config, arch) for libpath in extralibpaths] 401 return self.make_libpaths(libpaths) 402 403 def cc_variables(self, config, arch, targettype, variables): 404 localvariables = [] 405 if 'includepaths' in variables: 406 moreincludepaths = self.make_includepaths(variables['includepaths']) 407 if not moreincludepaths == []: 408 localvariables += [('moreincludepaths', moreincludepaths)] 409 carchflags = self.make_carchflags(arch, targettype) 410 if carchflags != []: 411 localvariables += [('carchflags', carchflags)] 412 cconfigflags = self.make_cconfigflags(config, targettype) 413 if cconfigflags != []: 414 localvariables += [('cconfigflags', cconfigflags)] 415 if self.target.is_android(): 416 localvariables += [('sysroot', self.android.make_sysroot_path(arch))] 417 if 'defines' in variables: 418 localvariables += [('cmoreflags', ['-D' + define for define in variables['defines']])] 419 return localvariables 420 421 def ar_variables(self, config, arch, targettype, variables): 422 localvariables = [] 423 ararchflags = self.make_ararchflags(arch, targettype) 424 if ararchflags != []: 425 localvariables += [('ararchflags', ararchflags)] 426 arconfigflags = self.make_arconfigflags(config, targettype) 427 if arconfigflags != []: 428 localvariables += [('arconfigflags', arconfigflags)] 429 if self.target.is_android(): 430 localvariables += [('toolchain', self.android.make_gcc_bin_path(arch))] 431 return localvariables 432 433 def link_variables(self, config, arch, targettype, variables): 434 if variables == None: 435 variables = {} 436 localvariables = [] 437 linkarchflags = self.make_linkarchflags(arch, targettype, variables) 438 if linkarchflags != []: 439 localvariables += [('linkarchflags', linkarchflags)] 440 linkconfigflags = self.make_linkconfigflags(config, targettype, variables) 441 if linkconfigflags != []: 442 localvariables += [('linkconfigflags', linkconfigflags)] 443 if 'libs' in variables: 444 libvar = self.make_libs(variables['libs']) 445 if libvar != []: 446 localvariables += [('libs', libvar)] 447 448 localframeworks = self.frameworks or [] 449 if 'frameworks' in variables and variables['frameworks'] != None: 450 localframeworks += list(variables['frameworks']) 451 if len(localframeworks) > 0: 452 localvariables += [('frameworks', self.make_frameworks(list(localframeworks)))] 453 454 libpaths = [] 455 if 'libpaths' in variables: 456 libpaths = variables['libpaths'] 457 localvariables += [('configlibpaths', self.make_configlibpaths(config, arch, libpaths))] 458 if self.target.is_android(): 459 localvariables += [('sysroot', self.android.make_sysroot_path(arch))] 460 archlibs = self.make_linkarchlibs(arch, targettype) 461 if archlibs != []: 462 localvariables += [('archlibs', self.make_libs(archlibs))] 463 464 if 'runtime' in variables and variables['runtime'] == 'c++': 465 localvariables += [('link', self.cxxlinker)] 466 467 return localvariables 468 469 def builder_cc(self, writer, config, arch, targettype, infile, outfile, variables): 470 return writer.build(outfile, 'cc', infile, implicit = self.implicit_deps(config, variables), variables = self.cc_variables(config, arch, targettype, variables)) 471 472 def builder_cxx(self, writer, config, arch, targettype, infile, outfile, variables): 473 return writer.build(outfile, 'cxx', infile, implicit = self.implicit_deps(config, variables), variables = self.cc_variables(config, arch, targettype, variables)) 474 475 def builder_cm(self, writer, config, arch, targettype, infile, outfile, variables): 476 return writer.build(outfile, 'cm', infile, implicit = self.implicit_deps(config, variables), variables = self.cc_variables(config, arch, targettype, variables)) 477 478 def builder_lib(self, writer, config, arch, targettype, infiles, outfile, variables): 479 return writer.build(outfile, 'ar', infiles, implicit = self.implicit_deps(config, variables), variables = self.ar_variables(config, arch, targettype, variables)) 480 481 def builder_sharedlib(self, writer, config, arch, targettype, infiles, outfile, variables): 482 return writer.build(outfile, 'so', infiles, implicit = self.implicit_deps(config, variables), variables = self.link_variables(config, arch, targettype, variables)) 483 484 def builder_bin(self, writer, config, arch, targettype, infiles, outfile, variables): 485 return writer.build(outfile, 'link', infiles, implicit = self.implicit_deps(config, variables), variables = self.link_variables(config, arch, targettype, variables)) 486 487 #Apple universal targets 488 def builder_apple_multilib(self, writer, config, arch, targettype, infiles, outfile, variables): 489 localvariables = [('arflags', '-static -no_warning_for_no_symbols')] 490 if variables != None: 491 localvariables = variables + localvariables 492 return writer.build(os.path.join(outfile, self.buildtarget), 'ar', infiles, variables = localvariables); 493 494 def builder_apple_multisharedlib(self, writer, config, arch, targettype, infiles, outfile, variables): 495 return writer.build(os.path.join(outfile, self.buildtarget), 'so', infiles, implicit = self.implicit_deps(config, variables), variables = self.link_variables(config, arch, targettype, variables)) 496 497 def builder_apple_multibin(self, writer, config, arch, targettype, infiles, outfile, variables): 498 return writer.build(os.path.join(outfile, self.buildtarget), 'lipo', infiles, variables = variables) 499 500def create(host, target, toolchain): 501 return ClangToolchain(host, target, toolchain) 502