diff options
Diffstat (limited to 'mesonbuild/backend')
-rw-r--r-- | mesonbuild/backend/backends.py | 59 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 141 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 120 | ||||
-rw-r--r-- | mesonbuild/backend/xcodebackend.py | 36 |
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 " into &quot; whereas MSVS # requires quoted but not fixed elements. Enter horrible hack. - txt = open(ofname, 'r').read() - open(ofname, 'w').write(txt.replace('&quot;', '"')) + with open(ofname, 'r') as of: + txt = of.read() + with open(ofname, 'w') as of: + of.write(txt.replace('&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]] |