diff options
author | Niklas Claesson <niklas.claesson@cosylab.com> | 2018-01-31 11:27:37 +0100 |
---|---|---|
committer | Niklas Claesson <niklas.claesson@cosylab.com> | 2018-04-17 23:41:03 +0200 |
commit | c6e03b953530e111c99b25b01bcd59d176703dd6 (patch) | |
tree | 1a2cbd35c5cedd40a464e208546ef748b4367c56 /mesonbuild | |
parent | e50a5c1311efeeb02ee06435b21389131eb97bdf (diff) | |
download | meson-c6e03b953530e111c99b25b01bcd59d176703dd6.zip meson-c6e03b953530e111c99b25b01bcd59d176703dd6.tar.gz meson-c6e03b953530e111c99b25b01bcd59d176703dd6.tar.bz2 |
Use visual studio solution directories
This implements support for visual studio solution directories.
Projects will by default be put into directories that map their sub-directory
name in the source folder. No directories are created if `--layout=flat` is used.
Fixes: #2524
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 82 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 8 | ||||
-rw-r--r-- | mesonbuild/minit.py | 8 |
3 files changed, 77 insertions, 21 deletions
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 6ea898d..3a12b9b 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -16,6 +16,8 @@ import os import pickle import xml.dom.minidom import xml.etree.ElementTree as ET +import uuid +from pathlib import Path, PurePath from . import backends from .. import build @@ -81,6 +83,7 @@ class Vs2010Backend(backends.Backend): self.platform_toolset = None self.vs_version = '2010' self.windows_target_platform_version = None + self.subdirs = {} def generate_custom_generator_commands(self, target, parent_node): generator_output_files = [] @@ -225,6 +228,26 @@ class Vs2010Backend(backends.Backend): ret.update(all_deps) return ret + def generate_solution_dirs(self, ofile, parents): + prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' + iterpaths = reversed(parents) + # Skip first path + next(iterpaths) + for path in iterpaths: + if path not in self.subdirs: + basename = path.name + identifier = str(uuid.uuid4()).upper() + # top-level directories have None as their parent_dir + parent_dir = path.parent + parent_identifier = self.subdirs[parent_dir][0] \ + if parent_dir != PurePath('.') else None + self.subdirs[path] = (identifier, parent_identifier) + prj_line = prj_templ % ( + self.environment.coredata.lang_guids['directory'], + basename, basename, self.subdirs[path][0]) + ofile.write(prj_line) + ofile.write('EndProject\n') + def generate_solution(self, sln_filename, projlist): default_projlist = self.get_build_by_default_targets() with open(sln_filename, 'w', encoding='utf-8') as ofile: @@ -232,16 +255,26 @@ class Vs2010Backend(backends.Backend): 'Version 11.00\n') ofile.write('# Visual Studio ' + self.vs_version + '\n') prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' - for p in projlist: - prj_line = prj_templ % (self.environment.coredata.guid, - p[0], p[1], p[2]) + for prj in projlist: + coredata = self.environment.coredata + if coredata.get_builtin_option('layout') == 'mirror': + self.generate_solution_dirs(ofile, prj[1].parents) + target = self.build.targets[prj[0]] + lang = 'default' + if hasattr(target, 'compilers') and target.compilers: + for (lang_out, _) in target.compilers.items(): + lang = lang_out + break + prj_line = prj_templ % ( + self.environment.coredata.lang_guids[lang], + prj[0], prj[1], prj[2]) ofile.write(prj_line) - target = self.build.targets[p[0]] - t = {target.get_id(): target} + target_dict = {target.get_id(): target} # Get direct deps - all_deps = self.get_target_deps(t) + all_deps = self.get_target_deps(target_dict) # Get recursive deps - recursive_deps = self.get_target_deps(t, recursive=True) + recursive_deps = self.get_target_deps( + target_dict, recursive=True) ofile.write('\tProjectSection(ProjectDependencies) = ' 'postProject\n') regen_guid = self.environment.coredata.regen_guid @@ -252,14 +285,15 @@ class Vs2010Backend(backends.Backend): ofile.write('EndProjectSection\n') ofile.write('EndProject\n') for dep, target in recursive_deps.items(): - if p[0] in default_projlist: + if prj[0] in default_projlist: default_projlist[dep] = target - test_line = prj_templ % (self.environment.coredata.guid, + + test_line = prj_templ % (self.environment.coredata.lang_guids['default'], 'RUN_TESTS', 'RUN_TESTS.vcxproj', self.environment.coredata.test_guid) ofile.write(test_line) ofile.write('EndProject\n') - regen_line = prj_templ % (self.environment.coredata.guid, + regen_line = prj_templ % (self.environment.coredata.lang_guids['default'], 'REGEN', 'REGEN.vcxproj', self.environment.coredata.regen_guid) ofile.write(regen_line) @@ -298,19 +332,33 @@ class Vs2010Backend(backends.Backend): ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n') ofile.write('\t\tHideSolutionNode = FALSE\n') ofile.write('\tEndGlobalSection\n') + if self.subdirs: + ofile.write('\tGlobalSection(NestedProjects) = ' + 'preSolution\n') + for p in projlist: + if p[1].parent != PurePath('.'): + ofile.write("\t\t{%s} = {%s}\n" % (p[2], self.subdirs[p[1].parent][0])) + for (_, subdir) in self.subdirs.items(): + if subdir[1]: + ofile.write("\t\t{%s} = {%s}\n" % (subdir[0], subdir[1])) + ofile.write('\tEndGlobalSection\n') ofile.write('EndGlobal\n') def generate_projects(self): projlist = [] for name, target in self.build.targets.items(): - outdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) - os.makedirs(outdir, exist_ok=True) + outdir = Path( + self.environment.get_build_dir(), + self.get_target_dir(target) + ) + outdir.mkdir(exist_ok=True, parents=True) fname = name + '.vcxproj' - relname = os.path.join(self.get_target_dir(target), fname) - projfile = os.path.join(outdir, fname) - uuid = self.environment.coredata.target_guids[name] - self.gen_vcxproj(target, projfile, uuid) - projlist.append((name, relname, uuid)) + target_dir = PurePath(self.get_target_dir(target)) + relname = target_dir / fname + projfile_path = outdir / fname + proj_uuid = self.environment.coredata.target_guids[name] + self.gen_vcxproj(target, str(projfile_path), proj_uuid) + projlist.append((name, relname, proj_uuid)) return projlist def split_sources(self, srclist): diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index ba4f495..4887125 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -166,7 +166,13 @@ This will become a hard error in the future.''') class CoreData: def __init__(self, options): - self.guid = str(uuid.uuid4()).upper() + self.lang_guids = { + 'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', + 'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', + 'cpp': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', + 'test': '3AC096D0-A1C2-E12C-1390-A8335801FDAB', + 'directory': '2150E333-8FDC-42A3-9474-1A3956D46DE8', + } self.test_guid = str(uuid.uuid4()).upper() self.regen_guid = str(uuid.uuid4()).upper() self.target_guids = {} diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 0461cd9..1a83ed2 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -14,7 +14,7 @@ """Code that creates simple startup projects.""" -import os, sys, argparse, re, shutil +import os, sys, argparse, re, shutil, subprocess from glob import glob from mesonbuild import mesonlib from mesonbuild.environment import detect_ninja @@ -471,10 +471,12 @@ def run(args): print('Build directory already exists, deleting it.') shutil.rmtree(options.builddir) print('Building...') - err = os.system('{} "{}"'.format(' '.join(mesonlib.meson_command), options.builddir)) + cmd = mesonlib.meson_command + [options.builddir] + err = subprocess.call(cmd) if err: sys.exit(1) - err = os.system('{} -C "{}"'.format(detect_ninja(), options.builddir)) + cmd = [detect_ninja(), '-C', options.builddir] + err = subprocess.call(cmd) if err: sys.exit(1) return 0 |