aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/backend
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/backend')
-rw-r--r--mesonbuild/backend/backends.py59
-rw-r--r--mesonbuild/backend/ninjabackend.py141
-rw-r--r--mesonbuild/backend/vs2010backend.py120
-rw-r--r--mesonbuild/backend/xcodebackend.py36
4 files changed, 195 insertions, 161 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 82b387d..54be8ec 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -139,24 +139,34 @@ class Backend():
langlist = {}
abs_files = []
result = []
- for src in unity_src:
- comp = self.get_compiler_for_source(src, target.is_cross)
- language = comp.get_language()
- suffix = '.' + comp.get_default_suffix()
- if language not in langlist:
- outfilename = os.path.join(self.get_target_private_dir_abs(target), target.name + '-unity' + suffix)
- outfileabs = os.path.join(self.environment.get_build_dir(), outfilename)
- outfileabs_tmp = outfileabs + '.tmp'
- abs_files.append(outfileabs)
- outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
- if not os.path.exists(outfileabs_tmp_dir):
- os.makedirs(outfileabs_tmp_dir)
- outfile = open(outfileabs_tmp, 'w')
- langlist[language] = outfile
- result.append(outfilename)
- ofile = langlist[language]
- ofile.write('#include<%s>\n' % src)
- [x.close() for x in langlist.values()]
+
+ def init_language_file(language, suffix):
+ outfilename = os.path.join(self.get_target_private_dir_abs(target),
+ target.name + '-unity' + suffix)
+ outfileabs = os.path.join(self.environment.get_build_dir(),
+ outfilename)
+ outfileabs_tmp = outfileabs + '.tmp'
+ abs_files.append(outfileabs)
+ outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
+ if not os.path.exists(outfileabs_tmp_dir):
+ os.makedirs(outfileabs_tmp_dir)
+ result.append(outfilename)
+ return open(outfileabs_tmp, 'w')
+
+ try:
+ for src in unity_src:
+ comp = self.get_compiler_for_source(src, target.is_cross)
+ language = comp.get_language()
+ try:
+ ofile = langlist[language]
+ except KeyError:
+ suffix = '.' + comp.get_default_suffix()
+ ofile = langlist[language] = init_language_file(language,
+ suffix)
+ ofile.write('#include<%s>\n' % src)
+ finally:
+ for x in langlist.values():
+ x.close()
[mesonlib.replace_if_different(x, x + '.tmp') for x in abs_files]
return result
@@ -215,13 +225,11 @@ class Backend():
def serialise_tests(self):
test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
- datafile = open(test_data, 'wb')
- self.write_test_file(datafile)
- datafile.close()
+ with open(test_data, 'wb') as datafile:
+ self.write_test_file(datafile)
benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat')
- datafile = open(benchmark_data, 'wb')
- self.write_benchmark_file(datafile)
- datafile.close()
+ with open(benchmark_data, 'wb') as datafile:
+ self.write_benchmark_file(datafile)
return (test_data, benchmark_data)
def has_source_suffix(self, target, suffix):
@@ -442,7 +450,8 @@ class Backend():
mfobj = {'type': 'dependency manifest',
'version': '1.0'}
mfobj['projects'] = self.build.dep_manifest
- open(ifilename, 'w').write(json.dumps(mfobj))
+ with open(ifilename, 'w') as f:
+ f.write(json.dumps(mfobj))
d.data.append([ifilename, ofilename])
def get_regen_filelist(self):
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 595fedd..e81c407 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -133,17 +133,18 @@ class NinjaBackend(backends.Backend):
self.all_outputs = {}
self.valgrind = environment.find_valgrind()
- def detect_vs_dep_prefix(self, outfile, tempfilename):
+ def detect_vs_dep_prefix(self, tempfilename):
'''VS writes its dependency in a locale dependent format.
Detect the search prefix to use.'''
# Of course there is another program called 'cl' on
# some platforms. Let's just require that on Windows
# cl points to msvc.
if not mesonlib.is_windows() or shutil.which('cl') is None:
- return outfile
- outfile.close()
- open(os.path.join(self.environment.get_scratch_dir(), 'incdetect.c'),
- 'w').write('''#include<stdio.h>
+ return open(tempfilename, 'a')
+ filename = os.path.join(self.environment.get_scratch_dir(),
+ 'incdetect.c')
+ with open(filename, 'w') as f:
+ f.write('''#include<stdio.h>
int dummy;
''')
@@ -157,9 +158,8 @@ int dummy;
for line in stdo.split(b'\r\n'):
if line.endswith(b'stdio.h'):
matchstr = b':'.join(line.split(b':')[0:2]) + b':'
- binfile = open(tempfilename, 'ab')
- binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n')
- binfile.close()
+ with open(tempfilename, 'ab') as binfile:
+ binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n')
return open(tempfilename, 'a')
raise MesonException('Could not determine vs dep dependency prefix string.')
@@ -167,30 +167,31 @@ int dummy;
self.interpreter = interp
outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
tempfilename = outfilename + '~'
- outfile = open(tempfilename, 'w')
- 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.5.1\n\n')
- outfile = self.detect_vs_dep_prefix(outfile, tempfilename)
- self.generate_rules(outfile)
- self.generate_phony(outfile)
- outfile.write('# Build rules for targets\n\n')
- [self.generate_target(t, outfile) for t in self.build.get_targets().values()]
- outfile.write('# Test rules\n\n')
- self.generate_tests(outfile)
- outfile.write('# Install rules\n\n')
- self.generate_install(outfile)
- if 'b_coverage' in self.environment.coredata.base_options and \
- self.environment.coredata.base_options['b_coverage'].value:
- outfile.write('# Coverage rules\n\n')
- self.generate_coverage_rules(outfile)
- outfile.write('# Suffix\n\n')
- self.generate_utils(outfile)
- self.generate_ending(outfile)
+ with open(tempfilename, 'w') as outfile:
+ 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.5.1\n\n')
+ with self.detect_vs_dep_prefix(tempfilename) as outfile:
+ self.generate_rules(outfile)
+ self.generate_phony(outfile)
+ outfile.write('# Build rules for targets\n\n')
+ for t in self.build.get_targets().values():
+ self.generate_target(t, outfile)
+ outfile.write('# Test rules\n\n')
+ self.generate_tests(outfile)
+ outfile.write('# Install rules\n\n')
+ self.generate_install(outfile)
+ if 'b_coverage' in self.environment.coredata.base_options and \
+ self.environment.coredata.base_options['b_coverage'].value:
+ outfile.write('# Coverage rules\n\n')
+ self.generate_coverage_rules(outfile)
+ outfile.write('# Suffix\n\n')
+ self.generate_utils(outfile)
+ self.generate_ending(outfile)
# Only ovewrite the old build file after the new one has been
# fully created.
- outfile.close()
os.replace(tempfilename, outfilename)
self.generate_compdb()
@@ -202,7 +203,8 @@ int dummy;
jsondb = subprocess.check_output([ninja_exe, '-t', 'compdb', 'c_COMPILER', 'cpp_COMPILER'], cwd=builddir)
except Exception:
raise MesonException('Could not create compilation database.')
- open(os.path.join(builddir, 'compile_commands.json'), 'wb').write(jsondb)
+ with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f:
+ f.write(jsondb)
# Get all generated headers. Any source file might need them so
# we need to add an order dependency to them.
@@ -505,8 +507,8 @@ int dummy;
self.generate_subdir_install(d)
elem.write(outfile)
- ofile = open(install_data_file, 'wb')
- pickle.dump(d, ofile)
+ with open(install_data_file, 'wb') as ofile:
+ pickle.dump(d, ofile)
def generate_target_install(self, d):
should_strip = self.environment.coredata.get_builtin_option('strip')
@@ -1416,16 +1418,22 @@ rule FORTRAN_DEP_HACK
# but those are really rare. I hope.
if not compiler.can_compile(s):
continue
- for line in open(os.path.join(self.environment.get_source_dir(), s.subdir, s.fname)):
- modmatch = modre.match(line)
- if modmatch is not None:
- modname = modmatch.group(1)
- if modname.lower() == 'procedure': # MODULE PROCEDURE construct
- continue
- if modname in module_files:
- raise InvalidArguments('Namespace collision: module %s defined in two files %s and %s.' %
- (modname, module_files[modname], s))
- module_files[modname] = s
+ filename = os.path.join(self.environment.get_source_dir(),
+ s.subdir, s.fname)
+ with open(filename) as f:
+ for line in f:
+ modmatch = modre.match(line)
+ if modmatch is not None:
+ modname = modmatch.group(1)
+ if modname.lower() == 'procedure':
+ # MODULE PROCEDURE construct
+ continue
+ if modname in module_files:
+ raise InvalidArguments(
+ 'Namespace collision: module %s defined in '
+ 'two files %s and %s.' %
+ (modname, module_files[modname], s))
+ module_files[modname] = s
self.fortran_deps[target.get_basename()] = module_files
def get_fortran_deps(self, compiler, src, target):
@@ -1433,27 +1441,32 @@ rule FORTRAN_DEP_HACK
usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE)
dirname = self.get_target_private_dir(target)
tdeps= self.fortran_deps[target.get_basename()]
- for line in open(src):
- usematch = usere.match(line)
- if usematch is not None:
- usename = usematch.group(1)
- if usename not in tdeps:
- # The module is not provided by any source file. This is due to
- # a) missing file/typo/etc
- # b) using a module provided by the compiler, such as OpenMP
- # There's no easy way to tell which is which (that I know of)
- # so just ignore this and go on. Ideally we would print a
- # warning message to the user but this is a common occurrance,
- # which would lead to lots of distracting noise.
- continue
- mod_source_file = tdeps[usename]
- # Check if a source uses a module it exports itself.
- # Potential bug if multiple targets have a file with
- # the same name.
- if mod_source_file.fname == os.path.split(src)[1]:
- continue
- mod_name = compiler.module_name_to_filename(usematch.group(1))
- mod_files.append(os.path.join(dirname, mod_name))
+ with open(src) as f:
+ for line in f:
+ usematch = usere.match(line)
+ if usematch is not None:
+ usename = usematch.group(1)
+ if usename not in tdeps:
+ # The module is not provided by any source file. This
+ # is due to:
+ # a) missing file/typo/etc
+ # b) using a module provided by the compiler, such as
+ # OpenMP
+ # There's no easy way to tell which is which (that I
+ # know of) so just ignore this and go on. Ideally we
+ # would print a warning message to the user but this is
+ # a common occurrence, which would lead to lots of
+ # distracting noise.
+ continue
+ mod_source_file = tdeps[usename]
+ # Check if a source uses a module it exports itself.
+ # Potential bug if multiple targets have a file with
+ # the same name.
+ if mod_source_file.fname == os.path.split(src)[1]:
+ continue
+ mod_name = compiler.module_name_to_filename(
+ usematch.group(1))
+ mod_files.append(os.path.join(dirname, mod_name))
return mod_files
def get_cross_stdlib_args(self, target, compiler):
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 669bcf8..eca7473 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -175,14 +175,18 @@ class Vs2010Backend(backends.Backend):
@staticmethod
def touch_regen_timestamp(build_dir):
- open(Vs2010Backend.get_regen_stampfile(build_dir), 'w').close()
+ with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w'):
+ pass
def generate_regen_info(self):
deps = self.get_regen_filelist()
regeninfo = RegenInfo(self.environment.get_source_dir(),
self.environment.get_build_dir(),
deps)
- pickle.dump(regeninfo, open(os.path.join(self.environment.get_scratch_dir(), 'regeninfo.dump'), 'wb'))
+ filename = os.path.join(self.environment.get_scratch_dir(),
+ 'regeninfo.dump')
+ with open(filename, 'wb') as f:
+ pickle.dump(regeninfo, f)
def get_obj_target_deps(self, obj_list):
result = {}
@@ -217,57 +221,66 @@ class Vs2010Backend(backends.Backend):
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')
- ofile.write('# Visual Studio ' + self.vs_version + '\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 = 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))
- 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')
+ with open(sln_filename, 'w') as ofile:
+ ofile.write('Microsoft Visual Studio Solution File, Format '
+ 'Version 11.00\n')
+ ofile.write('# Visual Studio ' + self.vs_version + '\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 = 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))
+ 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')
- 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')
- regen_line = prj_templ % (self.environment.coredata.guid,
- 'REGEN', 'REGEN.vcxproj', self.environment.coredata.regen_guid)
- ofile.write(regen_line)
- ofile.write('EndProject\n')
- ofile.write('Global\n')
- ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
- ofile.write('\t\t%s|%s = %s|%s\n' % (self.buildtype, self.platform, self.buildtype, self.platform))
- ofile.write('\tEndGlobalSection\n')
- ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
- ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (self.environment.coredata.regen_guid, self.buildtype, self.platform,
- self.buildtype, self.platform))
- ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
- (self.environment.coredata.regen_guid, self.buildtype, self.platform,
- self.buildtype, self.platform))
- for p in projlist:
+ regen_line = prj_templ % (self.environment.coredata.guid,
+ 'REGEN', 'REGEN.vcxproj',
+ self.environment.coredata.regen_guid)
+ ofile.write(regen_line)
+ ofile.write('EndProject\n')
+ ofile.write('Global\n')
+ ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = '
+ 'preSolution\n')
+ ofile.write('\t\t%s|%s = %s|%s\n' %
+ (self.buildtype, self.platform, self.buildtype,
+ self.platform))
+ ofile.write('\tEndGlobalSection\n')
+ ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = '
+ 'postSolution\n')
ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (p[2], self.buildtype, self.platform,
- self.buildtype, self.platform))
- if not isinstance(self.build.targets[p[0]], build.RunTarget):
- ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
+ (self.environment.coredata.regen_guid, self.buildtype,
+ self.platform, self.buildtype, self.platform))
+ ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
+ (self.environment.coredata.regen_guid, self.buildtype,
+ self.platform, self.buildtype, self.platform))
+ for p in projlist:
+ ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
(p[2], self.buildtype, self.platform,
self.buildtype, self.platform))
- ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (self.environment.coredata.test_guid, self.buildtype, self.platform,
- self.buildtype, self.platform))
- ofile.write('\tEndGlobalSection\n')
- ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n')
- ofile.write('\t\tHideSolutionNode = FALSE\n')
- ofile.write('\tEndGlobalSection\n')
- ofile.write('EndGlobal\n')
+ if not isinstance(self.build.targets[p[0]], build.RunTarget):
+ ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
+ (p[2], self.buildtype, self.platform,
+ self.buildtype, self.platform))
+ ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
+ (self.environment.coredata.test_guid, self.buildtype,
+ self.platform, self.buildtype, self.platform))
+ 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 = []
@@ -862,12 +875,15 @@ class Vs2010Backend(backends.Backend):
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())
+ with open(ofname, 'w') as of:
+ of.write(doc.toprettyxml())
# World of horror! Python insists on not quoting quotes and
# fixing the escaped &quot; into &amp;quot; whereas MSVS
# requires quoted but not fixed elements. Enter horrible hack.
- txt = open(ofname, 'r').read()
- open(ofname, 'w').write(txt.replace('&amp;quot;', '&quot;'))
+ with open(ofname, 'r') as of:
+ txt = of.read()
+ with open(ofname, 'w') as of:
+ of.write(txt.replace('&amp;quot;', '&quot;'))
def gen_regenproj(self, project_name, ofname):
root = ET.Element('Project', {'DefaultTargets': 'Build',
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py
index e64866d..b157741 100644
--- a/mesonbuild/backend/xcodebackend.py
+++ b/mesonbuild/backend/xcodebackend.py
@@ -82,26 +82,22 @@ class XCodeBackend(backends.Backend):
self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj')
os.makedirs(self.proj_dir, exist_ok=True)
self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj')
- self.ofile = open(self.proj_file, 'w')
- self.generate_prefix()
- self.generate_pbx_aggregate_target()
- self.generate_pbx_build_file()
- self.generate_pbx_build_style()
- self.generate_pbx_container_item_proxy()
- self.generate_pbx_file_reference()
- self.generate_pbx_group()
- self.generate_pbx_native_target()
- self.generate_pbx_project()
- self.generate_pbx_shell_build_phase(test_data)
- self.generate_pbx_sources_build_phase()
- self.generate_pbx_target_dependency()
- self.generate_xc_build_configuration()
- self.generate_xc_configurationList()
- self.generate_suffix()
-
- # for some reason, the entire file was not being flushed to the disk.
- # closing it explicitly forces a flush and fixes the issue
- self.ofile.close()
+ with open(self.proj_file, 'w') as self.ofile:
+ self.generate_prefix()
+ self.generate_pbx_aggregate_target()
+ self.generate_pbx_build_file()
+ self.generate_pbx_build_style()
+ self.generate_pbx_container_item_proxy()
+ self.generate_pbx_file_reference()
+ self.generate_pbx_group()
+ self.generate_pbx_native_target()
+ self.generate_pbx_project()
+ self.generate_pbx_shell_build_phase(test_data)
+ self.generate_pbx_sources_build_phase()
+ self.generate_pbx_target_dependency()
+ self.generate_xc_build_configuration()
+ self.generate_xc_configurationList()
+ self.generate_suffix()
def get_xcodetype(self, fname):
return self.xcodetypemap[fname.split('.')[-1]]