summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Elliott <luke.b.elliott@gmail.com>2023-08-09 08:39:08 +0100
committerEli Schwartz <eschwartz93@gmail.com>2023-09-26 02:29:25 -0400
commitb6b68d7ee687682ce529617e8ace48b582d0dbf1 (patch)
tree3ebd5e64c02c7717cdef54c8abb23e02c5507c02
parent14ac4e3528bfcf5d12c20020fab7dbf95757e8a8 (diff)
downloadmeson-b6b68d7ee687682ce529617e8ace48b582d0dbf1.tar.gz
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>
-rw-r--r--mesonbuild/backend/vs2010backend.py70
1 files changed, 69 insertions, 1 deletions
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 943dffa4f..0b6be1c79 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/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