Fix shared libs and using one source in multiple targets.

pull/8625/head
Jussi Pakkanen 4 years ago
parent 3b16e39009
commit 0b50c5705f
  1. 112
      mesonbuild/backend/xcodebackend.py

@ -189,6 +189,16 @@ class XCodeBackend(backends.Backend):
self.test_command_id = self.gen_id() self.test_command_id = self.gen_id()
self.test_buildconf_id = self.gen_id() self.test_buildconf_id = self.gen_id()
self.top_level_dict = PbxDict() self.top_level_dict = PbxDict()
# In Xcode files are not accessed via their file names, but rather every one of them
# gets an unique id. More precisely they get one unique id per target they are used
# in. If you generate only one id per file and use them, compilation will work but the
# UI will only show the file in one target but not the others. Thus they key is
# a tuple containing the target and filename.
self.buildfile_ids = {}
# That is not enough, though. Each target/file combination also gets a unique id
# in the file reference section. Because why not. This means that a source file
# that is used in two targets gets a total of four unique ID numbers.
self.fileref_ids = {}
def write_pbxfile(self, top_level_dict, ofilename): def write_pbxfile(self, top_level_dict, ofilename):
with open(ofilename, 'w') as ofile: with open(ofilename, 'w') as ofile:
@ -212,7 +222,6 @@ class XCodeBackend(backends.Backend):
def generate(self): def generate(self):
test_data = self.serialize_tests()[0] test_data = self.serialize_tests()[0]
self.generate_filemap() self.generate_filemap()
self.generate_buildmap()
self.generate_buildstylemap() self.generate_buildstylemap()
self.generate_build_phase_map() self.generate_build_phase_map()
self.generate_build_configuration_map() self.generate_build_configuration_map()
@ -226,6 +235,7 @@ class XCodeBackend(backends.Backend):
self.generate_target_dependency_map() self.generate_target_dependency_map()
self.generate_pbxdep_map() self.generate_pbxdep_map()
self.generate_containerproxy_map() self.generate_containerproxy_map()
self.generate_target_file_maps()
self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj') self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj')
os.makedirs(self.proj_dir, exist_ok=True) os.makedirs(self.proj_dir, exist_ok=True)
self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj') self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj')
@ -296,17 +306,6 @@ class XCodeBackend(backends.Backend):
self.filemap[o] = self.gen_id() self.filemap[o] = self.gen_id()
self.target_filemap[name] = self.gen_id() self.target_filemap[name] = self.gen_id()
def generate_buildmap(self):
self.buildmap = {}
for t in self.build.get_build_targets().values():
for s in t.sources:
s = os.path.join(s.subdir, s.fname)
self.buildmap[s] = self.gen_id()
for o in t.objects:
o = os.path.join(t.subdir, o)
if isinstance(o, str):
self.buildmap[o] = self.gen_id()
def generate_buildstylemap(self): def generate_buildstylemap(self):
self.buildstylemap = {self.buildtype: self.gen_id()} self.buildstylemap = {self.buildtype: self.gen_id()}
@ -371,6 +370,20 @@ class XCodeBackend(backends.Backend):
for t in self.build.get_build_targets(): for t in self.build.get_build_targets():
self.containerproxy_map[t] = self.gen_id() self.containerproxy_map[t] = self.gen_id()
def generate_target_file_maps(self):
for tname, t in self.build.get_build_targets().items():
for s in t.sources:
if isinstance(s, mesonlib.File):
s = os.path.join(s.subdir, s.fname)
if not isinstance(s, str):
continue
self.buildfile_ids[(tname, s)] = self.gen_id()
self.fileref_ids[(tname, s)] = self.gen_id()
for o in t.objects:
o = os.path.join(t.subdir, o)
self.buildfile_ids[(tname, o)] = self.gen_id()
self.fileref_ids[(tname, o)] = self.gen_id()
def generate_source_phase_map(self): def generate_source_phase_map(self):
self.source_phase = {} self.source_phase = {}
for t in self.build.get_build_targets(): for t in self.build.get_build_targets():
@ -404,7 +417,7 @@ class XCodeBackend(backends.Backend):
objects_dict.add_item(t[0], agt_dict, name) objects_dict.add_item(t[0], agt_dict, name)
def generate_pbx_build_file(self, objects_dict): def generate_pbx_build_file(self, objects_dict):
for t in self.build.get_build_targets().values(): for tname, t in self.build.get_build_targets().items():
for dep in t.get_external_deps(): for dep in t.get_external_deps():
if isinstance(dep, dependencies.AppleFrameworks): if isinstance(dep, dependencies.AppleFrameworks):
for f in dep.frameworks: for f in dep.frameworks:
@ -417,16 +430,16 @@ class XCodeBackend(backends.Backend):
if isinstance(s, mesonlib.File): if isinstance(s, mesonlib.File):
s = os.path.join(s.subdir, s.fname) s = os.path.join(s.subdir, s.fname)
if isinstance(s, str): if not isinstance(s, str):
continue
s = os.path.join(t.subdir, s) s = os.path.join(t.subdir, s)
sdict = PbxDict() sdict = PbxDict()
idval = self.buildmap[s] idval = self.buildfile_ids[(tname, s)]
fileref = self.fileref_ids[(tname, s)]
fullpath = os.path.join(self.environment.get_source_dir(), s) fullpath = os.path.join(self.environment.get_source_dir(), s)
fileref = self.filemap[s]
fullpath2 = fullpath
compiler_args = '' compiler_args = ''
sdict.add_item('isa', 'PBXBuildFile') sdict.add_item('isa', 'PBXBuildFile')
sdict.add_item('fileRef', fileref, fullpath2) sdict.add_item('fileRef', fileref, fullpath)
settingdict = PbxDict() settingdict = PbxDict()
settingdict.add_item('COMPILER_FLAGS', '"' + compiler_args + '"') settingdict.add_item('COMPILER_FLAGS', '"' + compiler_args + '"')
sdict.add_item('settings', settingdict) sdict.add_item('settings', settingdict)
@ -434,8 +447,9 @@ class XCodeBackend(backends.Backend):
for o in t.objects: for o in t.objects:
o = os.path.join(t.subdir, o) o = os.path.join(t.subdir, o)
idval = self.buildmap[o] idval = self.buildfile_ids[(tname, o)]
fileref = self.filemap[o] fileref = self.fileref_ids[(tname, s)]
self.targetfile_ids[(tname, s)] = idval
fullpath = os.path.join(self.environment.get_source_dir(), o) fullpath = os.path.join(self.environment.get_source_dir(), o)
fullpath2 = fullpath fullpath2 = fullpath
o_dict = PbxDict() o_dict = PbxDict()
@ -465,11 +479,10 @@ class XCodeBackend(backends.Backend):
proxy_dict.add_item('remoteInfo', '"' + t + '"') proxy_dict.add_item('remoteInfo', '"' + t + '"')
def generate_pbx_file_reference(self, objects_dict): def generate_pbx_file_reference(self, objects_dict):
for t in self.build.get_build_targets().values(): for tname, t in self.build.get_build_targets().items():
for dep in t.get_external_deps(): for dep in t.get_external_deps():
if isinstance(dep, dependencies.AppleFrameworks): if isinstance(dep, dependencies.AppleFrameworks):
for f in dep.frameworks: for f in dep.frameworks:
# FIXME not ported
fw_dict = PbxDict() fw_dict = PbxDict()
objects_dict.add_item(self.native_frameworks_fileref[f], fw_dict, f) objects_dict.add_item(self.native_frameworks_fileref[f], fw_dict, f)
fw_dict.add_item('isa', 'PBXFileReference') fw_dict.add_item('isa', 'PBXFileReference')
@ -477,12 +490,19 @@ class XCodeBackend(backends.Backend):
fw_dict.add_item('name', f'{f}.framework') fw_dict.add_item('name', f'{f}.framework')
fw_dict.add_item('path', f'System/Library/Frameworks/{f}.framework') fw_dict.add_item('path', f'System/Library/Frameworks/{f}.framework')
fw_dict.add_item('sourceTree', 'SDKROOT') fw_dict.add_item('sourceTree', 'SDKROOT')
for fname, idval in self.filemap.items(): for s in t.sources:
if isinstance(s, mesonlib.File):
s = os.path.join(s.subdir, s.fname)
if not isinstance(s, str):
continue
s = os.path.join(t.subdir, s)
idval = self.fileref_ids[(tname, s)]
fullpath = os.path.join(self.environment.get_source_dir(), s)
src_dict = PbxDict() src_dict = PbxDict()
fullpath = os.path.join(self.environment.get_source_dir(), fname) xcodetype = self.get_xcodetype(s)
xcodetype = self.get_xcodetype(fname) name = os.path.basename(s)
name = os.path.basename(fname) path = s
path = fname
objects_dict.add_item(idval, src_dict, fullpath) objects_dict.add_item(idval, src_dict, fullpath)
src_dict.add_item('isa', 'PBXFileReference') src_dict.add_item('isa', 'PBXFileReference')
src_dict.add_item('explicitFileType', '"' + xcodetype + '"') src_dict.add_item('explicitFileType', '"' + xcodetype + '"')
@ -490,6 +510,17 @@ class XCodeBackend(backends.Backend):
src_dict.add_item('name', '"' + name + '"') src_dict.add_item('name', '"' + name + '"')
src_dict.add_item('path', '"' + path + '"') src_dict.add_item('path', '"' + path + '"')
src_dict.add_item('sourceTree', 'SOURCE_ROOT') src_dict.add_item('sourceTree', 'SOURCE_ROOT')
for o in t.objects:
o = os.path.join(t.subdir, o)
idval = self.fileref_ids[(tname, o)]
fileref = self.filemap[o]
fullpath = os.path.join(self.environment.get_source_dir(), o)
fullpath2 = fullpath
o_dict = PbxDict()
objects_dict.add_item(idval, o_dict, fullpath)
o_dict.add_item('isa', 'PBXBuildFile')
o_dict.add_item('fileRef', fileref, fullpath2)
for tname, idval in self.target_filemap.items(): for tname, idval in self.target_filemap.items():
target_dict = PbxDict() target_dict = PbxDict()
objects_dict.add_item(idval, target_dict, tname) objects_dict.add_item(idval, target_dict, tname)
@ -557,7 +588,6 @@ class XCodeBackend(backends.Backend):
source_dict.add_item('name', 'Sources') source_dict.add_item('name', 'Sources')
source_dict.add_item('sourceTree', '"<group>"') source_dict.add_item('sourceTree', '"<group>"')
resource_dict = PbxDict() resource_dict = PbxDict()
objects_dict.add_item(resources_id, resource_dict, 'Resources') objects_dict.add_item(resources_id, resource_dict, 'Resources')
resource_dict.add_item('isa', 'PBXGroup') resource_dict.add_item('isa', 'PBXGroup')
@ -583,27 +613,29 @@ class XCodeBackend(backends.Backend):
frameworks_dict.add_item('sourceTree', '"<group>"') frameworks_dict.add_item('sourceTree', '"<group>"')
# Targets # Targets
for t in self.build.get_build_targets(): for tname, t in self.build.get_build_targets().items():
target_dict = PbxDict() target_dict = PbxDict()
objects_dict.add_item(groupmap[t], target_dict, t) objects_dict.add_item(groupmap[tname], target_dict, tname)
target_dict.add_item('isa', 'PBXGroup') target_dict.add_item('isa', 'PBXGroup')
target_children = PbxArray() target_children = PbxArray()
target_dict.add_item('children', target_children) target_dict.add_item('children', target_children)
target_children.add_item(target_src_map[t], 'Source files') target_children.add_item(target_src_map[tname], 'Source files')
target_dict.add_item('name', f'"{t}"') target_dict.add_item('name', f'"{t}"')
target_dict.add_item('sourceTree', '"<group>"') target_dict.add_item('sourceTree', '"<group>"')
source_files_dict = PbxDict() source_files_dict = PbxDict()
objects_dict.add_item(target_src_map[t], source_files_dict, 'Source files') objects_dict.add_item(target_src_map[tname], source_files_dict, 'Source files')
source_files_dict.add_item('isa', 'PBXGroup') source_files_dict.add_item('isa', 'PBXGroup')
source_file_children = PbxArray() source_file_children = PbxArray()
source_files_dict.add_item('children', source_file_children) source_files_dict.add_item('children', source_file_children)
for s in self.build.get_build_targets()[t].sources: for s in t.sources:
s = os.path.join(s.subdir, s.fname) if isinstance(s, mesonlib.File):
if isinstance(s, str): s = os.path.join(t.subdir, s.fname)
source_file_children.add_item(self.filemap[s], s) if not isinstance(s, str):
for o in self.build.get_build_targets()[t].objects: continue
o = os.path.join(self.build.get_build_targets()[t].subdir, o) source_file_children.add_item(self.fileref_ids[(tname, s)], s)
source_file_children.add_item(self.filemap[o], o) for o in t.objects:
o = os.path.join(t.subdir, o)
source_file_children.add_item(self.fileref_ids[(tname, o)], o)
source_files_dict.add_item('name', '"Source files"') source_files_dict.add_item('name', '"Source files"')
source_files_dict.add_item('sourceTree', '"<group>"') source_files_dict.add_item('sourceTree', '"<group>"')
@ -702,7 +734,7 @@ class XCodeBackend(backends.Backend):
for s in self.build.get_build_targets()[name].sources: for s in self.build.get_build_targets()[name].sources:
s = os.path.join(s.subdir, s.fname) s = os.path.join(s.subdir, s.fname)
if not self.environment.is_header(s): if not self.environment.is_header(s):
file_arr.add_item(self.buildmap[s], os.path.join(self.environment.get_source_dir(), s)) file_arr.add_item(self.buildfile_ids[(name, s)], os.path.join(self.environment.get_source_dir(), s))
phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0) phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
def generate_pbx_target_dependency(self, objects_dict): def generate_pbx_target_dependency(self, objects_dict):

Loading…
Cancel
Save