diff options
-rw-r--r-- | authors.txt | 1 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 62 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 10 | ||||
-rw-r--r-- | test cases/common/42 string formatting/meson.build | 37 |
4 files changed, 105 insertions, 5 deletions
diff --git a/authors.txt b/authors.txt index 5f79881..d8b0abc 100644 --- a/authors.txt +++ b/authors.txt @@ -32,3 +32,4 @@ Nirbheek Chauhan Nicolas Schneider Luke Adams Rogiel Sulzbach +Tim-Philipp Müller diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 58a7bd3..217bb69 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -14,6 +14,8 @@ import os, sys import pickle + +from mesonbuild import compilers from . import backends from .. import build from .. import dependencies @@ -312,6 +314,24 @@ class Vs2010Backend(backends.Backend): tree = ET.ElementTree(root) tree.write(ofname, encoding='utf-8', xml_declaration=True) + def add_pch(self, inc_cl, proj_to_src_dir, pch_sources, source_file): + if len(pch_sources) <= 1: + # We only need per file precompiled headers if we have more than 1 language. + return + if source_file.split('.')[-1] in compilers.c_suffixes: + lang = 'c' + elif source_file.split('.')[-1] in compilers.cpp_suffixes: + lang = 'cpp' + else: + return + header = os.path.join(proj_to_src_dir, pch_sources[lang][0]) + pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile') + pch_file.text = header + pch_include = ET.SubElement(inc_cl, 'ForcedIncludeFiles') + pch_include.text = header + ';%(ForcedIncludeFiles)' + pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile') + pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % lang + def gen_vcxproj(self, target, ofname, guid, compiler): mlog.debug('Generating vcxproj %s.' % target.name) entrypoint = 'WinMainCRTStartup' @@ -426,7 +446,26 @@ class Vs2010Backend(backends.Backend): rtlib.text = 'MultiThreadedDebugDLL' funclink = ET.SubElement(clconf, 'FunctionLevelLinking') funclink.text = 'true' - pch = ET.SubElement(clconf, 'PrecompiledHeader') + pch_node = ET.SubElement(clconf, 'PrecompiledHeader') + pch_sources = {} + for lang in ['c', 'cpp']: + pch = target.get_pch(lang) + if len(pch) == 0: + continue + pch_node.text = 'Use' + pch_sources[lang] = [pch[0], pch[1], lang] + if len(pch_sources) == 1: + # If there is only 1 language with precompiled headers, we can use it for the entire project, which + # is cleaner than specifying it for each source file. + pch_source = list(pch_sources.values())[0] + header = os.path.join(proj_to_src_dir, pch_source[0]) + pch_file = ET.SubElement(clconf, 'PrecompiledHeaderFile') + pch_file.text = header + pch_include = ET.SubElement(clconf, 'ForcedIncludeFiles') + pch_include.text = header + ';%(ForcedIncludeFiles)' + pch_out = ET.SubElement(clconf, 'PrecompiledHeaderOutputFile') + pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % pch_source[2] + warnings = ET.SubElement(clconf, 'WarningLevel') warnings.text = 'Level3' debinfo = ET.SubElement(clconf, 'DebugInformationFormat') @@ -487,14 +526,29 @@ class Vs2010Backend(backends.Backend): else: relpath = h.rel_to_builddir(proj_to_src_root) ET.SubElement(inc_hdrs, 'CLInclude', Include = relpath) - if len(sources) + len(gen_src) > 0: + if len(sources) + len(gen_src) + len(pch_sources) > 0: inc_src = ET.SubElement(root, 'ItemGroup') for s in sources: relpath = s.rel_to_builddir(proj_to_src_root) - ET.SubElement(inc_src, 'CLCompile', Include=relpath) + inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) + self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s) for s in gen_src: relpath = self.relpath(s, target.subdir) - ET.SubElement(inc_src, 'CLCompile', Include=relpath) + inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) + self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s) + for lang in pch_sources: + header, impl, suffix = pch_sources[lang] + relpath = os.path.join(proj_to_src_dir, impl) + inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) + pch = ET.SubElement(inc_cl, 'PrecompiledHeader') + pch.text = 'Create' + pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile') + pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % suffix + pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile') + # MSBuild searches for the header relative from the implementation, so we have to use + # just the file name instead of the relative path to the file. + pch_file.text = os.path.split(header)[1] + if len(objects) > 0: # Do not add gen_objs to project file. Those are automatically used by MSBuild, because they are part of # the CustomBuildStep Outputs. diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 62b7fc0..14f20e7 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2033,6 +2033,12 @@ class Interpreter(): return obj.strip() elif method_name == 'format': return self.format_string(obj, args) + elif method_name == 'to_upper': + return obj.upper() + elif method_name == 'to_lower': + return obj.lower() + elif method_name == 'underscorify': + return re.sub(r'[^a-zA-Z0-9]', '_', obj) elif method_name == 'split': if len(posargs) > 1: raise InterpreterException('Split() must have at most one argument.') @@ -2043,12 +2049,14 @@ class Interpreter(): return obj.split(s) else: return obj.split() - elif method_name == 'startswith' or method_name == 'endswith': + elif method_name == 'startswith' or method_name == 'contains' or method_name == 'endswith': s = posargs[0] if not isinstance(s, str): raise InterpreterException('Argument must be a string.') if method_name == 'startswith': return obj.startswith(s) + elif method_name == 'contains': + return obj.find(s) >= 0 return obj.endswith(s) elif method_name == 'to_int': try: diff --git a/test cases/common/42 string formatting/meson.build b/test cases/common/42 string formatting/meson.build index 39737f7..56cbcb2 100644 --- a/test cases/common/42 string formatting/meson.build +++ b/test cases/common/42 string formatting/meson.build @@ -41,4 +41,41 @@ if long.endswith(prefix) error('Not suffix.') endif +if not long.contains(prefix) + error('Does not contain prefix') +endif + +if not long.contains(suffix) + error('Does not contain suffix') +endif + +if not long.contains('bcd') + error('Does not contain middle part') +endif + +if long.contains('dc') + error('Broken contains') +endif + +if long.to_upper() != 'ABCDE' + error('Broken to_upper') +endif + +if long.to_upper().to_lower() != long + error('Broken to_lower') +endif + +if 'struct stat.st_foo'.underscorify() != 'struct_stat_st_foo' + error('Broken underscorify') +endif + +if '#include <foo/bar.h>'.underscorify() != '_include__foo_bar_h_' + error('Broken underscorify') +endif + +# case should not change, space should be replaced, numbers are ok too +if 'Do SomeThing 09'.underscorify() != 'Do_SomeThing_09' + error('Broken underscorify') +endif + assert('3'.to_int() == 3, 'String int conversion does not work.') |