in Sharpmake.Generators/VisualStudio/Vcxproj.cs [1339:2034]
private void GenerateFilesSection(
GenerationContext context,
IFileGenerator fileGenerator,
IList<string> generatedFiles,
IList<string> skipFiles
)
{
string filtersFileName = context.ProjectPath + ProjectExtension + ProjectFilterExtension;
string copyDependenciesFileName = context.ProjectPath + CopyDependenciesExtension;
string relativeCopyDependenciesFileName = Util.PathGetRelative(context.ProjectDirectory, copyDependenciesFileName, false);
Strings projectFiles = context.Project.GetSourceFilesForConfigurations(context.ProjectConfigurations);
// Add source files
var allFiles = new List<ProjectFile>();
var includeFiles = new List<ProjectFile>();
var sourceFiles = new List<ProjectFile>();
var NatvisFiles = new List<ProjectFile>();
var PRIFiles = new List<ProjectFile>();
var NoneFiles = new List<ProjectFile>();
var XResourcesReswFiles = new List<ProjectFile>();
var XResourcesImgFiles = new List<ProjectFile>();
var customBuildFiles = new List<ProjectFile>();
foreach (string file in context.Project.NatvisFiles)
{
var natvisFile = new ProjectFile(context, file);
NatvisFiles.Add(natvisFile);
}
foreach (string file in context.Project.NoneFiles)
{
var priFile = new ProjectFile(context, file);
NoneFiles.Add(priFile);
}
foreach (string file in projectFiles)
{
var projectFile = new ProjectFile(context, file);
allFiles.Add(projectFile);
}
allFiles.Sort((l, r) => { return string.Compare(l.FileNameProjectRelative, r.FileNameProjectRelative, StringComparison.InvariantCultureIgnoreCase); });
// Gather files with custom build steps.
var configurationCustomFileBuildSteps = new Dictionary<Project.Configuration, Dictionary<string, CombinedCustomFileBuildStep>>();
Strings configurationCustomBuildFiles = new Strings();
using (Builder.Instance.CreateProfilingScope("GenerateFilesSection:confs1", context.ProjectConfigurations.Count))
{
foreach (Project.Configuration config in context.ProjectConfigurations)
{
using (fileGenerator.Resolver.NewScopedParameter("project", context.Project))
using (fileGenerator.Resolver.NewScopedParameter("config", config))
using (fileGenerator.Resolver.NewScopedParameter("target", config.Target))
{
var customFileBuildSteps = CombineCustomFileBuildSteps(context.ProjectDirectory, fileGenerator.Resolver, config.CustomFileBuildSteps.Where(step => step.Filter != Project.Configuration.CustomFileBuildStep.ProjectFilter.BFFOnly));
configurationCustomFileBuildSteps.Add(config, customFileBuildSteps);
foreach (var customBuildSetup in customFileBuildSteps)
{
configurationCustomBuildFiles.Add(customBuildSetup.Key);
}
}
}
}
// type -> files
var customSourceFiles = new Dictionary<string, List<ProjectFile>>();
using (Builder.Instance.CreateProfilingScope("GenerateFilesSection:allFiles", allFiles.Count))
{
foreach (var projectFile in allFiles)
{
string type = null;
if (context.Project.ExtensionBuildTools.TryGetValue(projectFile.FileExtension, out type))
{
List<ProjectFile> files = null;
if (!customSourceFiles.TryGetValue(type, out files))
{
files = new List<ProjectFile>();
customSourceFiles[type] = files;
}
files.Add(projectFile);
}
else if (configurationCustomBuildFiles.Contains(projectFile.FileNameProjectRelative))
{
customBuildFiles.Add(projectFile);
}
else if (context.Project.SourceFilesCompileExtensions.Contains(projectFile.FileExtension) ||
(string.Compare(projectFile.FileExtension, ".rc", StringComparison.OrdinalIgnoreCase) == 0))
{
sourceFiles.Add(projectFile);
}
else // if (projectFile.FileExtension == "h")
{
includeFiles.Add(projectFile);
}
}
}
// Write header files
fileGenerator.Write(Template.Project.ProjectFilesBegin);
bool hasCustomBuildForAllIncludes = context.ProjectConfigurations.First().CustomBuildForAllIncludes != null;
if (hasCustomBuildForAllIncludes)
{
foreach (var file in includeFiles)
{
using (fileGenerator.Declare("file", file.FileNameProjectRelative))
using (fileGenerator.Declare("filetype", FileGeneratorUtilities.RemoveLineTag))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildBegin);
foreach (Project.Configuration conf in context.ProjectConfigurations)
{
if (conf.CustomBuildForAllIncludes == null)
continue;
using (fileGenerator.Declare("conf", conf))
using (fileGenerator.Declare("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
using (fileGenerator.Declare("description", conf.CustomBuildForAllIncludes.Description))
using (fileGenerator.Declare("command", conf.CustomBuildForAllIncludes.CommandLines.JoinStrings(Environment.NewLine, escapeXml: true)))
using (fileGenerator.Declare("inputs", FileGeneratorUtilities.RemoveLineTag))
using (fileGenerator.Declare("outputs", conf.CustomBuildForAllIncludes.Outputs.JoinStrings(";")))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildDescription);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildCommand);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildInputs);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildOutputs);
}
}
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildEnd);
}
}
}
else
{
foreach (var file in includeFiles)
{
using (fileGenerator.Declare("file", file))
fileGenerator.Write(Template.Project.ProjectFilesHeader);
}
}
fileGenerator.Write(Template.Project.ProjectFilesEnd);
if (customBuildFiles.Count > 0)
{
// Write custom build steps
fileGenerator.Write(Template.Project.ProjectFilesBegin);
foreach (var file in customBuildFiles)
{
using (fileGenerator.Declare("file", file.FileNameProjectRelative))
using (fileGenerator.Declare("filetype", FileGeneratorUtilities.RemoveLineTag))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildBegin);
foreach (Project.Configuration conf in context.ProjectConfigurations)
{
CombinedCustomFileBuildStep buildStep;
if (configurationCustomFileBuildSteps[conf].TryGetValue(file.FileNameProjectRelative, out buildStep))
{
using (fileGenerator.Declare("conf", conf))
using (fileGenerator.Declare("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
using (fileGenerator.Declare("description", buildStep.Description))
using (fileGenerator.Declare("command", buildStep.Commands))
using (fileGenerator.Declare("inputs", buildStep.AdditionalInputs))
using (fileGenerator.Declare("outputs", buildStep.Outputs))
using (fileGenerator.Declare("outputItemType", string.IsNullOrEmpty(buildStep.OutputItemType) ? FileGeneratorUtilities.RemoveLineTag : buildStep.OutputItemType))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildDescription);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildCommand);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildInputs);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildOutputs);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildOutputItemType);
}
}
}
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildEnd);
}
}
fileGenerator.Write(Template.Project.ProjectFilesEnd);
}
// Write natvis files
if (context.Project.NatvisFiles.Count > 0 && context.ProjectConfigurations.Any(conf => conf.Target.HaveFragment<DevEnv>() && conf.Target.GetFragment<DevEnv>() >= DevEnv.vs2015))
{
fileGenerator.Write(Template.Project.ProjectFilesBegin);
foreach (var file in NatvisFiles)
{
using (fileGenerator.Declare("file", file))
fileGenerator.Write(Template.Project.ProjectFilesNatvis);
}
fileGenerator.Write(Template.Project.ProjectFilesEnd);
}
// Write PRI files
var writtenPRIFiles = new Strings();
if (context.Project.PRIFiles.Count > 0)
{
fileGenerator.Write(Template.Project.ProjectFilesBegin);
foreach (string file in context.Project.PRIFiles.SortedValues)
{
var priFile = new ProjectFile(context, file);
PRIFiles.Add(priFile);
writtenPRIFiles.Add(priFile.FileNameProjectRelative);
using (fileGenerator.Declare("file", priFile))
fileGenerator.Write(Template.Project.ProjectFilesPRIResources);
}
fileGenerator.Write(Template.Project.ProjectFilesEnd);
}
// Write None files
if (context.Project.NoneFiles.Count > 0)
{
fileGenerator.Write(Template.Project.ProjectFilesBegin);
foreach (string file in context.Project.NoneFiles)
{
var projectFile = new ProjectFile(context, file);
using (fileGenerator.Declare("file", projectFile))
fileGenerator.Write(Template.Project.ProjectFilesNone);
}
fileGenerator.Write(Template.Project.ProjectFilesEnd);
}
foreach (var platform in context.PresentPlatforms.Values)
{
platform.GeneratePlatformResourceFileList(context, fileGenerator, writtenPRIFiles, XResourcesReswFiles, XResourcesImgFiles);
var customPlatformFiles = platform.GetPlatformFileLists(context);
foreach (var tuple in customPlatformFiles)
{
string type = tuple.Item1;
var files = tuple.Item2;
customSourceFiles.GetValueOrAdd(type, new List<ProjectFile>()).AddRange(files);
}
}
fileGenerator.Write(Template.Project.ProjectFilesBegin);
// Validation map
var configurationCompiledFiles = new List<List<ProjectFile>>();
foreach (Project.Configuration conf in context.ProjectConfigurations)
configurationCompiledFiles.Add(new List<ProjectFile>());
bool hasCustomBuildForAllSources = context.ProjectConfigurations.First().CustomBuildForAllSources != null;
if (hasCustomBuildForAllSources)
{
foreach (var file in sourceFiles)
{
using (fileGenerator.Declare("file", file.FileNameProjectRelative))
using (fileGenerator.Declare("filetype", FileGeneratorUtilities.RemoveLineTag))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildBegin);
foreach (Project.Configuration conf in context.ProjectConfigurations)
{
if (conf.CustomBuildForAllSources == null)
continue;
using (fileGenerator.Declare("conf", conf))
using (fileGenerator.Declare("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
using (fileGenerator.Declare("description", conf.CustomBuildForAllSources.Description))
using (fileGenerator.Declare("command", conf.CustomBuildForAllSources.CommandLines.JoinStrings(Environment.NewLine, escapeXml: true)))
using (fileGenerator.Declare("inputs", FileGeneratorUtilities.RemoveLineTag))
using (fileGenerator.Declare("outputs", conf.CustomBuildForAllSources.Outputs.JoinStrings(";")))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildDescription);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildCommand);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildInputs);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildOutputs);
}
}
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildEnd);
}
}
}
else
{
// Write source files
foreach (var file in sourceFiles)
{
using (fileGenerator.Declare("file", file))
using (fileGenerator.Declare("filetype", FileGeneratorUtilities.RemoveLineTag))
{
bool isResource = string.Compare(file.FileExtension, ".rc", StringComparison.OrdinalIgnoreCase) == 0;
if (isResource)
fileGenerator.Write(Template.Project.ProjectFilesResourceBegin);
else
fileGenerator.Write(Template.Project.ProjectFilesSourceBegin);
bool haveFileOptions = false;
bool closeFileSource = true;
for (int i = 0; i < context.ProjectConfigurations.Count; ++i)
{
Project.Configuration conf = context.ProjectConfigurations[i];
context.Configuration = conf;
var platformVcxproj = context.PresentPlatforms[conf.Platform];
var compiledFiles = configurationCompiledFiles[i];
bool hasPrecomp = platformVcxproj.HasPrecomp(context);
bool isPrecompSource = !string.IsNullOrEmpty(conf.PrecompSource) && file.FileName.EndsWith(conf.PrecompSource, StringComparison.OrdinalIgnoreCase);
bool isDontUsePrecomp = conf.PrecompSourceExclude.Contains(file.FileName) ||
conf.PrecompSourceExcludeFolders.Any(folder => file.FileName.StartsWith(folder, StringComparison.OrdinalIgnoreCase)) ||
conf.PrecompSourceExcludeExtension.Contains(file.FileExtension);
bool hasForcedIncludes = conf.ForcedIncludesFilters.Any(filter => filter.IsValid(file.FileName));
bool isExcludeFromBuild = conf.ResolvedSourceFilesBuildExclude.Contains(file.FileName);
bool consumeWinRTExtensions = conf.ConsumeWinRTExtensions.Contains(file.FileName) || conf.ResolvedSourceFilesWithCompileAsWinRTOption.Contains(file.FileName);
bool excludeWinRTExtensions = conf.ExcludeWinRTExtensions.Contains(file.FileName) || conf.ResolvedSourceFilesWithExcludeAsWinRTOption.Contains(file.FileName);
bool isBlobFileDefine = conf.BlobFileDefine != string.Empty && file.FileName.EndsWith(Project.BlobExtension, StringComparison.OrdinalIgnoreCase);
bool isResourceFileDefine = conf.ResourceFileDefine != string.Empty && file.FileName.EndsWith(".rc", StringComparison.OrdinalIgnoreCase);
bool isCompileAsCFile = conf.ResolvedSourceFilesWithCompileAsCOption.Contains(file.FileName);
bool isCompileAsCPPFile = conf.ResolvedSourceFilesWithCompileAsCPPOption.Contains(file.FileName);
bool isCompileAsCLRFile = conf.ResolvedSourceFilesWithCompileAsCLROption.Contains(file.FileName);
bool isCompileAsNonCLRFile = conf.ResolvedSourceFilesWithCompileAsNonCLROption.Contains(file.FileName);
bool objsInSubdirectories = conf.ObjectFileName != null && !isResource;
bool isExcludeFromGenerateXmlDocumentation = conf.ResolvedSourceFilesGenerateXmlDocumentationExclude.Contains(file.FileName);
if (isPrecompSource && platformVcxproj.ExcludesPrecompiledHeadersFromBuild)
isExcludeFromBuild = true;
if (!isExcludeFromBuild && !isResource)
compiledFiles.Add(file);
if (isCompileAsCLRFile || consumeWinRTExtensions || excludeWinRTExtensions)
isDontUsePrecomp = true;
if (string.Compare(file.FileExtension, ".c", StringComparison.OrdinalIgnoreCase) == 0)
isDontUsePrecomp = true;
string exceptionSetting = null;
switch (conf.GetExceptionSettingForFile(file.FileName))
{
case Sharpmake.Options.Vc.Compiler.Exceptions.Enable:
exceptionSetting = "Sync";
break;
case Sharpmake.Options.Vc.Compiler.Exceptions.EnableWithExternC:
exceptionSetting = "SyncCThrow";
break;
case Sharpmake.Options.Vc.Compiler.Exceptions.EnableWithSEH:
exceptionSetting = "Async";
break;
}
bool hasExceptionSetting = !string.IsNullOrEmpty(exceptionSetting);
haveFileOptions = haveFileOptions ||
isExcludeFromBuild ||
isPrecompSource ||
(isDontUsePrecomp && hasPrecomp) ||
hasForcedIncludes ||
isBlobFileDefine ||
isResourceFileDefine ||
isCompileAsCFile ||
isCompileAsCPPFile ||
isCompileAsNonCLRFile ||
hasExceptionSetting ||
consumeWinRTExtensions ||
excludeWinRTExtensions ||
objsInSubdirectories;
if (haveFileOptions)
{
using (fileGenerator.Declare("conf", conf))
using (fileGenerator.Declare("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
{
if (closeFileSource)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceBeginOptions);
closeFileSource = false;
}
if (isBlobFileDefine)
{
using (fileGenerator.Declare("ProjectFilesSourceDefine", conf.BlobFileDefine))
fileGenerator.Write(Template.Project.ProjectFilesSourceDefine);
}
if (isResourceFileDefine)
{
using (fileGenerator.Declare("ProjectFilesSourceDefine", conf.ResourceFileDefine))
fileGenerator.Write(Template.Project.ProjectFilesSourceDefine);
}
if (isExcludeFromBuild)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceExcludeFromBuild);
}
else
{
if (isCompileAsCFile)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceCompileAsC);
}
else if (isCompileAsCPPFile)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceCompileAsCPP);
}
else if (isCompileAsCLRFile)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceCompileAsCLR);
}
if (isCompileAsNonCLRFile)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceDoNotCompileAsCLR);
}
bool writeVanillaForcedInclude = false;
if (isPrecompSource)
{
fileGenerator.Write(Template.Project.ProjectFilesSourcePrecompCreate);
}
else if (isDontUsePrecomp && hasPrecomp)
{
fileGenerator.Write(Template.Project.ProjectFilesSourcePrecompNotUsing);
// in case we are using the LLVM toolchain, the PCH was added
// as force include globally for the conf, so we need
// to use the forced include vanilla list that we prepared
var optionsForConf = context.ProjectConfigurationOptions[conf];
if (optionsForConf.ContainsKey("ForcedIncludeFilesVanilla"))
{
// Note: faster to test that the options array has the
// vanilla list, as we only add it in case we use LLVM,
// but we could also have tested
// Options.GetObject<Options.Vc.General.PlatformToolset>(conf).IsLLVMToolchain()
writeVanillaForcedInclude = true;
}
}
if (hasForcedIncludes)
{
Strings forcedIncludes = new Strings(conf.ForcedIncludesFilters
.Where(filter => filter.IsValid(file.FileName))
.SelectMany(filter => filter.ForcedIncludes));
var optionsForConf = context.ProjectConfigurationOptions[conf];
using (fileGenerator.Declare("ForcedIncludeFiles", forcedIncludes.JoinStrings(";")))
using (fileGenerator.Declare("options", optionsForConf))
{
if (writeVanillaForcedInclude)
{
fileGenerator.Write(Template.Project.ProjectFilesAdditionalForcedIncludeVanilla);
}
else
{
fileGenerator.Write(Template.Project.ProjectFilesAdditionalForcedInclude);
}
}
}
else if (writeVanillaForcedInclude)
{
var optionsForConf = context.ProjectConfigurationOptions[conf];
using (fileGenerator.Declare("options", optionsForConf))
fileGenerator.Write(Template.Project.ProjectFilesForcedIncludeVanilla);
}
if (consumeWinRTExtensions)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceConsumeWinRTExtensions);
}
if (hasExceptionSetting)
{
using (fileGenerator.Declare("exceptionSetting", exceptionSetting))
{
fileGenerator.Write(Template.Project.ProjectFilesSourceEnableExceptions);
}
}
if (excludeWinRTExtensions)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceExcludeWinRTExtensions);
}
if (objsInSubdirectories)
{
string objectFileName = conf.ObjectFileName(file.FileNameSourceRelative);
if (!string.IsNullOrEmpty(objectFileName))
{
using (fileGenerator.Declare("ObjectFileName", objectFileName))
{
fileGenerator.Write(Template.Project.ProjectFilesSourceObjectFileName);
}
}
}
if (isExcludeFromGenerateXmlDocumentation)
{
fileGenerator.Write(Template.Project.ProjectFilesSourceExcludeGenerateXmlDocumentation);
}
}
}
}
}
if (haveFileOptions)
{
if (isResource)
fileGenerator.Write(Template.Project.ProjectFilesResourceEnd);
else
fileGenerator.Write(Template.Project.ProjectFilesSourceEndOptions);
}
else
fileGenerator.Write(Template.Project.ProjectFilesSourceEnd);
}
}
}
// Write files built with custom tools
var typeNames = new List<string>(customSourceFiles.Keys);
typeNames.Sort();
foreach (string typeName in typeNames)
{
fileGenerator.Write(Template.Project.ProjectFilesEnd);
fileGenerator.Write(Template.Project.ProjectFilesBegin);
using (fileGenerator.Declare("type", typeName))
{
var files = customSourceFiles[typeName];
foreach (var file in files)
{
using (fileGenerator.Declare("file", file))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomSourceBegin);
bool haveFileOptions = false;
for (int i = 0; i < context.ProjectConfigurations.Count; ++i)
{
Project.Configuration conf = context.ProjectConfigurations[i];
using (fileGenerator.Declare("conf", conf))
using (fileGenerator.Declare("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
{
var compiledFiles = configurationCompiledFiles[i];
bool isExcludeFromBuild = conf.ResolvedSourceFilesBuildExclude.Contains(file.FileName);
if (isExcludeFromBuild)
{
if (!haveFileOptions)
{
fileGenerator.Write(Template.Project.ProjectFilesCustomSourceBeginOptions);
haveFileOptions = true;
}
fileGenerator.Write(Template.Project.ProjectFilesSourceExcludeFromBuild);
}
}
}
if (haveFileOptions)
fileGenerator.Write(Template.Project.ProjectFilesCustomSourceEndOptions);
else
fileGenerator.Write(Template.Project.ProjectFilesCustomSourceEnd);
}
}
}
}
var copyDependenciesBuildStepDictionary = new Dictionary<Project.Configuration, Project.Configuration.FileCustomBuild>();
foreach (var conf in context.ProjectConfigurations)
{
if (conf.IsFastBuild) // copies handled in bff
continue;
if (conf.Output != Project.Configuration.OutputType.Exe && !conf.ExecuteTargetCopy)
continue;
var copies = ProjectOptionsGenerator.ConvertPostBuildCopiesToRelative(conf, context.ProjectDirectory);
if (!copies.Any())
continue;
var copyDependenciesBuildStep = copyDependenciesBuildStepDictionary.GetValueOrAdd(conf, new Project.Configuration.FileCustomBuild("Copy files to output paths..."));
if (conf.CopyDependenciesBuildStep != null)
copyDependenciesBuildStep = conf.CopyDependenciesBuildStep;
foreach (var copy in copies)
{
var sourceFile = copy.Key;
var destinationFolder = copy.Value;
copyDependenciesBuildStep.CommandLines.Add(conf.CreateTargetCopyCommand(sourceFile, destinationFolder, context.ProjectDirectory));
copyDependenciesBuildStep.Inputs.Add(sourceFile);
copyDependenciesBuildStep.Outputs.Add(Path.Combine(destinationFolder, Path.GetFileName(sourceFile)));
}
}
// Write the "copy dependencies" build step (as a custom build tool on a dummy file, to make sure the copy is always done when needed)
bool hasDependenciesToCopy = copyDependenciesBuildStepDictionary.Any();
var dependenciesFileGenerator = new XmlFileGenerator(fileGenerator.Resolver); // borrowing resolver
if (hasDependenciesToCopy)
{
fileGenerator.Write(Template.Project.ProjectFilesEnd);
fileGenerator.Write(Template.Project.ProjectFilesBegin);
using (fileGenerator.Declare("file", relativeCopyDependenciesFileName))
using (fileGenerator.Declare("filetype", "Document"))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildBegin);
foreach (var pair in copyDependenciesBuildStepDictionary)
{
var conf = pair.Key;
Project.Configuration.FileCustomBuild copyDependencies = pair.Value;
using (fileGenerator.Declare("conf", conf))
using (fileGenerator.Declare("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
using (fileGenerator.Declare("description", copyDependencies.Description))
using (fileGenerator.Declare("command", copyDependencies.CommandLines.JoinStrings(Environment.NewLine, escapeXml: true)))
using (fileGenerator.Declare("inputs", copyDependencies.Inputs.JoinStrings(";")))
using (fileGenerator.Declare("outputs", copyDependencies.Outputs.JoinStrings(";")))
using (fileGenerator.Declare("linkobjects", copyDependencies.LinkObjects))
{
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildDescription);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildCommand);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildInputs);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildOutputs);
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildLinkObject);
// Also write the dependencies in the generated "runtimedependencies" file, for convenience
dependenciesFileGenerator.Write(string.Format("{0}[conf.Name]|[platformName]{0}", Environment.NewLine));
dependenciesFileGenerator.Write(string.Format(" {0}" + Environment.NewLine, copyDependencies.Inputs.JoinStrings(Environment.NewLine + " ")));
}
}
fileGenerator.Write(Template.Project.ProjectFilesCustomBuildEnd);
}
}
// Validation
for (int i = 0; i < context.ProjectConfigurations.Count; ++i)
{
Project.Configuration conf = context.ProjectConfigurations[i];
var compiledFiles = configurationCompiledFiles[i];
compiledFiles.Sort((l, r) => { return string.Compare(l.FileNameWithoutExtension, r.FileNameWithoutExtension, StringComparison.OrdinalIgnoreCase); });
for (int j = 0; j < compiledFiles.Count - 1; ++j)
{
ProjectFile l = compiledFiles[j];
ProjectFile r = compiledFiles[j + 1];
if (string.Compare(l.FileNameWithoutExtension, r.FileNameSourceRelative, StringComparison.OrdinalIgnoreCase) == 0)
{
string plausibleCause = "";
string message =
string.Format(
"error: {0} project configuration contains 2 files with the same file name '{1}', project compilation will fail due to same obj names"
+ Environment.NewLine + "{2}" + Environment.NewLine + "{3}.{4}",
conf, l.FileNameWithoutExtension, l.FileNameProjectRelative, r.FileNameProjectRelative, plausibleCause);
throw new Error(message);
}
}
}
// done!
fileGenerator.Write(Template.Project.ProjectFilesEnd);
// for the configuration that are fastbuild but external and requires to add the bff files
if (context.ProjectConfigurations.Any(x => x.IsFastBuild))
GenerateBffFilesSection(context, fileGenerator);
var allFileLists = new List<Tuple<string, List<ProjectFile>>>();
allFileLists.Add(Tuple.Create(hasCustomBuildForAllSources ? "CustomBuild" : "ClCompile", sourceFiles));
allFileLists.Add(Tuple.Create("PRIResource", XResourcesReswFiles));
allFileLists.Add(Tuple.Create("Image", XResourcesImgFiles));
allFileLists.Add(Tuple.Create(hasCustomBuildForAllIncludes ? "CustomBuild" : "ClInclude", includeFiles));
allFileLists.Add(Tuple.Create("CustomBuild", customBuildFiles));
if (NatvisFiles.Count > 0)
allFileLists.Add(Tuple.Create("Natvis", NatvisFiles));
if (PRIFiles.Count > 0)
allFileLists.Add(Tuple.Create("PRIResource", PRIFiles));
if (NoneFiles.Count > 0)
allFileLists.Add(Tuple.Create("None", NoneFiles));
foreach (var entry in customSourceFiles)
{
allFileLists.Add(Tuple.Create(entry.Key, entry.Value));
}
bool skipFilterGeneration = context.ProjectConfigurations.Any(conf => conf.SkipFilterGeneration);
if (!skipFilterGeneration || !File.Exists(filtersFileName))
{
using (fileGenerator.Declare("project", context.Project))
GenerateFiltersFile(context, filtersFileName, allFileLists, hasDependenciesToCopy ? relativeCopyDependenciesFileName : string.Empty, fileGenerator.Resolver, generatedFiles, skipFiles);
}
if (hasDependenciesToCopy)
{
FileInfo copyDependenciesFileInfo = new FileInfo(copyDependenciesFileName);
if (context.Builder.Context.WriteGeneratedFile(context.Project.GetType(), copyDependenciesFileInfo, dependenciesFileGenerator))
generatedFiles.Add(copyDependenciesFileInfo.FullName);
else
skipFiles.Add(copyDependenciesFileInfo.FullName);
}
}