Separated backends into their own files.

pull/15/head
Jussi Pakkanen 11 years ago
parent 5efb36caab
commit 1967b64180
  1. 1865
      backends.py
  2. 11
      meson.py
  3. 863
      ninjabackend.py
  4. 380
      vs2010backend.py

File diff suppressed because it is too large Load Diff

@ -18,7 +18,7 @@ from optparse import OptionParser
import sys, stat, traceback, pickle
import os.path
import environment, interpreter
import backends, build
import build
import mlog, coredata
from coredata import MesonException
@ -130,11 +130,14 @@ itself as required.'''
intr = interpreter.Interpreter(b)
intr.run()
if options.backend == 'ninja':
g = backends.NinjaBackend(b, intr)
import ninjabackend
g = ninjabackend.NinjaBackend(b, intr)
elif options.backend == 'vs2010':
g = backends.Vs2010Backend(b, intr)
import vs2010backend
g = vs2010backend.Vs2010Backend(b, intr)
elif options.backend == 'xcode':
g = backends.XCodeBackend(b, intr)
import xcodebackend
g = xcodebackend.XCodeBackend(b, intr)
else:
raise RuntimeError('Unknown backend "%s".' % options.backend)
g.generate()

@ -0,0 +1,863 @@
# Copyright 2012-2014 Jussi Pakkanen
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import backends
import environment
import build
from meson_install import InstallData
import os, sys, shutil, pickle
if environment.is_windows():
quote_char = '"'
execute_wrapper = 'cmd /c'
else:
quote_char = "'"
execute_wrapper = ''
def ninja_quote(text):
return text.replace(' ', '$ ').replace(':', '$:')
class NinjaBuildElement():
def __init__(self, outfilenames, rule, infilenames):
if isinstance(outfilenames, str):
self.outfilenames = [outfilenames]
else:
self.outfilenames = outfilenames
assert(isinstance(rule, str))
self.rule = rule
if isinstance(infilenames, str):
self.infilenames = [infilenames]
else:
self.infilenames = infilenames
self.deps = []
self.orderdeps = []
self.elems = []
def add_dep(self, dep):
if isinstance(dep, list):
self.deps += dep
else:
self.deps.append(dep)
def add_orderdep(self, dep):
if isinstance(dep, list):
self.orderdeps += dep
else:
self.orderdeps.append(dep)
def add_item(self, name, elems):
if isinstance(elems, str):
elems = [elems]
self.elems.append((name, elems))
def write(self, outfile):
line = 'build %s: %s %s' % (' '.join([ninja_quote(i) for i in self.outfilenames]),\
self.rule,
' '.join([ninja_quote(i) for i in self.infilenames]))
if len(self.deps) > 0:
line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
if len(self.orderdeps) > 0:
line += ' || ' + ' '.join([ninja_quote(x) for x in self.orderdeps])
line += '\n'
outfile.write(line)
for e in self.elems:
(name, elems) = e
should_quote = True
if name == 'DEPFILE' or name == 'DESC':
should_quote = False
line = ' %s = ' % name
q_templ = quote_char + "%s" + quote_char
noq_templ = "%s"
newelems = []
for i in elems:
if not should_quote or i == '&&': # Hackety hack hack
templ = noq_templ
else:
templ = q_templ
newelems.append(templ % ninja_quote(i))
line += ' '.join(newelems)
line += '\n'
outfile.write(line)
outfile.write('\n')
class NinjaBackend(backends.Backend):
def __init__(self, build, interp):
super().__init__(build, interp)
self.source_suffix_in_objs = True
self.ninja_filename = 'build.ninja'
def generate(self):
outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
tempfilename = outfilename + '~'
outfile = open(tempfilename, 'w')
self.generate_configure_files()
self.generate_pkgconfig_files()
outfile.write('# This is the build file for project "%s"\n' % self.build.get_project())
outfile.write('# It is autogenerated by the Meson build system.\n')
outfile.write('# Do not edit by hand.\n\n')
outfile.write('ninja_required_version = 1.3.4\n\n')
self.generate_rules(outfile)
outfile.write('# Build rules for targets\n\n')
[self.generate_target(t, outfile) for t in self.build.get_targets().values()]
if len(self.build.pot) > 0:
outfile.write('# Build rules for localisation.\n\n')
self.generate_po(outfile)
outfile.write('# Test rules\n\n')
self.generate_tests(outfile)
outfile.write('# Install rules\n\n')
self.generate_install(outfile)
if self.environment.coredata.coverage:
outfile.write('# Coverage rules\n\n')
self.generate_coverage_rules(outfile)
outfile.write('# Suffix\n\n')
self.generate_ending(outfile)
# Only ovewrite the old build file after the new one has been
# fully created.
outfile.close()
os.replace(tempfilename, outfilename)
def generate_po(self, outfile):
for p in self.build.pot:
(packagename, languages, subdir) = p
input_file = os.path.join(subdir, 'POTFILES')
elem = NinjaBuildElement('pot', 'GEN_POT', [])
elem.add_item('PACKAGENAME', packagename)
elem.add_item('OUTFILE', packagename + '.pot')
elem.add_item('FILELIST', os.path.join(self.environment.get_source_dir(), input_file))
elem.add_item('OUTDIR', os.path.join(self.environment.get_source_dir(), subdir))
elem.write(outfile)
for l in languages:
infile = os.path.join(self.environment.get_source_dir(), subdir, l + '.po')
outfilename = os.path.join(subdir, l + '.gmo')
lelem = NinjaBuildElement(outfilename, 'GEN_GMO', infile)
lelem.add_item('INFILE', infile)
lelem.add_item('OUTFILE', outfilename)
lelem.write(outfile)
def generate_coverage_rules(self, outfile):
(gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools()
added_rule = False
if gcovr_exe:
added_rule = True
elem = NinjaBuildElement('coverage-xml', 'CUSTOM_COMMAND', '')
elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', self.environment.get_build_dir(),\
'-o', os.path.join(self.environment.get_log_dir(), 'coverage.xml')])
elem.add_item('DESC', 'Generating XML coverage report.')
elem.write(outfile)
elem = NinjaBuildElement('coverage-text', 'CUSTOM_COMMAND', '')
elem.add_item('COMMAND', [gcovr_exe, '-r', self.environment.get_build_dir(),\
'-o', os.path.join(self.environment.get_log_dir(), 'coverage.txt')])
elem.add_item('DESC', 'Generating text coverage report.')
elem.write(outfile)
if lcov_exe and genhtml_exe:
added_rule = True
phony_elem = NinjaBuildElement('coverage-html', 'phony', 'coveragereport/index.html')
phony_elem.write(outfile)
elem = NinjaBuildElement('coveragereport/index.html', 'CUSTOM_COMMAND', '')
command = [lcov_exe, '--directory', self.environment.get_build_dir(),\
'--capture', '--output-file', 'coverage.info', '--no-checksum',\
'&&', genhtml_exe, '--prefix', self.environment.get_build_dir(),\
'--output-directory', self.environment.get_log_dir(), '--title', 'Code coverage',\
'--legend', '--show-details', 'coverage.info']
elem.add_item('COMMAND', command)
elem.add_item('DESC', 'Generating HTML coverage report.')
elem.write(outfile)
if not added_rule:
mlog.log(mlog.red('Warning:'), 'coverage requested but neither gcovr nor lcov/genhtml found.')
def generate_install(self, outfile):
script_root = self.environment.get_script_dir()
install_script = os.path.join(script_root, 'meson_install.py')
install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat')
depfixer = os.path.join(script_root, 'depfixer.py')
d = InstallData(self.environment.get_prefix(), depfixer, './') # Fixme
elem = NinjaBuildElement('install', 'CUSTOM_COMMAND', '')
elem.add_dep('all')
elem.add_item('DESC', 'Installing files.')
elem.add_item('COMMAND', [sys.executable, install_script, install_data_file])
self.generate_target_install(d)
self.generate_header_install(d)
self.generate_man_install(d)
self.generate_data_install(d)
self.generate_po_install(d, elem)
self.generate_pkgconfig_install(d)
elem.write(outfile)
ofile = open(install_data_file, 'wb')
pickle.dump(d, ofile)
def generate_po_install(self, d, elem):
for p in self.build.pot:
(package_name, languages, subdir) = p
# FIXME: assumes only one po package per source
d.po_package_name = package_name
for lang in languages:
rel_src = os.path.join(subdir, lang + '.gmo')
src_file = os.path.join(self.environment.get_build_dir(), rel_src)
d.po.append((src_file, self.environment.coredata.localedir, lang))
elem.add_dep(rel_src)
def generate_target_install(self, d):
libdir = self.environment.get_libdir()
bindir = self.environment.get_bindir()
should_strip = self.environment.coredata.strip
for t in self.build.get_targets().values():
if t.should_install():
outdir = t.get_custom_install_dir()
if outdir is None:
if isinstance(t, build.Executable):
outdir = bindir
else:
outdir = libdir
i = [self.get_target_filename(t), outdir, t.get_aliaslist(), should_strip]
d.targets.append(i)
def generate_pkgconfig_install(self, d):
pkgroot = os.path.join(self.environment.coredata.prefix,
self.environment.coredata.libdir, 'pkgconfig')
for p in self.build.pkgconfig_gens:
pcfile = p.filebase + '.pc'
srcabs = os.path.join(self.environment.get_scratch_dir(),
pcfile)
dstabs = os.path.join(pkgroot, pcfile)
i = [srcabs, dstabs]
d.man.append(i)
def generate_header_install(self, d):
incroot = self.environment.get_includedir()
headers = self.build.get_headers()
for h in headers:
outdir = h.get_custom_install_dir()
if outdir is None:
outdir = os.path.join(incroot, h.get_subdir())
for f in h.get_sources():
abspath = os.path.join(self.environment.get_source_dir(), f) # FIXME
i = [abspath, outdir]
d.headers.append(i)
def generate_man_install(self, d):
manroot = self.environment.get_mandir()
man = self.build.get_man()
for m in man:
for f in m.get_sources():
num = f.split('.')[-1]
subdir = m.get_custom_install_dir()
if subdir is None:
subdir = os.path.join(manroot, 'man' + num)
srcabs = os.path.join(self.environment.get_source_dir(), f)
dstabs = os.path.join(subdir, f + '.gz')
i = [srcabs, dstabs]
d.man.append(i)
def generate_data_install(self, d):
dataroot = self.environment.get_datadir()
data = self.build.get_data()
for de in data:
subdir = de.get_custom_install_dir()
if subdir is None:
subdir = os.path.join(dataroot, de.get_subdir())
for f in de.get_sources():
srcabs = os.path.join(self.environment.get_source_dir(), f)
dstabs = os.path.join(subdir, f)
i = [srcabs, dstabs]
d.data.append(i)
def generate_tests(self, outfile):
self.serialise_tests()
valgrind = environment.find_valgrind()
script_root = self.environment.get_script_dir()
test_script = os.path.join(script_root, 'meson_test.py')
test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
cmd = [sys.executable, test_script, test_data]
elem = NinjaBuildElement('test', 'CUSTOM_COMMAND', 'all')
elem.add_item('COMMAND', cmd)
elem.add_item('DESC', 'Running test suite.')
elem.write(outfile)
if valgrind:
velem = NinjaBuildElement('test-valgrind', 'CUSTOM_COMMAND', 'all')
velem.add_item('COMMAND', cmd + ['--wrapper=' + valgrind])
velem.add_item('DESC', 'Running test suite under Valgrind.')
velem.write(outfile)
def generate_dep_gen_rules(self, outfile):
outfile.write('# Rules for external dependency generators.\n\n')
processed = {}
for dep in self.environment.coredata.deps.values():
name = dep.get_name()
if name in processed:
continue
processed[name] = True
for rule in dep.get_generate_rules():
outfile.write('rule %s\n' % rule.name)
command = ' '.join([ninja_quote(x) for x in rule.cmd_list])
command = command.replace('@INFILE@', '$in').replace('@OUTFILE@', '$out')
command = command.replace('@SOURCE_ROOT@', self.environment.get_source_dir())
command = command.replace('@BUILD_ROOT@', self.environment.get_build_dir())
outfile.write(' command = %s\n' % command)
desc = rule.description.replace('@INFILE@', '$in')
outfile.write(' description = %s\n' % desc)
if rule.src_keyword in self.dep_rules:
raise InvalidArguments('Multiple rules for keyword %s.' % rule.src_keyword)
self.dep_rules[rule.src_keyword] = rule
outfile.write('\n')
def generate_rules(self, outfile):
outfile.write('# Rules for compiling.\n\n')
self.generate_compile_rules(outfile)
outfile.write('# Rules for linking.\n\n')
if self.environment.is_cross_build():
self.generate_static_link_rules(True, outfile)
self.generate_static_link_rules(False, outfile)
self.generate_dynamic_link_rules(outfile)
self.generate_dep_gen_rules(outfile)
outfile.write('# Other rules\n\n')
outfile.write('rule CUSTOM_COMMAND\n')
outfile.write(' command = $COMMAND\n')
outfile.write(' description = $DESC\n')
outfile.write(' restat = 1\n\n')
outfile.write('rule REGENERATE_BUILD\n')
c = (quote_char + ninja_quote(sys.executable) + quote_char,
quote_char + ninja_quote(self.environment.get_build_command()) + quote_char,
quote_char + ninja_quote(self.environment.get_source_dir()) + quote_char,
quote_char + ninja_quote(self.environment.get_build_dir()) + quote_char)
outfile.write(" command = %s %s %s %s --backend ninja secret-handshake\n" % c)
outfile.write(' description = Regenerating build files\n')
outfile.write(' generator = 1\n\n')
if len(self.build.pot) > 0:
self.generate_gettext_rules(outfile)
outfile.write('\n')
def generate_gettext_rules(self, outfile):
rule = 'rule GEN_POT\n'
command = " command = xgettext --package-name=$PACKAGENAME -p $OUTDIR -f $FILELIST -D '%s' -k_ -o $OUTFILE\n" % \
self.environment.get_source_dir()
desc = " description = Creating pot file for package $PACKAGENAME.\n"
outfile.write(rule)
outfile.write(command)
outfile.write(desc)
outfile.write('\n')
rule = 'rule GEN_GMO\n'
command = ' command = msgfmt $INFILE -o $OUTFILE\n'
desc = ' description = Generating gmo file $OUTFILE\n'
outfile.write(rule)
outfile.write(command)
outfile.write(desc)
outfile.write('\n')
def generate_jar_target(self, target, outfile):
fname = target.get_filename()
subdir = target.get_subdir()
outname_rel = os.path.join(subdir, fname)
src_list = target.get_sources()
class_list = []
compiler = self.get_compiler_for_source(src_list[0])
assert(compiler.get_language() == 'java')
c = 'c'
m = ''
e = ''
f = 'f'
main_class = target.get_main_class()
if main_class != '':
e = 'e'
for src in src_list:
class_list.append(self.generate_single_java_compile(subdir, src, target, compiler, outfile))
jar_rule = 'java_LINKER'
commands = [c+m+e+f]
if e != '':
commands.append(main_class)
commands.append(self.get_target_filename(target))
commands += ['-C', self.get_target_private_dir(target)]
commands += class_list
elem = NinjaBuildElement(outname_rel, jar_rule, [])
elem.add_dep([os.path.join(self.get_target_private_dir(target), i) for i in class_list])
elem.add_item('FLAGS', commands)
elem.write(outfile)
def generate_single_java_compile(self, subdir, src, target, compiler, outfile):
buildtype = self.environment.coredata.buildtype
args = []
if buildtype == 'debug':
args += compiler.get_debug_flags()
args += compiler.get_output_flags(self.get_target_private_dir(target))
rel_src = os.path.join(self.build_to_src, subdir, src)
plain_class_path = src[:-4] + 'class'
rel_obj = os.path.join(self.get_target_private_dir(target), plain_class_path)
element = NinjaBuildElement(rel_obj,
compiler.get_language() + '_COMPILER', rel_src)
element.add_item('FLAGS', args)
element.write(outfile)
return plain_class_path
def generate_java_link(self, outfile):
rule = 'rule java_LINKER\n'
command = ' command = jar $FLAGS\n'
description = ' description = Creating jar $out.\n'
outfile.write(rule)
outfile.write(command)
outfile.write(description)
outfile.write('\n')
def generate_static_link_rules(self, is_cross, outfile):
if self.build.has_language('java'):
if not is_cross:
self.generate_java_link(outfile)
if is_cross:
static_linker = self.build.static_cross_linker
crstr = '_CROSS'
else:
static_linker = self.build.static_linker
crstr = ''
if static_linker is None:
return
rule = 'rule STATIC%s_LINKER\n' % crstr
command = ' command = %s $LINK_FLAGS %s $in\n' % \
(' '.join(static_linker.get_exelist()),
' '.join(static_linker.get_output_flags('$out')))
description = ' description = Static linking library $out\n\n'
outfile.write(rule)
outfile.write(command)
outfile.write(description)
def generate_dynamic_link_rules(self, outfile):
ctypes = [(self.build.compilers, False), (self.build.cross_compilers, True)]
for (complist, is_cross) in ctypes:
for compiler in complist:
langname = compiler.get_language()
if langname == 'java':
continue
crstr = ''
if is_cross:
crstr = '_CROSS'
rule = 'rule %s%s_LINKER\n' % (langname, crstr)
command = ' command = %s %s $FLAGS %s $in $LINK_FLAGS $aliasing\n' % \
(execute_wrapper,
' '.join(compiler.get_linker_exelist()),\
' '.join(compiler.get_linker_output_flags('$out')))
description = ' description = Linking target $out'
outfile.write(rule)
outfile.write(command)
outfile.write(description)
outfile.write('\n')
scriptdir = self.environment.get_script_dir()
outfile.write('\n')
symrule = 'rule SHSYM\n'
symcmd = ' command = "%s" "%s" "%s" "%s" $CROSS\n' % (ninja_quote(sys.executable),
ninja_quote(os.path.join(scriptdir, 'symbolextractor.py')),
'$in', '$out')
synstat = ' restat = 1\n'
syndesc = ' description = Generating symbol file $out.\n'
outfile.write(symrule)
outfile.write(symcmd)
outfile.write(synstat)
outfile.write(syndesc)
outfile.write('\n')
def generate_java_compile_rule(self, compiler, outfile):
rule = 'rule %s_COMPILER\n' % compiler.get_language()
invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()])
command = ' command = %s $FLAGS $in\n' % invoc
description = ' description = Compiling Java object $in.\n'
outfile.write(rule)
outfile.write(command)
outfile.write(description)
outfile.write('\n')
def generate_compile_rule_for(self, langname, compiler, qstr, is_cross, outfile):
if langname == 'java':
if not is_cross:
self.generate_java_compile_rule(compiler, outfile)
return
if is_cross:
crstr = '_CROSS'
else:
crstr = ''
rule = 'rule %s%s_COMPILER\n' % (langname, crstr)
depflags = compiler.get_dependency_gen_flags('$out', '$DEPFILE')
command = " command = %s $FLAGS %s %s %s $in\n" % \
(' '.join(compiler.get_exelist()),\
' '.join([qstr % d for d in depflags]),\
' '.join(compiler.get_output_flags('$out')),\
' '.join(compiler.get_compile_only_flags()))
description = ' description = Compiling %s object $out\n' % langname
if compiler.get_id() == 'msvc':
deps = ' deps = msvc\n'
else:
deps = ' deps = gcc\n'
deps += ' depfile = $DEPFILE\n'
outfile.write(rule)
outfile.write(command)
outfile.write(deps)
outfile.write(description)
outfile.write('\n')
def generate_pch_rule_for(self, langname, compiler, qstr, is_cross, outfile):
if langname != 'c' and langname != 'cpp':
return
if is_cross:
crstr = '_CROSS'
else:
crstr = ''
rule = 'rule %s%s_PCH\n' % (langname, crstr)
depflags = compiler.get_dependency_gen_flags('$out', '$DEPFILE')
if compiler.get_id() == 'msvc':
output = ''
else:
output = ' '.join(compiler.get_output_flags('$out'))
command = " command = %s $FLAGS %s %s %s $in\n" % \
(' '.join(compiler.get_exelist()),\
' '.join([qstr % d for d in depflags]),\
output,\
' '.join(compiler.get_compile_only_flags()))
description = ' description = Precompiling header %s\n' % '$in'
if compiler.get_id() == 'msvc':
deps = ' deps = msvc\n'
else:
deps = ' deps = gcc\n'
deps += ' depfile = $DEPFILE\n'
outfile.write(rule)
outfile.write(command)
outfile.write(deps)
outfile.write(description)
outfile.write('\n')
def generate_compile_rules(self, outfile):
qstr = quote_char + "%s" + quote_char
for compiler in self.build.compilers:
langname = compiler.get_language()
self.generate_compile_rule_for(langname, compiler, qstr, False, outfile)
self.generate_pch_rule_for(langname, compiler, qstr, False, outfile)
if self.environment.is_cross_build():
for compiler in self.build.cross_compilers:
langname = compiler.get_language()
self.generate_compile_rule_for(langname, compiler, qstr, True, outfile)
self.generate_pch_rule_for(langname, compiler, qstr, True, outfile)
outfile.write('\n')
def generate_custom_generator_rules(self, target, outfile):
for genlist in target.get_generated_sources():
generator = genlist.get_generator()
exe = generator.get_exe()
if self.environment.is_cross_build() and \
isinstance(exe, build.BuildTarget) and exe.is_cross:
if 'exe_wrapper' not in self.environment.cross_info:
s = 'Can not use target %s as a generator because it is cross-built\n'
s += 'and no exe wrapper is defined. You might want to set it to native instead.'
s = s % exe.name
raise MesonException(s)
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:
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(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(target), of) for of in 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(target))
for x in args]
cmdlist = [exe_file] + args
elem = NinjaBuildElement(outfiles, 'CUSTOM_COMMAND', infilename)
elem.add_item('DESC', 'Generating $out')
if isinstance(exe, build.BuildTarget):
elem.add_dep(self.get_target_filename(exe))
elem.add_item('COMMAND', cmdlist)
elem.write(outfile)
def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[]):
compiler = self.get_compiler_for_source(src)
commands = self.generate_basic_compiler_flags(target, compiler)
commands.append(compiler.get_include_arg(self.get_target_private_dir(target)))
if is_generated:
if '/' in src:
rel_src = src
else:
rel_src = os.path.join(self.get_target_private_dir(target), src)
else:
rel_src = os.path.join(self.build_to_src, target.get_source_subdir(), src)
if os.path.isabs(src):
src_filename = os.path.basename(src)
else:
src_filename = src
obj_basename = src_filename.replace('/', '_').replace('\\', '_')
rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename)
rel_obj += '.' + self.environment.get_object_suffix()
dep_file = rel_obj + '.' + compiler.get_depfile_suffix()
if self.environment.coredata.use_pch:
pchlist = target.get_pch(compiler.language)
else:
pchlist = []
if len(pchlist) == 0:
pch_dep = []
else:
arr = []
i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0]))
arr.append(i)
pch_dep = arr
for i in target.get_include_dirs():
basedir = i.get_curdir()
for d in i.get_incdirs():
expdir = os.path.join(basedir, d)
fulldir = os.path.join(self.environment.get_source_dir(), expdir)
barg = compiler.get_include_arg(expdir)
sarg = compiler.get_include_arg(fulldir)
commands.append(barg)
commands.append(sarg)
if self.environment.coredata.use_pch:
commands += self.get_pch_include_args(compiler, target)
crstr = ''
if target.is_cross:
crstr = '_CROSS'
compiler_name = '%s%s_COMPILER' % (compiler.get_language(), crstr)
element = NinjaBuildElement(rel_obj, compiler_name, rel_src)
for d in header_deps:
if not '/' in d:
d = os.path.join(self.get_target_private_dir(target), d)
element.add_dep(d)
element.add_orderdep(pch_dep)
element.add_item('DEPFILE', dep_file)
element.add_item('FLAGS', commands)
element.write(outfile)
return rel_obj
def generate_msvc_pch_command(self, target, compiler, pch):
if len(pch) != 2:
raise RuntimeError('MSVC requires one header and one source to produce precompiled headers.')
header = pch[0]
source = pch[1]
pchname = compiler.get_pch_name(header)
dst = os.path.join(self.get_target_private_dir(target), pchname)
commands = []
commands += self.generate_basic_compiler_flags(target, compiler)
just_name = os.path.split(header)[1]
commands += compiler.gen_pch_args(just_name, source, dst)
dep = dst + '.' + compiler.get_depfile_suffix()
return (commands, dep, dst)
def generate_gcc_pch_command(self, target, compiler, pch):
commands = []
commands += self.generate_basic_compiler_flags(target, compiler)
dst = os.path.join(self.get_target_private_dir(target),
os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix())
dep = dst + '.' + compiler.get_depfile_suffix()
return (commands, dep, dst)
def generate_pch(self, target, outfile):
cstr = ''
if target.is_cross:
cstr = '_CROSS'
for lang in ['c', 'cpp']:
pch = target.get_pch(lang)
if len(pch) == 0:
continue
if '/' not in pch[0] or '/' not in pch[-1]:
raise build.InvalidArguments('Precompiled header of "%s" must not be in the same directory as source, please put it in a subdirectory.' % target.get_basename())
compiler = self.get_compiler_for_lang(lang)
if compiler.id == 'msvc':
src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[-1])
(commands, dep, dst) = self.generate_msvc_pch_command(target, compiler, pch)
extradep = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0])
else:
src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0])
(commands, dep, dst) = self.generate_gcc_pch_command(target, compiler, pch[0])
extradep = None
rulename = compiler.get_language() + cstr + '_PCH'
elem = NinjaBuildElement(dst, rulename, src)
if extradep is not None:
elem.add_dep(extradep)
elem.add_item('FLAGS', commands)
elem.add_item('DEPFILE', dep)
elem.write(outfile)
def generate_shsym(self, outfile, target):
target_name = self.get_target_filename(target)
targetdir = self.get_target_private_dir(target)
symname = os.path.join(targetdir, target_name + '.symbols')
elem = NinjaBuildElement(symname, 'SHSYM', target_name)
if self.environment.is_cross_build():
elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info['name'])
elem.write(outfile)
def generate_link(self, target, outfile, outname, obj_list, linker):
if isinstance(target, build.StaticLibrary):
linker_base = 'STATIC'
else:
linker_base = linker.get_language() # Fixme.
if isinstance(target, build.SharedLibrary):
self.generate_shsym(outfile, target)
crstr = ''
if target.is_cross:
crstr = '_CROSS'
linker_rule = linker_base + crstr + '_LINKER'
abspath = os.path.join(self.environment.get_build_dir(), target.subdir)
commands = []
commands += linker.get_linker_always_flags()
if isinstance(target, build.Executable):
commands += linker.get_std_exe_link_flags()
elif isinstance(target, build.SharedLibrary):
commands += linker.get_std_shared_lib_link_flags()
commands += linker.get_pic_flags()
commands += linker.get_soname_flags(target.name, abspath)
elif isinstance(target, build.StaticLibrary):
commands += linker.get_std_link_flags()
else:
raise RuntimeError('Unknown build target type.')
for dep in target.get_external_deps():
commands += dep.get_link_flags()
dependencies = target.get_dependencies()
commands += self.build_target_link_arguments(linker, dependencies)
commands += target.link_flags
commands += linker.build_rpath_args(self.environment.get_build_dir(), target.get_rpaths())
if self.environment.coredata.coverage:
commands += linker.get_coverage_link_flags()
dep_targets = [self.get_dependency_filename(t) for t in dependencies]
dep_targets += [os.path.join(self.environment.source_dir,
target.subdir, t) for t in target.link_depends]
elem = NinjaBuildElement(outname, linker_rule, obj_list)
elem.add_dep(dep_targets)
elem.add_item('LINK_FLAGS', commands)
return elem
def get_dependency_filename(self, t):
if isinstance(t, build.SharedLibrary):
return os.path.join(self.get_target_private_dir(t), self.get_target_filename(t) + '.symbols')
return self.get_target_filename(t)
def generate_shlib_aliases(self, target, outdir, outfile, elem):
basename = target.get_filename()
aliases = target.get_aliaslist()
aliascmd = []
if shutil.which('ln'):
for alias in aliases:
aliasfile = os.path.join(outdir, alias)
cmd = ["&&", 'ln', '-s', '-f', basename, aliasfile]
aliascmd += cmd
else:
mlog.log("Library versioning disabled because host does not support symlinks.")
elem.add_item('aliasing', aliascmd)
elem.write(outfile)
def generate_gcov_clean(self, outfile):
gcno_elem = NinjaBuildElement('clean-gcno', 'CUSTOM_COMMAND', '')
script_root = self.environment.get_script_dir()
clean_script = os.path.join(script_root, 'delwithsuffix.py')
gcno_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcno'])
gcno_elem.add_item('description', 'Deleting gcno files')
gcno_elem.write(outfile)
gcda_elem = NinjaBuildElement('clean-gcda', 'CUSTOM_COMMAND', '')
script_root = self.environment.get_script_dir()
clean_script = os.path.join(script_root, 'delwithsuffix.py')
gcda_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcda'])
gcda_elem.add_item('description', 'Deleting gcda files')
gcda_elem.write(outfile)
def is_compilable_file(self, filename):
if filename.endswith('.cpp') or\
filename.endswith('.c') or\
filename.endswith('.cxx') or\
filename.endswith('.cc') or\
filename.endswith('.C'):
return True
return False
def process_dep_gens(self, outfile, target):
src_deps = []
other_deps = []
for rule in self.dep_rules.values():
srcs = target.get_original_kwargs().get(rule.src_keyword, [])
if isinstance(srcs, str):
srcs = [srcs]
for src in srcs:
plainname = os.path.split(src)[1]
basename = plainname.split('.')[0]
outname = rule.name_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
outfilename = os.path.join(self.get_target_private_dir(target), outname)
infilename = os.path.join(self.build_to_src, target.get_source_subdir(), src)
rule = rule.name
elem = NinjaBuildElement(outfilename, rule, infilename)
elem.write(outfile)
if self.is_compilable_file(outfilename):
src_deps.append(outfilename)
else:
other_deps.append(outfilename)
return (src_deps, other_deps)
def generate_cppcheck_target(self, outfile):
cppcheck_exe = environment.find_cppcheck()
if not cppcheck_exe:
return
elem = NinjaBuildElement('cppcheck', 'CUSTOM_COMMAND', [])
elem.add_item('COMMAND', [cppcheck_exe, self.environment.get_source_dir()])
elem.add_item('description', 'Running cppchecker')
elem.write(outfile)
def generate_ending(self, outfile):
targetlist = [self.get_target_filename(t) for t in self.build.get_targets().values()]
elem = NinjaBuildElement('all', 'phony', targetlist)
elem.write(outfile)
default = 'default all\n\n'
outfile.write(default)
ninja_command = environment.detect_ninja()
if ninja_command is None:
raise RuntimeError('Could not detect ninja command')
elem = NinjaBuildElement('clean', 'CUSTOM_COMMAND', '')
elem.add_item('COMMAND', [ninja_command, '-t', 'clean'])
elem.add_item('description', 'Cleaning')
if self.environment.coredata.coverage:
self.generate_gcov_clean(outfile)
elem.add_dep('clean-gcda')
elem.add_dep('clean-gcno')
elem.write(outfile)
deps = [os.path.join(self.build_to_src, df) \
for df in self.interpreter.get_build_def_files()]
if self.environment.is_cross_build():
deps.append(os.path.join(self.build_to_src,
self.environment.coredata.cross_file))
deps.append('meson-private/coredata.dat')
if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')):
deps.append(os.path.join(self.build_to_src, 'meson_options.txt'))
for sp in self.build.subprojects.keys():
fname = os.path.join(self.environment.get_source_dir(), sp, 'meson_options.txt')
if os.path.isfile(fname):
deps.append(os.path.join(self.build_to_src, sp, 'meson_options.txt'))
elem = NinjaBuildElement('build.ninja', 'REGENERATE_BUILD', deps)
elem.write(outfile)
elem = NinjaBuildElement(deps, 'phony', '')
elem.write(outfile)
self.generate_cppcheck_target(outfile)

@ -0,0 +1,380 @@
# Copyright 2014 Jussi Pakkanen
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import backends
import xml.etree.ElementTree as ET
import xml.dom.minidom
class Vs2010Backend(backends.Backend):
def __init__(self, build, interp):
super().__init__(build, interp)
self.project_file_version = '10.0.30319.1'
# foo.c compiles to foo.obj, not foo.c.obj
self.source_suffix_in_obj = False
def generate_custom_generator_commands(self, target, parent_node):
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))
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(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(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(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
def generate(self):
self.generate_configure_files()
self.generate_pkgconfig_files()
sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln')
projlist = self.generate_projects()
self.gen_testproj('RUN_TESTS', os.path.join(self.environment.get_build_dir(), 'RUN_TESTS.vcxproj'))
self.generate_solution(sln_filename, projlist)
def get_obj_target_deps(self, obj_list):
result = {}
for o in obj_list:
if isinstance(o, build.ExtractedObjects):
result[o.target.get_basename()] = True
return result.keys()
def generate_solution(self, sln_filename, projlist):
ofile = open(sln_filename, 'w')
ofile.write('Microsoft Visual Studio Solution File, Format Version 11.00\n')
ofile.write('# Visual Studio 2010\n')
prj_templ = prj_line = 'Project("{%s}") = "%s", "%s", "{%s}"\n'
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_basename()] = 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_basename()] = True
if len(all_deps) > 0:
ofile.write('\tProjectSection(ProjectDependencies) = postProject\n')
for dep in all_deps.keys():
guid = self.environment.coredata.target_guids[dep]
ofile.write('\t\t{%s} = {%s}\n' % (guid, guid))
ofile.write('EndProjectSection\n')
ofile.write('EndProject\n')
test_line = prj_templ % (self.environment.coredata.guid,
'RUN_TESTS', 'RUN_TESTS.vcxproj', self.environment.coredata.test_guid)
ofile.write(test_line)
ofile.write('EndProject\n')
ofile.write('Global\n')
ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
ofile.write('\t\tDebug|Win32 = Debug|Win32\n')
ofile.write('\tEndGlobalSection\n')
ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
for p in projlist:
ofile.write('\t\t{%s}.Debug|Win32.ActiveCfg = Debug|Win32\n' % p[2])
ofile.write('\t\t{%s}.Debug|Win32.Build.0 = Debug|Win32\n' % p[2])
ofile.write('\t\t{%s}.Debug|Win32.ActiveCfg = Debug|Win32\n' % self.environment.coredata.test_guid)
ofile.write('\tEndGlobalSection\n')
ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n')
ofile.write('\t\tHideSolutionNode = FALSE\n')
ofile.write('\tEndGlobalSection\n')
ofile.write('EndGlobal\n')
def generate_projects(self):
projlist = []
for name, target in self.build.targets.items():
outdir = os.path.join(self.environment.get_build_dir(), target.subdir)
fname = name + '.vcxproj'
relname = os.path.join(target.subdir, fname)
projfile = os.path.join(outdir, fname)
uuid = self.environment.coredata.target_guids[name]
self.gen_vcxproj(target, projfile, uuid)
projlist.append((name, relname, uuid))
return projlist
def split_sources(self, srclist):
sources = []
headers = []
for i in srclist:
if self.environment.is_header(i):
headers.append(i)
else:
sources.append(i)
return (sources, headers)
def target_to_build_root(self, target):
if target.subdir == '':
return ''
return '/'.join(['..']*(len(os.path.split(target.subdir))-1))
def special_quote(self, arr):
return ['"%s"' % i for i in arr]
def gen_vcxproj(self, target, ofname, guid):
down = self.target_to_build_root(target)
proj_to_src_root = os.path.join(down, self.build_to_src)
proj_to_src_dir = os.path.join(proj_to_src_root, target.subdir)
(sources, headers) = self.split_sources(target.sources)
entrypoint = 'WinMainCRTStartup'
buildtype = 'Debug'
platform = "Win32"
project_name = target.name
target_name = target.name
subsystem = 'Windows'
if isinstance(target, build.Executable):
conftype = 'Application'
if not target.gui_app:
subsystem = 'Console'
entrypoint = 'mainCRTStartup'
elif isinstance(target, build.StaticLibrary):
conftype = 'StaticLibrary'
elif isinstance(target, build.SharedLibrary):
conftype = 'DynamicLibrary'
entrypoint = '_DllMainCrtStartup'
else:
raise MesonException('Unknown target type for %s' % 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 = guid
kw = ET.SubElement(globalgroup, 'Keyword')
kw.text = 'Win32Proj'
ns = ET.SubElement(globalgroup, 'RootNamespace')
ns.text = target_name
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').text = conftype
ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false'
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
generated_files = self.generate_custom_generator_commands(target, root)
(gen_src, gen_hdrs) = self.split_sources(generated_files)
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 = os.path.join(self.get_target_dir(target), target.get_basename() + '.dir') + '\\'
tname = ET.SubElement(direlem, 'TargetName')
tname.text = target_name
inclinc = ET.SubElement(direlem, 'LinkIncremental')
inclinc.text = 'true'
compiles = ET.SubElement(root, 'ItemDefinitionGroup')
clconf = ET.SubElement(compiles, 'ClCompile')
opt = ET.SubElement(clconf, 'Optimization')
opt.text = 'disabled'
inc_dirs = [proj_to_src_dir, self.get_target_private_dir(target)]
extra_args = []
# SUCKS, VS can not handle per-language type flags, so just use
# them all.
for l in self.build.global_args.values():
for a in l:
extra_args.append(a)
for l in target.extra_args.values():
for a in l:
extra_args.append(a)
if len(extra_args) > 0:
extra_args.append('%(AdditionalOptions)')
ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(extra_args)
for d in target.include_dirs:
for i in d.incdirs:
curdir = os.path.join(d.curdir, i)
inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
inc_dirs.append(os.path.join(proj_to_src_root, curdir)) # src dir
inc_dirs.append('%(AdditionalIncludeDirectories)')
ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(inc_dirs)
preproc = ET.SubElement(clconf, 'PreprocessorDefinitions')
rebuild = ET.SubElement(clconf, 'MinimalRebuild')
rebuild.text = 'true'
rtlib = ET.SubElement(clconf, 'RuntimeLibrary')
rtlib.text = 'MultiThreadedDebugDLL'
funclink = ET.SubElement(clconf, 'FunctionLevelLinking')
funclink.text = 'true'
pch = ET.SubElement(clconf, 'PrecompiledHeader')
warnings = ET.SubElement(clconf, 'WarningLevel')
warnings.text = 'Level3'
debinfo = ET.SubElement(clconf, 'DebugInformationFormat')
debinfo.text = 'EditAndContinue'
resourcecompile = ET.SubElement(compiles, 'ResourceCompile')
ET.SubElement(resourcecompile, 'PreprocessorDefinitions')
link = ET.SubElement(compiles, 'Link')
additional_links = []
for t in target.link_targets:
lobj = self.build.targets[t.get_basename()]
rel_path = self.relpath(lobj.subdir, target.subdir)
linkname = os.path.join(rel_path, lobj.get_import_filename())
additional_links.append(linkname)
for o in self.flatten_object_list(target, down):
assert(isinstance(o, str))
additional_links.append(o)
if len(additional_links) > 0:
additional_links.append('%(AdditionalDependencies)')
ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links)
ofile = ET.SubElement(link, 'OutputFile')
ofile.text = '$(OutDir)%s' % target.get_filename()
addlibdir = ET.SubElement(link, 'AdditionalLibraryDirectories')
addlibdir.text = '%(AdditionalLibraryDirectories)'
subsys = ET.SubElement(link, 'SubSystem')
subsys.text = subsystem
gendeb = ET.SubElement(link, 'GenerateDebugInformation')
gendeb.text = 'true'
if isinstance(target, build.SharedLibrary):
ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
pdb = ET.SubElement(link, 'ProgramDataBaseFileName')
pdb.text = '$(OutDir}%s.pdb' % target_name
if isinstance(target, build.Executable):
ET.SubElement(link, 'EntryPointSymbol').text = entrypoint
targetmachine = ET.SubElement(link, 'TargetMachine')
targetmachine.text = 'MachineX86'
if len(headers) + len(gen_hdrs) > 0:
inc_hdrs = ET.SubElement(root, 'ItemGroup')
for h in headers:
relpath = os.path.join(proj_to_src_dir, h)
ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath)
for h in gen_hdrs:
relpath = self.relpath(h, target.subdir)
ET.SubElement(inc_hdrs, 'CLInclude', Include = relpath)
if len(sources) + len(gen_src) > 0:
inc_src = ET.SubElement(root, 'ItemGroup')
for s in sources:
relpath = os.path.join(proj_to_src_dir, s)
ET.SubElement(inc_src, 'CLCompile', Include=relpath)
for s in gen_src:
relpath = self.relpath(s, target.subdir)
ET.SubElement(inc_src, 'CLCompile', Include=relpath)
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
tree = ET.ElementTree(root)
tree.write(ofname, encoding='utf-8', xml_declaration=True)
# ElementTree can not do prettyprinting so do it manually
doc = xml.dom.minidom.parse(ofname)
open(ofname, 'w').write(doc.toprettyxml())
# World of horror! Python insists on not quoting quotes and
# fixing the escaped " into " whereas MSVS
# requires quoted but not fixed elements. Enter horrible hack.
txt = open(ofname, 'r').read()
open(ofname, 'w').write(txt.replace('"', '"'))
def gen_testproj(self, target_name, ofname):
buildtype = 'Debug'
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')
midl = ET.SubElement(action, 'Midl')
ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)'
ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)'
ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h'
ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb'
ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c'
ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c'
postbuild = ET.SubElement(action, 'PostBuildEvent')
ET.SubElement(postbuild, 'Message')
script_root = self.environment.get_script_dir()
test_script = os.path.join(script_root, 'meson_test.py')
test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
cmd_templ = '''setlocal
"%s" "%s" "%s"
if %%errorlevel%% neq 0 goto :cmEnd
:cmEnd
endlocal & call :cmErrorLevel %%errorlevel%% & goto :cmDone
:cmErrorLevel
exit /b %%1
:cmDone
if %%errorlevel%% neq 0 goto :VCEnd'''
ET.SubElement(postbuild, 'Command').text = cmd_templ % (sys.executable, test_script, test_data)
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
tree = ET.ElementTree(root)
tree.write(ofname, encoding='utf-8', xml_declaration=True)
datafile = open(test_data, 'wb')
self.write_test_file(datafile)
datafile.close()
# ElementTree can not do prettyprinting so do it manually
#doc = xml.dom.minidom.parse(ofname)
#open(ofname, 'w').write(doc.toprettyxml())
Loading…
Cancel
Save