aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authors.txt1
-rw-r--r--mesonbuild/backend/vs2010backend.py62
-rw-r--r--mesonbuild/interpreter.py10
-rw-r--r--test cases/common/42 string formatting/meson.build37
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.')