aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2021-04-11 16:12:56 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2021-04-11 16:12:56 +0300
commit60cf80c844d26121c86c1d9da0062f7e2495bd6a (patch)
treeb5f6597a06814733702021f0576a3de9457fc5e6
parentcdafd2b9b450d510ef6822024fc166c87e1f2906 (diff)
downloadmeson-ongoingxcode.zip
meson-ongoingxcode.tar.gz
meson-ongoingxcode.tar.bz2
Xcode: can generate object files with generators.ongoingxcode
-rw-r--r--mesonbuild/backend/xcodebackend.py84
1 files changed, 84 insertions, 0 deletions
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py
index 2bd6acf..d94ffde 100644
--- a/mesonbuild/backend/xcodebackend.py
+++ b/mesonbuild/backend/xcodebackend.py
@@ -189,6 +189,7 @@ class XCodeBackend(backends.Backend):
self.test_command_id = self.gen_id()
self.test_buildconf_id = self.gen_id()
self.top_level_dict = PbxDict()
+ self.generator_outputs = {}
# 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
@@ -252,6 +253,7 @@ class XCodeBackend(backends.Backend):
self.generate_native_target_map()
self.generate_native_frameworks_map()
self.generate_custom_target_map()
+ self.generate_generator_target_map()
self.generate_source_phase_map()
self.generate_target_dependency_map()
self.generate_pbxdep_map()
@@ -378,6 +380,17 @@ class XCodeBackend(backends.Backend):
self.custom_target_output_buildfile[o] = self.gen_id()
self.custom_target_output_fileref[o] = self.gen_id()
+ def generate_generator_target_map(self):
+ # Generator objects do not have natural unique ids
+ # so use a counter.
+ for tname, t in self.build_targets.items():
+ generator_id = 0
+ for s in t.generated:
+ if isinstance(s, build.GeneratedList):
+ self.shell_targets[(tname, generator_id)] = self.gen_id()
+ generator_id += 1
+ # FIXME add outputs.
+
def generate_native_frameworks_map(self):
self.native_frameworks = {}
self.native_frameworks_fileref = {}
@@ -745,9 +758,13 @@ class XCodeBackend(backends.Backend):
ntarget_dict.add_item('buildConfigurationList', self.buildconflistmap[tname], f'Build configuration list for PBXNativeTarget "{tname}"')
buildphases_array = PbxArray()
ntarget_dict.add_item('buildPhases', buildphases_array)
+ generator_id = 0
for g in t.generated:
if isinstance(g, build.CustomTarget):
buildphases_array.add_item(self.shell_targets[g.get_id()], f'/* {g.name} */')
+ elif isinstance(g, build.GeneratedList):
+ buildphases_array.add_item(self.shell_targets[(tname, generator_id)], 'Generator {}/{}'.format(generator_id, tname))
+ generator_id += 1
for bpname, bpval in t.buildphasemap.items():
buildphases_array.add_item(bpval, f'{bpname} yyy')
ntarget_dict.add_item('buildRules', PbxArray())
@@ -819,6 +836,10 @@ class XCodeBackend(backends.Backend):
cmdstr = ' '.join(["'%s'" % i for i in cmd])
shell_dict.add_item('shellScript', f'"{cmdstr}"')
shell_dict.add_item('showEnvVarsInLog', 0)
+ self.generate_custom_target_shell_build_phases(objects_dict)
+ self.generate_generator_target_shell_build_phases(objects_dict)
+
+ def generate_custom_target_shell_build_phases(self, objects_dict):
# Custom targets are shell build phases in Xcode terminology.
for tname, t in self.custom_targets.items():
if not isinstance(t, build.CustomTarget):
@@ -842,6 +863,61 @@ class XCodeBackend(backends.Backend):
custom_dict.add_item('shellScript', f'"cd {workdir}; {cmdstr}"')
custom_dict.add_item('showEnvVarsInLog', 0)
+ def generate_generator_target_shell_build_phases(self, objects_dict):
+ for tname, t in self.build_targets.items():
+ generator_id = 0
+ for genlist in t.generated:
+ if isinstance(genlist, build.GeneratedList):
+ generator = genlist.get_generator()
+ exe = generator.get_exe()
+ exe_arr = self.build_target_to_cmd_array(exe)
+ self.shell_targets[(tname, id)] = self.gen_id()
+ workdir = self.environment.get_build_dir()
+ gen_dict = PbxDict()
+ objects_dict.add_item(self.shell_targets[(tname, generator_id)], gen_dict, '"Generator {}/{}"'.format(generator_id, tname))
+ infilelist = genlist.get_inputs()
+ outfilelist = genlist.get_outputs()
+ gen_dict.add_item('isa', 'PBXShellScriptBuildPhase')
+ gen_dict.add_item('buildActionMask', 2147483647)
+ gen_dict.add_item('files', PbxArray())
+ gen_dict.add_item('inputPaths', PbxArray())
+ outarray = PbxArray()
+ gen_dict.add_item('name', '"Generator {}/{}"'.format(generator_id, tname))
+ gen_dict.add_item('outputPaths', outarray)
+ ofilenames = []
+ infiles_abs = []
+ commands = [["cd", workdir]] # Array of arrays, each one a single command, will get concatenated below.
+ ofile_abs = []
+ for i in infilelist:
+ infiles_abs = i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) # FIXME, make it handle other input types.
+ infilename = i.rel_to_builddir(self.build_to_src)
+ base_args = generator.get_arglist(infilename)
+ for o_base in genlist.get_outputs_for(i):
+ o = os.path.join(self.get_target_private_dir(t), o_base)
+ ofile_abs.append(os.path.join(self.environment.get_build_dir(), o))
+ args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', o) for x in base_args]
+ args = self.replace_outputs(args, self.get_target_private_dir(t), outfilelist)
+ commands.append(exe_arr + args)
+ for of in ofile_abs:
+ outarray.add_item(of)
+ self.generator_outputs[(tname, generator_id)] = ofile_abs
+ gen_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
+ gen_dict.add_item('shellPath', '/bin/sh')
+ quoted_cmds = []
+ for cmnd in commands:
+ q = []
+ for c in cmnd:
+ if ' ' in c:
+ q.append(f'\\"{c}\\"')
+ else:
+ q.append(c)
+ quoted_cmds.append(' '.join(q))
+ cmdstr = '"' + ' && '.join(quoted_cmds) + '"'
+ gen_dict.add_item('shellScript', cmdstr)
+ gen_dict.add_item('showEnvVarsInLog', 0)
+ generator_id += 1
+
+
def generate_pbx_sources_build_phase(self, objects_dict):
for name in self.source_phase.keys():
phase_dict = PbxDict()
@@ -1002,6 +1078,14 @@ class XCodeBackend(backends.Backend):
if objname_abs not in added_objs:
added_objs.add(objname_abs)
ldargs += [r'\"' + objname_abs + r'\"']
+ generator_id = 0
+ for o in target.generated:
+ if isinstance(o, build.GeneratedList):
+ outputs = self.generator_outputs[target_name, generator_id]
+ generator_id += 1
+ for o_abs in outputs:
+ if o_abs.endswith('.o') or o_abs.endswith('.obj'):
+ ldargs += [r'\"' + o_abs + r'\"']
ldstr = ' '.join(ldargs)
valid = self.buildconfmap[target_name][buildtype]
langargs = {}