in Sharpmake.Generators/VisualStudio/Pyproj.cs [86:276]
private string Generate(PythonProject project, List<Project.Configuration> unsortedConfigurations, string projectPath, string projectFile, out bool updated)
{
var itemGroups = new ItemGroups();
// Need to sort by name and platform
List<Project.Configuration> configurations = new List<Project.Configuration>();
configurations.AddRange(unsortedConfigurations.OrderBy(conf => conf.Name + conf.Platform));
string sourceRootPath = project.IsSourceFilesCaseSensitive ? Util.GetCapitalizedPath(project.SourceRootPath) : project.SourceRootPath;
Resolver resolver = new Resolver();
using (resolver.NewScopedParameter("guid", configurations.First().ProjectGuid))
using (resolver.NewScopedParameter("projectHome", Util.PathGetRelative(projectPath, sourceRootPath)))
using (resolver.NewScopedParameter("startupFile", project.StartupFile))
using (resolver.NewScopedParameter("searchPath", project.SearchPaths.JoinStrings(";")))
{
_project = project;
_projectConfigurationList = configurations;
DevEnvRange devEnvRange = new DevEnvRange(unsortedConfigurations);
bool needsPypatching = devEnvRange.MinDevEnv >= DevEnv.vs2017;
if (!needsPypatching && (devEnvRange.MinDevEnv != devEnvRange.MaxDevEnv))
{
Builder.Instance.LogWarningLine("There are mixed devEnvs for one project. VS2017 or higher Visual Studio solutions will require manual updates.");
}
MemoryStream memoryStream = new MemoryStream();
StreamWriter writer = new StreamWriter(memoryStream);
// xml begin header
Write(Template.Project.ProjectBegin, writer, resolver);
string defaultInterpreterRegisterKeyName = $@"Software\Microsoft\VisualStudio\{devEnvRange.MinDevEnv.GetVisualVersionString()}\PythonTools\Options\Interpreters";
var defaultInterpreter = GetRegistryCurrentUserSubKeyValue(defaultInterpreterRegisterKeyName, "DefaultInterpreter", "{00000000-0000-0000-0000-000000000000}");
var defaultInterpreterVersion = GetRegistryCurrentUserSubKeyValue(defaultInterpreterRegisterKeyName, "DefaultInterpreterVersion", "2.7");
string currentInterpreterId = defaultInterpreter;
string currentInterpreterVersion = defaultInterpreterVersion;
string ptvsTargetsFile = $@"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets";
// environments
foreach (PythonEnvironment pyEnvironment in _project.Environments)
{
if (pyEnvironment.IsActivated)
{
string interpreterRegisterKeyName =
$@"Software\Microsoft\VisualStudio\{devEnvRange.MinDevEnv.GetVisualVersionString()}\PythonTools\Interpreters\{{{pyEnvironment.Guid}}}";
string interpreterDescription = GetRegistryCurrentUserSubKeyValue(interpreterRegisterKeyName, "Description", "");
if (interpreterDescription != string.Empty)
{
currentInterpreterId = $"{{{pyEnvironment.Guid}}}";
currentInterpreterVersion = GetRegistryCurrentUserSubKeyValue(interpreterRegisterKeyName, "Version", currentInterpreterVersion);
}
}
}
// virtual environments
foreach (PythonVirtualEnvironment virtualEnvironment in _project.VirtualEnvironments)
{
if (virtualEnvironment.IsDefault)
{
string baseInterpreterRegisterKeyName =
$@"Software\Microsoft\VisualStudio\{devEnvRange.MinDevEnv.GetVisualVersionString()}\PythonTools\Interpreters\{{{virtualEnvironment.BaseInterpreterGuid}}}";
string baseInterpreterDescription = GetRegistryCurrentUserSubKeyValue(baseInterpreterRegisterKeyName, "Description", "");
if (baseInterpreterDescription != string.Empty)
{
currentInterpreterId = $"{{{virtualEnvironment.Guid}}}";
currentInterpreterVersion = GetRegistryCurrentUserSubKeyValue(baseInterpreterRegisterKeyName, "Version", currentInterpreterVersion);
}
}
}
// Project description
if (needsPypatching)
{
currentInterpreterId = $"MSBuild|debug|$(MSBuildProjectFullPath)";
ptvsTargetsFile = FileGeneratorUtilities.RemoveLineTag;
}
using (resolver.NewScopedParameter("interpreterId", currentInterpreterId))
using (resolver.NewScopedParameter("interpreterVersion", currentInterpreterVersion))
using (resolver.NewScopedParameter("ptvsTargetsFile", ptvsTargetsFile))
{
Write(Template.Project.ProjectDescription, writer, resolver);
}
GenerateItems(writer, resolver);
string baseGuid = FileGeneratorUtilities.RemoveLineTag;
foreach (PythonVirtualEnvironment virtualEnvironment in _project.VirtualEnvironments)
{
baseGuid = needsPypatching ? baseGuid : virtualEnvironment.BaseInterpreterGuid.ToString();
string pyVersion = string.IsNullOrEmpty(virtualEnvironment.Version) ? currentInterpreterVersion : virtualEnvironment.Version;
Write(Template.Project.ProjectItemGroupBegin, writer, resolver);
using (resolver.NewScopedParameter("name", virtualEnvironment.Name))
using (resolver.NewScopedParameter("version", pyVersion))
using (resolver.NewScopedParameter("basePath", virtualEnvironment.Path))
using (resolver.NewScopedParameter("baseGuid", baseGuid))
using (resolver.NewScopedParameter("guid", virtualEnvironment.Guid))
{
Write(Template.Project.VirtualEnvironmentInterpreter, writer, resolver);
}
Write(Template.Project.ProjectItemGroupEnd, writer, resolver);
}
Write(Template.Project.ProjectItemGroupBegin, writer, resolver);
if (_project.Environments.Count > 0)
{
foreach (PythonEnvironment pyEnvironment in _project.Environments)
{
// Verify if the interpreter exists in the register.
string interpreterRegisterKeyName =
$@"Software\Microsoft\VisualStudio\{devEnvRange.MinDevEnv.GetVisualVersionString()}\PythonTools\Interpreters\{{{pyEnvironment.Guid}}}";
string interpreterDescription = GetRegistryCurrentUserSubKeyValue(interpreterRegisterKeyName, "Description", "");
if (interpreterDescription != string.Empty)
{
string interpreterVersion = GetRegistryCurrentUserSubKeyValue(interpreterRegisterKeyName, "Version", currentInterpreterVersion);
using (resolver.NewScopedParameter("guid", $"{{{pyEnvironment.Guid}}}"))
using (resolver.NewScopedParameter("version", interpreterVersion))
{
Write(Template.Project.InterpreterReference, writer, resolver);
}
}
}
}
else if (_project.VirtualEnvironments.Count == 0) // Set the default interpreter
{
using (resolver.NewScopedParameter("guid", currentInterpreterId))
using (resolver.NewScopedParameter("version", currentInterpreterVersion))
{
Write(Template.Project.InterpreterReference, writer, resolver);
}
}
Write(Template.Project.ProjectItemGroupEnd, writer, resolver);
// configuration general
foreach (Project.Configuration conf in _projectConfigurationList)
{
foreach (var dependencies in new[] { conf.ResolvedPublicDependencies, conf.DotNetPrivateDependencies.Select(x => x.Configuration) })
{
foreach (var dependency in dependencies)
{
string relativeToProjectFile = Util.PathGetRelative(sourceRootPath, dependency.ProjectFullFileNameWithExtension);
bool privateDependency = project.DependenciesCopyLocal.HasFlag(Project.DependenciesCopyLocalTypes.ProjectReferences);
conf.GetDependencySetting(dependency.Project.GetType());
itemGroups.ProjectReferences.Add(new ItemGroups.ProjectReference
{
Include = relativeToProjectFile,
Name = dependency.ProjectName,
Private = privateDependency ? "True" : "False",
Project = new Guid(dependency.ProjectGuid)
});
}
}
}
GenerateFolders(writer, resolver);
// Import native Python Tools project
if (needsPypatching)
{
Write(Template.Project.ImportPythonTools, writer, resolver);
}
writer.Write(itemGroups.Resolve(resolver));
Write(Template.Project.ProjectEnd, writer, resolver);
// Write the project file
writer.Flush();
// remove all line that contain RemoveLineTag
memoryStream = Util.RemoveLineTags(memoryStream, FileGeneratorUtilities.RemoveLineTag);
memoryStream.Seek(0, SeekOrigin.Begin);
FileInfo projectFileInfo = new FileInfo(projectPath + @"\" + projectFile + ProjectExtension);
updated = _builder.Context.WriteGeneratedFile(project.GetType(), projectFileInfo, memoryStream);
writer.Close();
_project = null;
return projectFileInfo.FullName;
}
}