diff options
-rw-r--r-- | backends.py | 42 | ||||
-rw-r--r-- | ninjabackend.py | 38 | ||||
-rw-r--r-- | vs2010backend.py | 140 |
3 files changed, 144 insertions, 76 deletions
diff --git a/backends.py b/backends.py index b5af2ac..92a17fd 100644 --- a/backends.py +++ b/backends.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os, pickle +import os, pickle, re import build import dependencies import mesonlib @@ -350,3 +350,43 @@ class Backend(): if os.path.isfile(fname): deps.append(os.path.join(self.build_to_src, sp, 'meson_options.txt')) return deps + + def eval_custom_target_command(self, target): + ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output] + srcs = [] + for i in target.sources: + if isinstance(i, str): + srcs.append(os.path.join(self.build_to_src, target.subdir, i)) + else: + srcs.append(i.rel_to_builddir(self.build_to_src)) + cmd = [] + for i in target.command: + if isinstance(i, build.CustomTarget): + # GIR scanner will attempt to execute this binary but + # it assumes that it is in path, so always give it a full path. + tmp = i.get_filename()[0] + i = os.path.join(self.get_target_dir(i), tmp) + for (j, src) in enumerate(srcs): + i = i.replace('@INPUT%d@' % j, src) + for (j, res) in enumerate(ofilenames): + i = i.replace('@OUTPUT%d@' % j, res) + if i == '@INPUT@': + cmd += srcs + elif i == '@OUTPUT@': + cmd += ofilenames + else: + if '@OUTDIR@' in i: + i = i.replace('@OUTDIR@', self.get_target_dir(target)) + elif '@PRIVATE_OUTDIR_' in i: + match = re.search('@PRIVATE_OUTDIR_(ABS_)?([-a-zA-Z0-9.@:]*)@', i) + source = match.group(0) + if match.group(1) is None: + lead_dir = '' + else: + lead_dir = self.environment.get_build_dir() + target_id = match.group(2) + i = i.replace(source, + os.path.join(lead_dir, + self.get_target_dir(self.build.targets[target_id]))) + cmd.append(i) + return (srcs, ofilenames, cmd) diff --git a/ninjabackend.py b/ninjabackend.py index f9d1979..f1274a7 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -287,19 +287,13 @@ class NinjaBackend(backends.Backend): self.generate_target(t, outfile) def generate_custom_target(self, target, outfile): - ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output] + (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = [] for i in target.get_dependencies(): # FIXME, should not grab element at zero but rather expand all. if isinstance(i, list): i = i[0] deps.append(os.path.join(self.get_target_dir(i), i.get_filename()[0])) - srcs = [] - for i in target.sources: - if isinstance(i, str): - srcs.append(os.path.join(self.build_to_src, target.subdir, i)) - else: - srcs.append(i.rel_to_builddir(self.build_to_src)) if target.build_always: deps.append('PHONY') elem = NinjaBuildElement(ofilenames, 'CUSTOM_COMMAND', srcs) @@ -315,36 +309,6 @@ class NinjaBackend(backends.Backend): tmp = [tmp] for fname in tmp: elem.add_dep(os.path.join(self.get_target_dir(d), fname)) - cmd = [] - for i in target.command: - if isinstance(i, build.CustomTarget): - # GIR scanner will attempt to execute this binary but - # it assumes that it is in path, so always give it a full path. - tmp = i.get_filename()[0] - i = os.path.join(self.get_target_dir(i), tmp) - for (j, src) in enumerate(srcs): - i = i.replace('@INPUT%d@' % j, src) - for (j, res) in enumerate(ofilenames): - i = i.replace('@OUTPUT%d@' % j, res) - if i == '@INPUT@': - cmd += srcs - elif i == '@OUTPUT@': - cmd += ofilenames - else: - if '@OUTDIR@' in i: - i = i.replace('@OUTDIR@', self.get_target_dir(target)) - elif '@PRIVATE_OUTDIR_' in i: - match = re.search('@PRIVATE_OUTDIR_(ABS_)?([-a-zA-Z0-9.@:]*)@', i) - source = match.group(0) - if match.group(1) is None: - lead_dir = '' - else: - lead_dir = self.environment.get_build_dir() - target_id = match.group(2) - i = i.replace(source, - os.path.join(lead_dir, - self.get_target_dir(self.build.targets[target_id]))) - cmd.append(i) elem.add_item('COMMAND', cmd) elem.add_item('description', 'Generating %s with a custom command.' % target.name) diff --git a/vs2010backend.py b/vs2010backend.py index 5a18dcb..c431a59 100644 --- a/vs2010backend.py +++ b/vs2010backend.py @@ -15,6 +15,7 @@ import os, sys import pickle import backends, build +import mlog import xml.etree.ElementTree as ET import xml.dom.minidom from coredata import MesonException @@ -37,35 +38,38 @@ class Vs2010Backend(backends.Backend): idgroup = ET.SubElement(parent_node, 'ItemDefinitionGroup') all_output_files = [] for genlist in target.get_generated_sources(): - generator = genlist.get_generator() - exe = generator.get_exe() - infilelist = genlist.get_infilelist() - outfilelist = genlist.get_outfilelist() - if isinstance(exe, build.BuildTarget): - exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe)) + if isinstance(genlist, build.CustomTarget): + all_output_files += [os.path.join(self.get_target_dir(genlist), i) for i in genlist.output] else: - exe_file = exe.get_command() - base_args = generator.get_arglist() - for i in range(len(infilelist)): - if len(infilelist) == len(outfilelist): - sole_output = os.path.join(self.get_target_private_dir_abs(target), outfilelist[i]) + generator = genlist.get_generator() + exe = generator.get_exe() + infilelist = genlist.get_infilelist() + outfilelist = genlist.get_outfilelist() + if isinstance(exe, build.BuildTarget): + exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe)) else: - sole_output = '' - curfile = infilelist[i] - infilename = os.path.join(self.environment.get_source_dir(), curfile) - outfiles = genlist.get_outputs_for(curfile) - outfiles = [os.path.join(self.get_target_private_dir_abs(target), of) for of in outfiles] - all_output_files += outfiles - args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\ - for x in base_args] - args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir_abs(target)) - for x in args] - fullcmd = [exe_file] + args - cbs = ET.SubElement(idgroup, 'CustomBuildStep') - ET.SubElement(cbs, 'Command').text = ' '.join(self.special_quote(fullcmd)) - ET.SubElement(cbs, 'Inputs').text = infilename - ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles) - ET.SubElement(cbs, 'Message').text = 'Generating sources from %s.' % infilename + exe_file = exe.get_command() + base_args = generator.get_arglist() + for i in range(len(infilelist)): + if len(infilelist) == len(outfilelist): + sole_output = os.path.join(self.get_target_private_dir_abs(target), outfilelist[i]) + else: + sole_output = '' + curfile = infilelist[i] + infilename = os.path.join(self.environment.get_source_dir(), curfile) + outfiles = genlist.get_outputs_for(curfile) + outfiles = [os.path.join(self.get_target_private_dir_abs(target), of) for of in outfiles] + all_output_files += outfiles + args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\ + for x in base_args] + args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir_abs(target)) + for x in args] + fullcmd = [exe_file] + args + cbs = ET.SubElement(idgroup, 'CustomBuildStep') + ET.SubElement(cbs, 'Command').text = ' '.join(self.special_quote(fullcmd)) + ET.SubElement(cbs, 'Inputs').text = infilename + ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles) + ET.SubElement(cbs, 'Message').text = 'Generating sources from %s.' % infilename pg = ET.SubElement(parent_node, 'PropertyGroup') ET.SubElement(pg, 'CustomBuildBeforeTargets').text = 'ClCompile' return all_output_files @@ -99,6 +103,26 @@ class Vs2010Backend(backends.Backend): result[o.target.get_basename()] = True return result.keys() + def determine_deps(self, p): + all_deps = {} + target = self.build.targets[p[0]] + if isinstance(target, build.CustomTarget): + for d in target.dependencies: + all_deps[d.get_id()] = True + return all_deps + for ldep in target.link_targets: + all_deps[ldep.get_id()] = True + for objdep in self.get_obj_target_deps(target.objects): + all_deps[objdep] = True + for gendep in target.generated: + if isinstance(gendep, build.CustomTarget): + all_deps[gendep.get_id()] = True + else: + gen_exe = gendep.generator.get_exe() + if isinstance(gen_exe, build.Executable): + all_deps[gen_exe.get_id()] = True + return all_deps + def generate_solution(self, sln_filename, projlist): ofile = open(sln_filename, 'w') ofile.write('Microsoft Visual Studio Solution File, Format Version 11.00\n') @@ -107,15 +131,7 @@ class Vs2010Backend(backends.Backend): for p in projlist: prj_line = prj_templ % (self.environment.coredata.guid, p[0], p[1], p[2]) ofile.write(prj_line) - all_deps = {} - for ldep in self.build.targets[p[0]].link_targets: - all_deps[ldep.get_id()] = True - for objdep in self.get_obj_target_deps(self.build.targets[p[0]].objects): - all_deps[objdep] = True - for gendep in self.build.targets[p[0]].generated: - gen_exe = gendep.generator.get_exe() - if isinstance(gen_exe, build.Executable): - all_deps[gen_exe.get_id()] = True + all_deps = self.determine_deps(p) ofile.write('\tProjectSection(ProjectDependencies) = postProject\n') regen_guid = self.environment.coredata.regen_guid ofile.write('\t\t{%s} = {%s}\n' % (regen_guid, regen_guid)) @@ -191,9 +207,57 @@ class Vs2010Backend(backends.Backend): return ['"%s"' % i for i in arr] def gen_custom_target_vcxproj(self, target, ofname, guid): - raise NotImplementedError('Custom target not implemented yet. Sorry.') + buildtype = self.environment.coredata.buildtype + platform = "Win32" + project_name = target.name + root = ET.Element('Project', {'DefaultTargets' : "Build", + 'ToolsVersion' : '4.0', + 'xmlns' : 'http://schemas.microsoft.com/developer/msbuild/2003'}) + confitems = ET.SubElement(root, 'ItemGroup', {'Label' : 'ProjectConfigurations'}) + prjconf = ET.SubElement(confitems, 'ProjectConfiguration', {'Include' : 'Debug|Win32'}) + p = ET.SubElement(prjconf, 'Configuration') + p.text= buildtype + pl = ET.SubElement(prjconf, 'Platform') + pl.text = platform + globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') + guidelem = ET.SubElement(globalgroup, 'ProjectGuid') + guidelem.text = self.environment.coredata.test_guid + kw = ET.SubElement(globalgroup, 'Keyword') + kw.text = 'Win32Proj' + p = ET.SubElement(globalgroup, 'Platform') + p.text= platform + pname= ET.SubElement(globalgroup, 'ProjectName') + pname.text = project_name + ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props') + type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') + ET.SubElement(type_config, 'ConfigurationType') + ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' + ET.SubElement(type_config, 'UseOfMfc').text = 'false' + ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props') + direlem = ET.SubElement(root, 'PropertyGroup') + fver = ET.SubElement(direlem, '_ProjectFileVersion') + fver.text = self.project_file_version + outdir = ET.SubElement(direlem, 'OutDir') + outdir.text = '.\\' + intdir = ET.SubElement(direlem, 'IntDir') + intdir.text = 'test-temp\\' + tname = ET.SubElement(direlem, 'TargetName') + tname.text = target.name + action = ET.SubElement(root, 'ItemDefinitionGroup') + customstep = ET.SubElement(action, 'CustomBuildStep') + (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) + cmd_templ = '''"%s" '''*len(cmd) + ET.SubElement(customstep, 'Command').text = cmd_templ % tuple(cmd) + ET.SubElement(customstep, 'Outputs').text = ';'.join([os.path.join(self.environment.get_build_dir(), i)\ + for i in ofilenames]) + ET.SubElement(customstep, 'Inputs').text = ';'.join([os.path.join(self.environment.get_build_dir(), i) \ + for i in srcs]) + ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') + tree = ET.ElementTree(root) + tree.write(ofname, encoding='utf-8', xml_declaration=True) def gen_vcxproj(self, target, ofname, guid, compiler): + mlog.debug('Generating vcxproj %s.' % target.name) entrypoint = 'WinMainCRTStartup' subsystem = 'Windows' if isinstance(target, build.Executable): @@ -207,7 +271,7 @@ class Vs2010Backend(backends.Backend): conftype = 'DynamicLibrary' entrypoint = '_DllMainCrtStartup' elif isinstance(target, build.CustomTarget): - self.gen_custom_target_vcxproj(target, ofname, guid) + return self.gen_custom_target_vcxproj(target, ofname, guid) else: raise MesonException('Unknown target type for %s' % target.get_basename()) down = self.target_to_build_root(target) |