Sharpmake.Generators/Generic/MakeProject.cs (227 lines of code) (raw):

// Copyright (c) Ubisoft. All Rights Reserved. // Licensed under the Apache 2.0 License. See LICENSE.md in the project root for license information. using System.Collections.Generic; using System.IO; using System.Linq; namespace Sharpmake.Generators.Generic { public partial class MakeProject : IProjectGenerator { private const string _makefileExtension = ".mk"; private const string RemoveLineTag = FileGeneratorUtilities.RemoveLineTag; private Builder _builder; public void Generate(Builder builder, Project project, List<Project.Configuration> configurations, string projectFile, List<string> generatedFiles, List<string> skipFiles) { _builder = builder; FileInfo fileInfo = new FileInfo(projectFile); string projectPath = fileInfo.Directory.FullName; string projectFileName = fileInfo.Name; bool updated; string projectFileResult = GenerateProject(project, configurations, projectPath, projectFileName, out updated); if (updated) generatedFiles.Add(projectFileResult); else skipFiles.Add(projectFileResult); _builder = null; } public string GenerateProject(Project project, List<Project.Configuration> configurations, string projectPath, string projectFileName, out bool updated) { string projectDirectory = Util.GetCapitalizedPath(projectPath); Directory.CreateDirectory(projectDirectory); string fileFullPath = projectDirectory + Path.DirectorySeparatorChar + projectFileName + _makefileExtension; FileInfo fileInfo = new FileInfo(fileFullPath); var fileGenerator = new FileGenerator(); using (fileGenerator.Declare("item", new ProjectSettings(project, configurations, fileGenerator.Resolver))) { fileGenerator.Write(Template.GlobalTemplate); } fileGenerator.RemoveTaggedLines(); updated = _builder.Context.WriteGeneratedFile(project.GetType(), fileInfo, fileGenerator); return fileInfo.FullName; } private static void ResolveProjectPaths(Project project, Strings stringsToResolve) { foreach (string value in stringsToResolve.Values) { string newValue = ResolveProjectPaths(project, value); stringsToResolve.UpdateValue(value, newValue); } } private static string ResolveProjectPaths(Project project, string stringToResolve) { string resolvedString = stringToResolve.Replace("[project.SharpmakeCsPath]", project.SharpmakeCsPath).Replace("[project.SharpmakeCsProjectPath]", project.SharpmakeCsProjectPath); return Util.SimplifyPath(resolvedString); } private class ProjectSettings { private string _includePaths; private string _moduleName; private string _armMode; private string _shortCommands; private string _cFlagsDebug; private string _cFlagsRelease; private string _cFlagsFinal; private string _cFlagsExportedDebug; private string _cFlagsExportedRelease; private string _cFlagsExportedFinal; private string _sourcePaths; private string _groupStaticLibraries; private string _buildType; private string _prebuiltStaticLibraries; private string _prebuiltStaticLibrariesDebug; private string _prebuiltStaticLibrariesRelease; private readonly string _prebuiltStaticLibrariesFinal; public ProjectSettings(Project project, List<Project.Configuration> configurations, Resolver resolver) { Project.Configuration configurationDebug = configurations.FirstOrDefault(conf => conf.Target.GetFragment<Optimization>() == Optimization.Debug); Project.Configuration configurationRelease = configurations.FirstOrDefault(conf => conf.Target.GetFragment<Optimization>() == Optimization.Release); Project.Configuration configurationRetail = configurations.FirstOrDefault(conf => conf.Target.GetFragment<Optimization>() == Optimization.Retail); if (configurationDebug == null || configurationRelease == null || configurationRetail == null) throw new Error("Android makefiles require a debug, release and final configuration. "); configurationDebug.Defines.Add("_DEBUG"); configurationRelease.Defines.Add("NDEBUG"); configurationRetail.Defines.Add("NDEBUG"); _includePaths = ""; foreach (string includePath in configurationDebug.IncludePaths) { using (resolver.NewScopedParameter("Path", includePath)) { _includePaths += resolver.Resolve(Template.IncludePathTemplate) + "\r\n"; } } _sourcePaths = ""; Strings sourceFiles = project.GetSourceFilesForConfigurations(configurations); ResolveProjectPaths(project, sourceFiles); foreach (string sourcePath in sourceFiles) { string extension = sourcePath.Substring(sourcePath.LastIndexOf('.')); if (project.SourceFilesCompileExtensions.Contains(extension)) { if (!configurationDebug.ResolvedSourceFilesBuildExclude.Contains(sourcePath)) { using (resolver.NewScopedParameter("Path", sourcePath)) { _sourcePaths += resolver.Resolve(Template.SourceFileTemplate) + "\r\n"; } } } } _moduleName = project.Name; Options.SelectOption(configurationDebug, Options.Option(Options.AndroidMakefile.ArmMode.Thumb, () => _armMode = RemoveLineTag), Options.Option(Options.AndroidMakefile.ArmMode.Arm, () => _armMode = "arm") ); Options.SelectOption(configurationDebug, Options.Option(Options.AndroidMakefile.ShortCommands.Disable, () => _shortCommands = "false"), Options.Option(Options.AndroidMakefile.ShortCommands.Enable, () => _shortCommands = "true") ); Options.SelectOption(configurationDebug, Options.Option(Options.AndroidMakefile.GroupStaticLibraries.Disable, () => _groupStaticLibraries = "false"), Options.Option(Options.AndroidMakefile.GroupStaticLibraries.Enable, () => _groupStaticLibraries = "true") ); Strings compilerFlagsDebug = Options.GetStrings<Options.AndroidMakefile.CompilerFlags>(configurationDebug); Strings compilerFlagsRelease = Options.GetStrings<Options.AndroidMakefile.CompilerFlags>(configurationRelease); Strings compilerFlagsFinal = Options.GetStrings<Options.AndroidMakefile.CompilerFlags>(configurationRetail); _cFlagsDebug = configurationDebug.Defines.Select(define => "-D" + define).Union(compilerFlagsDebug).DefaultIfEmpty("").Aggregate((first, next) => first + " " + next); _cFlagsRelease = configurationRelease.Defines.Select(define => "-D" + define).Union(compilerFlagsRelease).DefaultIfEmpty("").Aggregate((first, next) => first + " " + next); _cFlagsFinal = configurationRetail.Defines.Select(define => "-D" + define).Union(compilerFlagsFinal).DefaultIfEmpty("").Aggregate((first, next) => first + " " + next); //Strings compilerExportedFlagsDebug = Options.GetStrings<Options.AndroidMakefile.CompilerExportedFlags>(configurationDebug); //Strings compilerExportedFlagsRelease = Options.GetStrings<Options.AndroidMakefile.CompilerExportedFlags>(configurationRelease); //Strings compilerExportedFlagsFinal = Options.GetStrings<Options.AndroidMakefile.CompilerExportedFlags>(configurationRetail); Strings exportedDefinesDebug = Options.GetStrings<Options.AndroidMakefile.ExportedDefines>(configurationDebug); Strings exportedDefinesRelease = Options.GetStrings<Options.AndroidMakefile.ExportedDefines>(configurationRelease); Strings exportedDefinesFinal = Options.GetStrings<Options.AndroidMakefile.ExportedDefines>(configurationRetail); _cFlagsExportedDebug = exportedDefinesDebug.Select(define => "-D" + define).Union(compilerFlagsDebug).DefaultIfEmpty("").Aggregate((first, next) => first + " " + next); _cFlagsExportedRelease = exportedDefinesRelease.Select(define => "-D" + define).Union(compilerFlagsRelease).DefaultIfEmpty("").Aggregate((first, next) => first + " " + next); _cFlagsExportedFinal = exportedDefinesFinal.Select(define => "-D" + define).Union(compilerFlagsFinal).DefaultIfEmpty("").Aggregate((first, next) => first + " " + next); List<PrebuiltStaticLibrary> allPrebuiltStaticLibrariesDebug = new List<PrebuiltStaticLibrary>(); List<PrebuiltStaticLibrary> allPrebuiltStaticLibrariesRelease = new List<PrebuiltStaticLibrary>(); List<PrebuiltStaticLibrary> allPrebuiltStaticLibrariesFinal = new List<PrebuiltStaticLibrary>(); foreach (var library in Options.GetObjects<Options.AndroidMakefile.PrebuiltStaticLibraries>(configurationDebug)) { PrebuiltStaticLibrary internalLibrary = new PrebuiltStaticLibrary(project, library); allPrebuiltStaticLibrariesDebug.Add(internalLibrary); } foreach (var library in Options.GetObjects<Options.AndroidMakefile.PrebuiltStaticLibraries>(configurationRelease)) { PrebuiltStaticLibrary internalLibrary = new PrebuiltStaticLibrary(project, library); allPrebuiltStaticLibrariesRelease.Add(internalLibrary); } foreach (var library in Options.GetObjects<Options.AndroidMakefile.PrebuiltStaticLibraries>(configurationRetail)) { PrebuiltStaticLibrary internalLibrary = new PrebuiltStaticLibrary(project, library); allPrebuiltStaticLibrariesFinal.Add(internalLibrary); } IEnumerable<PrebuiltStaticLibrary> prebuiltStaticLibraries = allPrebuiltStaticLibrariesDebug.Intersect(allPrebuiltStaticLibrariesRelease).Intersect(allPrebuiltStaticLibrariesFinal); IEnumerable<PrebuiltStaticLibrary> prebuiltStaticLibrariesDebug = allPrebuiltStaticLibrariesDebug.Except(prebuiltStaticLibraries); IEnumerable<PrebuiltStaticLibrary> prebuiltStaticLibrariesRelease = allPrebuiltStaticLibrariesRelease.Except(prebuiltStaticLibraries); IEnumerable<PrebuiltStaticLibrary> prebuiltStaticLibrariesFinal = allPrebuiltStaticLibrariesFinal.Except(prebuiltStaticLibraries); _prebuiltStaticLibraries = prebuiltStaticLibraries.Any() ? prebuiltStaticLibraries.Select(item => { using (resolver.NewScopedParameter("item", item)) return resolver.Resolve(Template.PrebuiltStaticLibraryTemplate); }).Aggregate((first, next) => first + "\r\n" + next) : ""; _prebuiltStaticLibrariesDebug = prebuiltStaticLibrariesDebug.Any() ? prebuiltStaticLibrariesDebug.Select(item => { using (resolver.NewScopedParameter("item", item)) return resolver.Resolve(Template.PrebuiltStaticLibraryTemplate); }).Aggregate((first, next) => first + "\r\n" + next) : ""; _prebuiltStaticLibrariesRelease = prebuiltStaticLibrariesRelease.Any() ? prebuiltStaticLibrariesRelease.Select(item => { using (resolver.NewScopedParameter("item", item)) return resolver.Resolve(Template.PrebuiltStaticLibraryTemplate); }).Aggregate((first, next) => first + "\r\n" + next) : ""; _prebuiltStaticLibrariesFinal = prebuiltStaticLibrariesFinal.Any() ? prebuiltStaticLibrariesFinal.Select(item => { using (resolver.NewScopedParameter("item", item)) return resolver.Resolve(Template.PrebuiltStaticLibraryTemplate); }).Aggregate((first, next) => first + "\r\n" + next) : ""; switch (configurationDebug.Output) { case Project.Configuration.OutputType.Lib: _buildType = Template.BuildStaticLibraryTemplate; break; case Project.Configuration.OutputType.Dll: _buildType = Template.BuildSharedLibraryTemplate; break; default: _buildType = RemoveLineTag; break; } } public string IncludePaths { get { return _includePaths; } } public string ModuleName { get { return _moduleName; } } public string ArmMode { get { return _armMode; } } public string ShortCommands { get { return _shortCommands; } } public string GroupStaticLibraries { get { return _groupStaticLibraries; } } public string CFlagsDebug { get { return _cFlagsDebug; } } public string CFlagsRelease { get { return _cFlagsRelease; } } public string CFlagsFinal { get { return _cFlagsFinal; } } public string CFlagsExportedDebug { get { return _cFlagsExportedDebug; } } public string CFlagsExportedRelease { get { return _cFlagsExportedRelease; } } public string CFlagsExportedFinal { get { return _cFlagsExportedFinal; } } public string SourcePaths { get { return _sourcePaths; } } public string BuildType { get { return _buildType; } } public string PrebuiltStaticLibraries { get { return _prebuiltStaticLibraries; } } public string PrebuiltStaticLibrariesDebug { get { return _prebuiltStaticLibrariesDebug; } } public string PrebuiltStaticLibrariesRelease { get { return _prebuiltStaticLibrariesRelease; } } public string PrebuiltStaticLibrariesFinal { get { return _prebuiltStaticLibrariesFinal; } } } private class PrebuiltStaticLibrary { private Options.AndroidMakefile.PrebuiltStaticLibraries _option; private string _armMode; private readonly string _libraryPath; public PrebuiltStaticLibrary(Project project, Options.AndroidMakefile.PrebuiltStaticLibraries option) { _option = option; if (_option.Mode == Options.AndroidMakefile.ArmMode.Arm) _armMode = "arm"; else _armMode = RemoveLineTag; _libraryPath = ResolveProjectPaths(project, _option.LibraryPath); } public override bool Equals(object obj) { PrebuiltStaticLibrary other = obj as PrebuiltStaticLibrary; if (other == null) return false; return ModuleName == other.ModuleName && LibraryPath == other.LibraryPath && ArmMode == other.ArmMode; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; hash = hash * 23 + ModuleName.GetHashCode(); hash = hash * 23 + LibraryPath.GetHashCode(); hash = hash * 23 + LibraryPath.GetHashCode(); return hash; } } public string ArmMode { get { return _armMode; } } public string ModuleName { get { return _option.ModuleName; } } public string LibraryPath { get { return _libraryPath; } } } } }