vs2010backend: avoid duplicated directory structure in vcxproj.filters

Root the vcxproj.filters at the directory containing the meson.build
defining the target.

Co-authored-by: Joshua Ashton <joshua@froggi.es>
pull/12224/head
Luke Elliott 1 year ago committed by Eli Schwartz
parent 14ac4e3528
commit b6b68d7ee6
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 70
      mesonbuild/backend/vs2010backend.py

@ -20,7 +20,7 @@ import xml.dom.minidom
import xml.etree.ElementTree as ET
import uuid
import typing as T
from pathlib import Path, PurePath
from pathlib import Path, PurePath, PureWindowsPath
import re
from collections import Counter
@ -1809,8 +1809,76 @@ class Vs2010Backend(backends.Backend):
# build system as possible.
self.add_target_deps(root, target)
self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname)
if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror':
self.gen_vcxproj_filters(target, ofname)
return True
def gen_vcxproj_filters(self, target, ofname):
# Generate pitchfork of filters based on directory structure.
root = ET.Element('Project', {'ToolsVersion': '4.0',
'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'})
filter_folders = ET.SubElement(root, 'ItemGroup')
filter_items = ET.SubElement(root, 'ItemGroup')
mlog.debug(f'Generating vcxproj filters {target.name}.')
def relative_to_defined_in(file):
# Get the relative path to file's directory from the location of the meson.build that defines this target.
return os.path.dirname(self.relpath(PureWindowsPath(file.subdir, file.fname), self.get_target_dir(target)))
found_folders_to_filter = {}
all_files = target.sources + target.extra_files
# Build a dictionary of all used relative paths (i.e. from the meson.build defining this target)
# for all sources.
for i in all_files:
if not os.path.isabs(i.fname):
dirname = relative_to_defined_in(i)
if dirname:
found_folders_to_filter[dirname] = ''
# Now walk up each of those relative paths checking for empty intermediate dirs to generate the filter.
for folder in found_folders_to_filter:
dirname = folder
filter = ''
while dirname:
basename = os.path.basename(dirname)
if filter == '':
filter = basename
else:
# Use '/' to squash empty dirs. To actually get a '\', use '%255c'.
filter = basename + ('\\' if dirname in found_folders_to_filter else '/') + filter
dirname = os.path.dirname(dirname)
# Don't add an empty filter, breaks all other (?) filters.
if filter != '':
found_folders_to_filter[folder] = filter
filter_element = ET.SubElement(filter_folders, 'Filter', {'Include': filter})
uuid_element = ET.SubElement(filter_element, 'UniqueIdentifier')
uuid_element.text = '{' + str(uuid.uuid4()).upper() + '}'
sources, headers, objects, _ = self.split_sources(all_files)
down = self.target_to_build_root(target)
def add_element(type_name, elements):
for i in elements:
if not os.path.isabs(i.fname):
dirname = relative_to_defined_in(i)
if dirname and dirname in found_folders_to_filter:
relpath = os.path.join(down, i.rel_to_builddir(self.build_to_src))
target_element = ET.SubElement(filter_items, type_name, {'Include': relpath})
filter_element = ET.SubElement(target_element, 'Filter')
filter_element.text = found_folders_to_filter[dirname]
add_element('ClCompile', sources)
add_element('ClInclude', headers)
add_element('Object', objects)
self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname + '.filters')
def gen_regenproj(self):
# To fully adapt the REGEN work for a 'genvslite' solution, to check timestamps, settings, and regenerate the
# '[builddir]_vs' solution/vcxprojs, as well as regenerating the accompanying buildtype-suffixed ninja build

Loading…
Cancel
Save