From b8581b7b67327e6d41078c5a4e620b4c7ff399d3 Mon Sep 17 00:00:00 2001 From: Guillermo Ignacio Enriquez Gutierrez Date: Thu, 20 Sep 2018 01:41:23 +0900 Subject: [PATCH 1/6] Fix test script to be able to run in local macos --- run_project_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run_project_tests.py b/run_project_tests.py index 27e588bfb..6003370d3 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -393,6 +393,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen def gather_tests(testdir: Path): tests = [t.name for t in testdir.glob('*')] + tests = [t for t in tests if t != '.DS_Store'] # Filter non-tests files (macOS Finder indexing files, etc) testlist = [(int(t.split()[0]), t) for t in tests] testlist.sort() tests = [testdir / t[1] for t in testlist] From 13c0705263569dadc23443052b4d51e156cbe9cc Mon Sep 17 00:00:00 2001 From: Guillermo Ignacio Enriquez Gutierrez Date: Sun, 23 Sep 2018 00:42:33 +0900 Subject: [PATCH 2/6] Add flag to NOT use new build system in xcode because it fails in Xcode9 when using custom build directories --- run_tests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/run_tests.py b/run_tests.py index a5fd7a5fd..2a078ef96 100755 --- a/run_tests.py +++ b/run_tests.py @@ -143,7 +143,9 @@ def get_backend_commands(backend, debug=False): test_cmd = cmd + ['RUN_TESTS.vcxproj'] elif backend is Backend.xcode: cmd = ['xcodebuild'] - clean_cmd = cmd + ['-alltargets', 'clean'] + # In Xcode9 new build system's clean command fails when using a custom build directory. + # Maybe use it when CI uses Xcode10 we can remove '-UseNewBuildSystem=FALSE' + clean_cmd = cmd + ['-alltargets', 'clean', '-UseNewBuildSystem=FALSE'] test_cmd = cmd + ['-target', 'RUN_TESTS'] elif backend is Backend.ninja: # We need at least 1.6 because of -w dupbuild=err From f482b82a430e60aabca7bd6db0d7cdb20bf7db49 Mon Sep 17 00:00:00 2001 From: Guillermo Ignacio Enriquez Gutierrez Date: Sun, 23 Sep 2018 02:48:44 +0900 Subject: [PATCH 3/6] Sort some objects before writing as Xcode expects [skip ci] --- mesonbuild/backend/xcodebackend.py | 83 ++++++++++++++++-------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index b930c7f1c..8c85df92c 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -16,7 +16,7 @@ from . import backends from .. import build from .. import dependencies from .. import mesonlib -import uuid, os +import uuid, os, operator from ..mesonlib import MesonException @@ -202,38 +202,38 @@ class XCodeBackend(backends.Backend): self.source_phase[t] = self.gen_id() def generate_pbx_aggregate_target(self): + target_dependencies = list(map(lambda t: self.pbx_dep_map[t], self.build.targets)) + aggregated_targets = [] + aggregated_targets.append((self.all_id, 'ALL_BUILD', self.all_buildconf_id, [], target_dependencies)) + aggregated_targets.append((self.test_id, 'RUN_TESTS', self.test_buildconf_id, [self.test_command_id], [])) + # Sort objects by ID before writing + sorted_aggregated_targets = sorted(aggregated_targets, key=operator.itemgetter(0)) self.ofile.write('\n/* Begin PBXAggregateTarget section */\n') - self.write_line('%s /* ALL_BUILD */ = {' % self.all_id) - self.indent_level += 1 - self.write_line('isa = PBXAggregateTarget;') - self.write_line('buildConfigurationList = %s /* Build configuration list for PBXAggregateTarget "ALL_BUILD" */;' % self.all_buildconf_id) - self.write_line('buildPhases = (') - self.write_line(');') - self.write_line('dependencies = (') - self.indent_level += 1 - for t in self.build.targets: - self.write_line('%s /* PBXTargetDependency */,' % self.pbx_dep_map[t]) - self.indent_level -= 1 - self.write_line(');') - self.write_line('name = ALL_BUILD;') - self.write_line('productName = ALL_BUILD;') - self.indent_level -= 1 - self.write_line('};') - self.write_line('%s /* RUN_TESTS */ = {' % self.test_id) - self.indent_level += 1 - self.write_line('isa = PBXAggregateTarget;') - self.write_line('buildConfigurationList = %s /* Build configuration list for PBXAggregateTarget "RUN_TESTS" */;' % self.test_buildconf_id) - self.write_line('buildPhases = (') - self.indent_level += 1 - self.write_line('%s /* ShellScript */,' % self.test_command_id) - self.indent_level -= 1 - self.write_line(');') - self.write_line('dependencies = (') - self.write_line(');') - self.write_line('name = RUN_TESTS;') - self.write_line('productName = RUN_TESTS;') - self.indent_level -= 1 - self.write_line('};') + for t in sorted_aggregated_targets: + name = t[1] + buildconf_id = t[2] + build_phases = t[3] + dependencies = t[4] + self.write_line('%s /* %s */ = {' % (t[0], name)) + self.indent_level += 1 + self.write_line('isa = PBXAggregateTarget;') + self.write_line('buildConfigurationList = %s /* Build configuration list for PBXAggregateTarget "%s" */;' % (buildconf_id, name)) + self.write_line('buildPhases = (') + self.indent_level += 1 + for bp in build_phases: + self.write_line('%s /* ShellScript */,' % bp) + self.indent_level -= 1 + self.write_line(');') + self.write_line('dependencies = (') + self.indent_level += 1 + for td in dependencies: + self.write_line('%s /* PBXTargetDependency */,' % td) + self.indent_level -= 1 + self.write_line(');') + self.write_line('name = %s;' % name) + self.write_line('productName = %s;' % name) + self.indent_level -= 1 + self.write_line('};') self.ofile.write('/* End PBXAggregateTarget section */\n') def generate_pbx_build_file(self): @@ -594,14 +594,20 @@ class XCodeBackend(backends.Backend): self.ofile.write('/* End PBXSourcesBuildPhase section */\n') def generate_pbx_target_dependency(self): - self.ofile.write('\n/* Begin PBXTargetDependency section */\n') + targets = [] for t in self.build.targets: idval = self.pbx_dep_map[t] # VERIFY: is this correct? - self.write_line('%s /* PBXTargetDependency */ = {' % idval) + targets.append((idval, self.native_targets[t], t, self.containerproxy_map[t])) + + # Sort object by ID + sorted_targets = sorted(targets, key=operator.itemgetter(0)) + self.ofile.write('\n/* Begin PBXTargetDependency section */\n') + for t in sorted_targets: + self.write_line('%s /* PBXTargetDependency */ = {' % t[0]) self.indent_level += 1 self.write_line('isa = PBXTargetDependency;') - self.write_line('target = %s /* %s */;' % (self.native_targets[t], t)) - self.write_line('targetProxy = %s /* PBXContainerItemProxy */;' % self.containerproxy_map[t]) + self.write_line('target = %s /* %s */;' % (t[1], t[2])) + self.write_line('targetProxy = %s /* PBXContainerItemProxy */;' % t[3]) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXTargetDependency section */\n') @@ -764,12 +770,13 @@ class XCodeBackend(backends.Backend): self.write_build_setting_line('WARNING_CFLAGS', ['-Wmost', '-Wno-four-char-constants', '-Wno-unknown-pragmas']) self.indent_level -= 1 self.write_line('};') - self.write_line('name = "%s";' % buildtype) + self.write_line('name = %s;' % buildtype) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End XCBuildConfiguration section */\n') def generate_xc_configurationList(self): + # FIXME: sort items self.ofile.write('\n/* Begin XCConfigurationList section */\n') self.write_line('%s /* Build configuration list for PBXProject "%s" */ = {' % (self.project_conflist, self.build.project_name)) self.indent_level += 1 @@ -828,7 +835,7 @@ class XCodeBackend(backends.Backend): self.indent_level -= 1 self.write_line(');') self.write_line('defaultConfigurationIsVisible = 0;') - self.write_line('defaultConfigurationName = "%s";' % typestr) + self.write_line('defaultConfigurationName = %s;' % typestr) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End XCConfigurationList section */\n') From 9b7bb4aa92bc292230294929d35f3617cc48b0bf Mon Sep 17 00:00:00 2001 From: Guillermo Ignacio Enriquez Gutierrez Date: Mon, 24 Sep 2018 02:17:04 +0900 Subject: [PATCH 4/6] Partially fix targets that use precompiled header with --backend=xcode. Various compiled headers are not working yet [skip ci] --- mesonbuild/backend/xcodebackend.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 8c85df92c..42f44cf3d 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -60,6 +60,12 @@ class XCodeBackend(backends.Backend): os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname + def target_to_build_root(self, target): + if self.get_target_dir(target) == '': + return '' + directories = os.path.normpath(self.get_target_dir(target)).split(os.sep) + return os.sep.join(['..'] * len(directories)) + def write_line(self, text): self.ofile.write(self.indent * self.indent_level + text) if not text.endswith('\n'): @@ -749,6 +755,15 @@ class XCodeBackend(backends.Backend): self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = YES;') self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') + if target.has_pch: + # FIXME: GCC_PREFIX_HEADER accepts only one file so temporary we get the pch for the first language available and apply it to the entire target + # If more than pch are found we should add a compiler flag per each file + pch_headers = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp') + # Find path relative to target so we can use "$(PROJECT_DIR)" + relative_pch_path = os.path.join(self.get_target_dir(target), pch_headers[0]) + if relative_pch_path: + self.write_line('GCC_PRECOMPILE_PREFIX_HEADER = YES;') + self.write_line('GCC_PREFIX_HEADER = "$(PROJECT_DIR)/%s";' % relative_pch_path) self.write_line('GCC_PREPROCESSOR_DEFINITIONS = "";') self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') if len(headerdirs) > 0: From 6f4ba8b2f44d9cca0c2955cd0df74ef33efc339a Mon Sep 17 00:00:00 2001 From: Guillermo Ignacio Enriquez Gutierrez Date: Tue, 25 Sep 2018 01:11:46 +0900 Subject: [PATCH 5/6] Fix Xcode backend: support for precompiled headers. Only one header per target is supported --- mesonbuild/backend/xcodebackend.py | 17 +++++++++++------ test cases/common/13 pch/meson.build | 7 ++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 42f44cf3d..b0fcfa4c3 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -16,6 +16,7 @@ from . import backends from .. import build from .. import dependencies from .. import mesonlib +from .. import mlog import uuid, os, operator from ..mesonlib import MesonException @@ -756,12 +757,16 @@ class XCodeBackend(backends.Backend): self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') if target.has_pch: - # FIXME: GCC_PREFIX_HEADER accepts only one file so temporary we get the pch for the first language available and apply it to the entire target - # If more than pch are found we should add a compiler flag per each file - pch_headers = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp') - # Find path relative to target so we can use "$(PROJECT_DIR)" - relative_pch_path = os.path.join(self.get_target_dir(target), pch_headers[0]) - if relative_pch_path: + # Xcode uses GCC_PREFIX_HEADER which only allows one file per target/executable. Precompiling various header files and + # applying a particular pch to each source file will require custom scripts (as a build phase) and build flags per each + # file. Since Xcode itself already discourages precompiled headers in favor of modules we don't try much harder here. + pchs = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp') + # Make sure to use headers (other backends require implementation files like *.c *.cpp, etc; these should not be used here) + pchs = [pch for pch in pchs if pch.endswith('.h') or pch.endswith('.hh') or pch.endswith('hpp')] + if pchs: + if len(pchs) > 1: + mlog.warning('Unsupported Xcode configuration: More than 1 precompiled header found "%s". Target "%s" might not compile correctly.' % (str(pchs), target.name)) + relative_pch_path = os.path.join(target.get_subdir(), pchs[0]) # Path relative to target so it can be used with "$(PROJECT_DIR)" self.write_line('GCC_PRECOMPILE_PREFIX_HEADER = YES;') self.write_line('GCC_PREFIX_HEADER = "$(PROJECT_DIR)/%s";' % relative_pch_path) self.write_line('GCC_PREPROCESSOR_DEFINITIONS = "";') diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build index 05b40370b..d39527b7b 100644 --- a/test cases/common/13 pch/meson.build +++ b/test cases/common/13 pch/meson.build @@ -2,4 +2,9 @@ project('pch test', 'c', 'cpp') subdir('c') subdir('cpp') -subdir('mixed') + +if meson.backend() == 'xcode' + warning('Xcode backend only supports one precompiled header per target. Skipping "mixed" which has various precompiled headers.') +else + subdir('mixed') +endif From 5262aac977c899fac0c24e9c8e0185b9dc28ada8 Mon Sep 17 00:00:00 2001 From: Guillermo Ignacio Enriquez Gutierrez Date: Tue, 25 Sep 2018 01:14:48 +0900 Subject: [PATCH 6/6] Skip all dot files/directories when running tests --- run_project_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_project_tests.py b/run_project_tests.py index 6003370d3..ba7b5e088 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -393,7 +393,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen def gather_tests(testdir: Path): tests = [t.name for t in testdir.glob('*')] - tests = [t for t in tests if t != '.DS_Store'] # Filter non-tests files (macOS Finder indexing files, etc) + tests = [t for t in tests if not t.startswith('.')] # Filter non-tests files (dot files, etc) testlist = [(int(t.split()[0]), t) for t in tests] testlist.sort() tests = [testdir / t[1] for t in testlist]