Skip to content

Commit 8cfa63f

Browse files
Appleclang (WIP) (#222)
* untangle clang and appleclang
1 parent d29fe57 commit 8cfa63f

File tree

6 files changed

+79
-37
lines changed

6 files changed

+79
-37
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,3 +671,5 @@ venv/
671671
# single dist/index.js file and commit THAT instead.
672672
node_modules/
673673
!.github/actions/check-submodules/dist/
674+
675+
.DS_Store

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Usage: ```builder.pyz [build|inspect|<action-name>] [spec] [OPTIONS]```
3131
* ```--cmake-extra``` - Extra cmake config arg applied to all projects. e.g ```--cmake-extra=-DBUILD_SHARED_LIBS=ON```. May be specified multiple times.
3232
* ```--coverage``` - Generate the test coverage report and upload it to codecov. Only supported when using cmake and gcc as compiler, error out on other cases. Use `--coverage-include` and `--coverage-exclude` to report the needed coverage file. The default code coverage report will include everything in the `source/` directory
3333
* ```--coverage-include``` - The relative (based on the project directory) path of files and folders to include in the test coverage report. May be specified multiple times.
34-
* ```--coverage-exclude``` - The relative (based on the project directory) path of files and folders to exclude in the test coverage report. May be specified multiple times. Note: the include can override the exlucde path.
34+
* ```--coverage-exclude``` - The relative (based on the project directory) path of files and folders to exclude in the test coverage report. May be specified multiple times. Note: the include can override the exclude path.
3535

3636
### Supported Targets:
3737
* linux: x86|i686, x64|x86_64, armv6, armv7, arm64|armv8|aarch64|arm64v8
@@ -52,7 +52,7 @@ work.
5252

5353
### Configuration (builder.json)
5454
Each project has a configuration file: builder.json in the root of the project. It may also have a .builder folder which contains python
55-
scripts that will be automatically loaded when the project is found by the builder. Both of these are techncially optional, if the builder
55+
scripts that will be automatically loaded when the project is found by the builder. Both of these are technically optional, if the builder
5656
finds something that looks like a git repo full of code in a directory with the same name as the project it is searching for, it will use
5757
that instead. There are a few external dependencies (s2n and libcrypto, for instance) which are configured by scripts embedded in builder
5858
(see imports/).
@@ -78,7 +78,7 @@ See builder/data.py for more info/defaults/possible values.
7878
// Whether or not this project needs a C/C++ compiler
7979
"needs_compiler": true,
8080

81-
// Variables for use in interpolation throughout the config. Note that these can be overriden
81+
// Variables for use in interpolation throughout the config. Note that these can be overridden
8282
// per host/os/target/architecture/compiler/version (see below)
8383
// Variables can be references in braces: e.g. {my_variable}
8484
//

builder/core/data.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -478,9 +478,22 @@ class PKG_TOOLS(Enum):
478478
'default': {}
479479
}
480480
},
481+
'appleclang': {
482+
'hosts': ['macos'],
483+
'targets': ['macos', 'ios', 'tvos', 'watchos'],
484+
485+
'versions': {
486+
'default': {},
487+
488+
'11': {},
489+
'12': {},
490+
'13': {},
491+
'14': {},
492+
},
493+
},
481494
'clang': {
482-
'hosts': ['linux', 'macos', 'openbsd'],
483-
'targets': ['linux', 'macos', 'openbsd', 'ios', 'tvos', 'watchos'],
495+
'hosts': ['linux', 'openbsd'],
496+
'targets': ['linux', 'openbsd'],
484497

485498
'imports': ['llvm'],
486499

@@ -514,17 +527,13 @@ class PKG_TOOLS(Enum):
514527
'cmake_args': ['-DENABLE_FUZZ_TESTS=ON'],
515528
'apt_compiler_packages': ['libstdc++-9-dev'],
516529
},
517-
# 10 and 11 are XCode Apple clang/LLVM
518-
'10': {
519-
'!cmake_args': [],
520-
},
521-
'11': {
522-
'!cmake_args': [],
523-
},
530+
'10': {},
531+
'11': {},
524532
'12': {},
525533
'13': {},
526534
'14': {},
527-
'15': {}
535+
'15': {},
536+
'16': {}
528537
},
529538
'architectures': {
530539
# No fuzz tests on ARM

builder/core/spec.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# SPDX-License-Identifier: Apache-2.0.
33

44
import os
5-
import sys
65

76
from builder.core.data import *
87
from builder.core.host import current_host, current_os, current_arch, normalize_arch
@@ -89,3 +88,14 @@ def __str__(self):
8988

9089
def __repr__(self):
9190
return self.name
91+
92+
def update_compiler(self, compiler, compiler_version):
93+
self.compiler = compiler
94+
self.compiler_version = compiler_version
95+
96+
self.name = '-'.join([self.host, self.compiler,
97+
self.compiler_version, self.target, self.arch])
98+
if self.downstream:
99+
self.name += "-downstream"
100+
101+
validate_spec(self)

builder/core/toolchain.py

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def _compiler_version(cc):
1919
# Apple clang
2020
m = re.match('Apple (LLVM|clang) version (\d+)', text)
2121
if m:
22-
return 'clang', m.group(2)
22+
return 'appleclang', m.group(2)
2323
# LLVM clang
2424
m = re.match('.*(LLVM|clang) version (\d+)', text)
2525
if m:
@@ -59,6 +59,14 @@ def _clang_versions():
5959
return versions
6060

6161

62+
def _appleclang_versions():
63+
versions = [v for v in COMPILERS['appleclang']
64+
['versions'].keys() if v != 'default']
65+
versions.sort()
66+
versions.reverse()
67+
return versions
68+
69+
6270
def _gcc_versions():
6371
versions = [v for v in COMPILERS['gcc']
6472
['versions'].keys() if v != 'default']
@@ -150,7 +158,7 @@ def cxx_compiler_path(self):
150158
compiler = self.compiler
151159
if self.compiler == 'default':
152160
compiler = Toolchain.default_compiler()[0]
153-
if compiler == 'clang':
161+
if compiler == 'clang' or compiler == 'appleclang':
154162
return Toolchain.find_compiler_tool(compiler, 'clang++', self.compiler_version)[0]
155163
elif compiler == 'gcc':
156164
return Toolchain.find_compiler_tool(compiler, 'g++', self.compiler_version)[0]
@@ -176,6 +184,14 @@ def find_llvm_tool(name, version=None):
176184
versions = [version] if version else _clang_versions()
177185
return _find_compiler_tool(name, versions)
178186

187+
@staticmethod
188+
def find_apple_llvm_compiler(name, version=None):
189+
""" Finds apple versions of clang compilers at a specific version, or the latest one available.
190+
Note: apple does not ship tools like clang-tidy, so if installed
191+
those will follow regular llvm versioning """
192+
versions = [version] if version else _appleclang_versions()
193+
return _find_compiler_tool(name, versions)
194+
179195
@staticmethod
180196
def find_msvc(version=None):
181197
""" Finds MSVC at a specific version, or the latest one available """
@@ -214,7 +230,12 @@ def _find_msvc(version, install_vswhere=True):
214230
def find_compiler(compiler, version=None):
215231
""" Returns path, found_version for the requested compiler if it is installed """
216232
if compiler == 'clang':
217-
return Toolchain.find_llvm_tool(compiler, version)
233+
if current_os() == "macos":
234+
return Toolchain.find_apple_llvm_compiler(compiler, version)
235+
else:
236+
return Toolchain.find_llvm_tool(compiler, version)
237+
elif compiler == 'appleclang':
238+
return Toolchain.find_apple_llvm_compiler('clang', version)
218239
elif compiler == 'gcc':
219240
return Toolchain.find_gcc_tool(compiler, version)
220241
elif compiler == 'msvc':
@@ -226,20 +247,13 @@ def find_compiler_tool(compiler, tool, version=None):
226247
""" Returns path, found_version for the requested tool if it is installed """
227248
if compiler == 'clang':
228249
return Toolchain.find_llvm_tool(tool, version)
250+
elif compiler == 'appleclang':
251+
return Toolchain.find_apple_llvm_compiler(tool, version)
229252
elif compiler == 'gcc':
230253
return Toolchain.find_gcc_tool(tool, version)
231254

232255
return None, None
233256

234-
@staticmethod
235-
def compiler_packages(compiler, version):
236-
""" Returns a list of packages required to use the requested compiler """
237-
compiler_config = COMPILERS.get(compiler, {}).get(
238-
'versions', {}).get(version, None)
239-
if compiler_config:
240-
return compiler_config.get('packages', [])
241-
return []
242-
243257
@staticmethod
244258
def all_compilers():
245259
""" Returns a list of tuples of all available (compiler, version) """
@@ -248,10 +262,13 @@ def all_compilers():
248262
path, _version = Toolchain.find_gcc_tool('gcc', version)
249263
if path:
250264
compilers.append(('gcc', version))
251-
for version in _clang_versions():
265+
266+
is_mac = current_os() == "macos"
267+
versions = _appleclang_versions() if is_mac else _clang_versions()
268+
for version in versions:
252269
path, _version = Toolchain.find_llvm_tool('clang', version)
253270
if path:
254-
compilers.append(('clang', version))
271+
compilers.append(('appleclang' if is_mac else 'clang', version))
255272
if current_os() == 'windows':
256273
for version in _msvc_versions():
257274
path, _version = Toolchain.find_msvc(version)
@@ -275,7 +292,11 @@ def _find_compiler():
275292
compiler = None
276293
version = None
277294
platform = current_os()
278-
if platform != 'windows':
295+
296+
if platform == 'windows':
297+
compiler = 'msvc'
298+
version = Toolchain.find_msvc()[1]
299+
else:
279300
# resolve CC and /usr/bin/cc
280301
for env_cc in (util.where(os.environ.get('CC', None)), util.where('cc')):
281302
if env_cc:
@@ -284,8 +305,8 @@ def _find_compiler():
284305
return cc, ccver
285306

286307
# Try to find clang or gcc
287-
clang_path, clang_version = Toolchain.find_llvm_tool(
288-
'clang')
308+
clang_path, clang_version = Toolchain.find_llvm_tool('clang')
309+
print(clang_path)
289310
gcc_path, gcc_version = Toolchain.find_gcc_tool('gcc')
290311
if clang_path:
291312
compiler = 'clang'
@@ -297,9 +318,6 @@ def _find_compiler():
297318
print(
298319
'Neither GCC or Clang could be found on this system, perhaps not installed yet?')
299320

300-
else:
301-
compiler = 'msvc'
302-
version = Toolchain.find_msvc()[1]
303321
if not compiler or not version:
304322
print('WARNING: Default compiler could not be found')
305323

builder/main.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,12 @@ def main():
294294
print('No project specified and no project found in current directory')
295295
sys.exit(1)
296296

297+
if env.config.get('needs_compiler', True):
298+
env.toolchain = Toolchain(spec=env.spec)
299+
env.spec.update_compiler(env.toolchain.compiler, env.toolchain.compiler_version)
300+
if env.spec.compiler == 'default' or env.spec.compiler_version == 'default':
301+
raise Exception("Failed to resolve default compiler. None installed?")
302+
297303
print('Using Spec:')
298304
print(' Host: {} {}'.format(spec.host, current_arch()))
299305
print(' Target: {} {}'.format(spec.target, spec.arch))
@@ -302,9 +308,6 @@ def main():
302308
if not env.config.get('enabled', True):
303309
raise Exception("The project is disabled in this configuration")
304310

305-
if env.config.get('needs_compiler', True):
306-
env.toolchain = Toolchain(spec=env.spec)
307-
308311
if args.dump_config:
309312
from pprint import pprint
310313
print('Spec: ', end='')

0 commit comments

Comments
 (0)