diff options
| author | Mykola Dolhyi <0xb000@gmail.com> | 2024-06-27 19:10:02 +0300 |
|---|---|---|
| committer | Mykola Dolhyi <0xb000@gmail.com> | 2024-06-27 19:22:29 +0300 |
| commit | 7516508547524c53d99178f26d2df5f0cd6e8396 (patch) | |
| tree | 16e5c09ebb11028c3c5dc9d3d10867308fbd492c /mesonbuild/backend/xcodebackend.py | |
| parent | 7b43a2e19613f3702935872b21b1020f7d8c6a9b (diff) | |
| download | meson-7516508547524c53d99178f26d2df5f0cd6e8396.tar.gz | |
Refactor duplicated quoting code for XCode backend
XCode project file contains dictionary-like structures. Strings for the
mapped values have to be quoted if these include special characters.
Previously this quoting was happening in-place, before adding a new
value to the dictionary. This produce big amounts of boilerplate
error-prone code. For example if there are targets whose names contain special
characters (grpc++ in my case), produced file will be invalid.
This moves checking and quoting subroutine to the PbxDictItem class,
eliminating the need to do this on the caller side.
[Kin](https://github.com/Serchinastico/Kin) tool was used to validate
produced PBXProj files.
Diffstat (limited to 'mesonbuild/backend/xcodebackend.py')
| -rw-r--r-- | mesonbuild/backend/xcodebackend.py | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 69a544b24..66d42b30a 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -138,7 +138,11 @@ class PbxComment: class PbxDictItem: def __init__(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = ''): self.key = key - self.value = value + if isinstance(value, str): + self.value = self.quote_value(value) + else: + self.value = value + if comment: if '/*' in comment: self.comment = comment @@ -147,6 +151,17 @@ class PbxDictItem: else: self.comment = comment + def quote_value(self, value: str) -> str: + quoted = f'"{value}"' + + if len(value) == 0: + return quoted + + if set(' +@').isdisjoint(value) or value[0] == '"': + return value + + return quoted + class PbxDict: def __init__(self) -> None: # This class is a bit weird, because we want to write PBX dicts in @@ -826,7 +841,7 @@ class XCodeBackend(backends.Backend): proxy_dict.add_item('containerPortal', self.project_uid, 'Project object') proxy_dict.add_item('proxyType', '1') proxy_dict.add_item('remoteGlobalIDString', self.native_targets[t]) - proxy_dict.add_item('remoteInfo', '"' + t + '"') + proxy_dict.add_item('remoteInfo', t) def generate_pbx_file_reference(self, objects_dict: PbxDict) -> None: for tname, t in self.build_targets.items(): @@ -859,17 +874,17 @@ class XCodeBackend(backends.Backend): path = s objects_dict.add_item(idval, src_dict, fullpath) src_dict.add_item('isa', 'PBXFileReference') - src_dict.add_item('explicitFileType', '"' + xcodetype + '"') + src_dict.add_item('explicitFileType', xcodetype) src_dict.add_item('fileEncoding', '4') if in_build_dir: - src_dict.add_item('name', '"' + name + '"') + src_dict.add_item('name', name) # This makes no sense. This should say path instead of name # but then the path gets added twice. - src_dict.add_item('path', '"' + name + '"') + src_dict.add_item('path', name) src_dict.add_item('sourceTree', 'BUILD_ROOT') else: - src_dict.add_item('name', '"' + name + '"') - src_dict.add_item('path', '"' + path + '"') + src_dict.add_item('name', name) + src_dict.add_item('path', path) src_dict.add_item('sourceTree', 'SOURCE_ROOT') generator_id = 0 @@ -886,7 +901,7 @@ class XCodeBackend(backends.Backend): xcodetype = self.get_xcodetype(o) rel_name = mesonlib.relpath(o, self.environment.get_source_dir()) odict.add_item('isa', 'PBXFileReference') - odict.add_item('explicitFileType', '"' + xcodetype + '"') + odict.add_item('explicitFileType', xcodetype) odict.add_item('fileEncoding', '4') odict.add_item('name', f'"{name}"') odict.add_item('path', f'"{rel_name}"') @@ -910,7 +925,7 @@ class XCodeBackend(backends.Backend): name = os.path.basename(o) objects_dict.add_item(idval, o_dict, fullpath) o_dict.add_item('isa', 'PBXFileReference') - o_dict.add_item('explicitFileType', '"' + self.get_xcodetype(o) + '"') + o_dict.add_item('explicitFileType', self.get_xcodetype(o)) o_dict.add_item('fileEncoding', '4') o_dict.add_item('name', f'"{name}"') o_dict.add_item('path', f'"{rel_name}"') @@ -929,9 +944,9 @@ class XCodeBackend(backends.Backend): path = e objects_dict.add_item(idval, e_dict, fullpath) e_dict.add_item('isa', 'PBXFileReference') - e_dict.add_item('explicitFileType', '"' + xcodetype + '"') - e_dict.add_item('name', '"' + name + '"') - e_dict.add_item('path', '"' + path + '"') + e_dict.add_item('explicitFileType', xcodetype) + e_dict.add_item('name', name) + e_dict.add_item('path', path) e_dict.add_item('sourceTree', 'SOURCE_ROOT') for tname, idval in self.target_filemap.items(): target_dict = PbxDict() @@ -949,11 +964,8 @@ class XCodeBackend(backends.Backend): typestr = self.get_xcodetype(fname) path = '"%s"' % t.get_filename() target_dict.add_item('isa', 'PBXFileReference') - target_dict.add_item('explicitFileType', '"' + typestr + '"') - if ' ' in path and path[0] != '"': - target_dict.add_item('path', f'"{path}"') - else: - target_dict.add_item('path', path) + target_dict.add_item('explicitFileType', typestr) + target_dict.add_item('path', path) target_dict.add_item('refType', reftype) target_dict.add_item('sourceTree', 'BUILT_PRODUCTS_DIR') @@ -971,7 +983,7 @@ class XCodeBackend(backends.Backend): custom_dict = PbxDict() typestr = self.get_xcodetype(s) custom_dict.add_item('isa', 'PBXFileReference') - custom_dict.add_item('explicitFileType', '"' + typestr + '"') + custom_dict.add_item('explicitFileType', typestr) custom_dict.add_item('name', f'"{s}"') custom_dict.add_item('path', f'"{s}"') custom_dict.add_item('refType', 0) @@ -981,7 +993,7 @@ class XCodeBackend(backends.Backend): custom_dict = PbxDict() typestr = self.get_xcodetype(o) custom_dict.add_item('isa', 'PBXFileReference') - custom_dict.add_item('explicitFileType', '"' + typestr + '"') + custom_dict.add_item('explicitFileType', typestr) custom_dict.add_item('name', o) custom_dict.add_item('path', f'"{os.path.join(self.src_to_build, o)}"') custom_dict.add_item('refType', 0) @@ -993,7 +1005,7 @@ class XCodeBackend(backends.Backend): buildfile_dict = PbxDict() typestr = self.get_xcodetype(buildfile) buildfile_dict.add_item('isa', 'PBXFileReference') - buildfile_dict.add_item('explicitFileType', '"' + typestr + '"') + buildfile_dict.add_item('explicitFileType', typestr) buildfile_dict.add_item('name', f'"{basename}"') buildfile_dict.add_item('path', f'"{buildfile}"') buildfile_dict.add_item('refType', 0) @@ -1277,8 +1289,8 @@ class XCodeBackend(backends.Backend): project_dict.add_item('compatibilityVersion', f'"{self.xcodeversion}"') project_dict.add_item('hasScannedForEncodings', 0) project_dict.add_item('mainGroup', self.maingroup_id) - project_dict.add_item('projectDirPath', '"' + self.environment.get_source_dir() + '"') - project_dict.add_item('projectRoot', '""') + project_dict.add_item('projectDirPath', self.environment.get_source_dir()) + project_dict.add_item('projectRoot', '') targets_arr = PbxArray() project_dict.add_item('targets', targets_arr) targets_arr.add_item(self.all_id, 'ALL_BUILD') @@ -1429,7 +1441,7 @@ class XCodeBackend(backends.Backend): else: q.append(c) quoted_cmds.append(' '.join(q)) - cmdstr = '"' + ' && '.join(quoted_cmds) + '"' + cmdstr = ' && '.join(quoted_cmds) gen_dict.add_item('shellScript', cmdstr) gen_dict.add_item('showEnvVarsInLog', 0) @@ -1799,7 +1811,7 @@ class XCodeBackend(backends.Backend): if ' ' in a or "'" in a: a = r'\"' + a + r'\"' quoted_args.append(a) - settings_dict.add_item(f'OTHER_{langname}FLAGS', '"' + ' '.join(quoted_args) + '"') + settings_dict.add_item(f'OTHER_{langname}FLAGS', ' '.join(quoted_args)) def generate_xc_configurationList(self, objects_dict: PbxDict) -> None: # FIXME: sort items |
