vs2010: support multiple precompiled headers (one per language)

This creates the PrecompiledHeader properties for every source file in the
project if multiple languages are present. Otherwise, the global pch
settings are used.
The pch to use is determined by checking the suffix of the source file.
pull/440/head
Nicolas Schneider 9 years ago
parent 5ba7680a0d
commit 49418cfe8a
  1. 62
      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'
@ -427,19 +447,25 @@ class Vs2010Backend(backends.Backend):
funclink = ET.SubElement(clconf, 'FunctionLevelLinking')
funclink.text = 'true'
pch_node = ET.SubElement(clconf, 'PrecompiledHeader')
pch_sources = []
pch_sources = {}
for lang in ['c', 'cpp']:
pch = target.get_pch(lang)
if len(pch) == 0:
continue
if len(pch_sources) > 0:
raise MesonException('VS2010 backend does not support multiple precompiled header files.')
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 = pch[0]
pch_file.text = header
pch_include = ET.SubElement(clconf, 'ForcedIncludeFiles')
pch_include.text = pch[0] + ';%(ForcedIncludeFiles)'
pch_sources.append(pch[1])
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')
@ -504,15 +530,25 @@ class Vs2010Backend(backends.Backend):
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)
for s in pch_sources:
relpath = os.path.join(proj_to_src_dir, s)
comp_pch = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
pch = ET.SubElement(comp_pch, 'PrecompiledHeader')
pch.text = 'Create'
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.

Loading…
Cancel
Save