private OrderableStrings GetDependenciesOutputFilesProjectRelative(Project.Configuration conf, FileInfo projectFileInfo) { // Build list of dependencies output files relative to project file. OrderableStrings dependencyFiles = new OrderableStrings(); foreach (Project.Configuration dependencyConf in conf.ResolvedDependencies) { var outputFileProjectRelative = Path.Combine(GetOutputDirectory(dependencyConf, projectFileInfo), FormatOutputFileName(dependencyConf)); dependencyFiles.Add(outputFileProjectRelative, dependencyConf.TargetFileOrderNumber); } dependencyFiles.Sort(); return(dependencyFiles); }
private static string GenerateLibraryReferences(OrderableStrings paths, Project.Configuration conf, OrderableStrings pathsToMerge = null) { for (int i = 0; i < paths.Count; ++i) { string libraryName = PathMakeUnix(paths[i]); if (File.Exists(libraryName)) { // If this is a full path to an existing file then do nothing, the linker can accept // it as a direct argument instead of having to go through -l } else if (conf.Platform.IsMac()) { // Mac ld only supports -l<name paths[i] = "-l" + libraryName; } else { // We've got two kinds of way of listing a library: // - With a filename without extension we must add the potential prefix and potential extension. // - With a filename with a static or shared lib extension (eg. .a/.so), we shouldn't touch it as it's already set by the script. string extension = Path.GetExtension(libraryName).ToLowerInvariant(); if (extension != ".a" && extension != ".so") { paths[i] = "-l:lib" + libraryName + ".a"; } else { paths[i] = "-l:" + libraryName; } } } if (pathsToMerge != null) { paths.AddRange(pathsToMerge); } paths.Sort(); return(paths.JoinStrings(" ")); }
private Options.ExplicitOptions GenerateOptions(Project.Configuration conf, FileInfo projectFileInfo) { Options.ExplicitOptions options = new Options.ExplicitOptions(); // CompilerToUse SelectOption(conf, Options.Option(Options.Makefile.General.PlatformToolset.Gcc, () => { options["CompilerToUse"] = "g++"; }), Options.Option(Options.Makefile.General.PlatformToolset.Clang, () => { options["CompilerToUse"] = "clang++"; }) ); // IntermediateDirectory options["IntermediateDirectory"] = PathMakeUnix(Util.PathGetRelative(projectFileInfo.DirectoryName, conf.IntermediatePath)); // OutputDirectory string outputDirectory = PathMakeUnix(GetOutputDirectory(conf, projectFileInfo)); options["OutputDirectory"] = outputDirectory; #region Compiler // Defines var defines = new Strings(); if (conf.DefaultOption == Options.DefaultTarget.Debug) { defines.Add("_DEBUG"); } else // Release { defines.Add("NDEBUG"); } foreach (string define in conf.Defines) { if (!string.IsNullOrWhiteSpace(define)) { defines.Add(define.Replace(@"""", @"\""")); } } defines.InsertPrefixSuffix(@"-D """, @""""); options["Defines"] = defines.JoinStrings(" "); // Includes OrderableStrings includePaths = new OrderableStrings(); includePaths.AddRange(Util.PathGetRelative(projectFileInfo.DirectoryName, Util.PathGetCapitalized(conf.IncludePrivatePaths))); includePaths.AddRange(Util.PathGetRelative(projectFileInfo.DirectoryName, Util.PathGetCapitalized(conf.IncludePaths))); includePaths.AddRange(Util.PathGetRelative(projectFileInfo.DirectoryName, Util.PathGetCapitalized(conf.DependenciesIncludePaths))); PathMakeUnix(includePaths); includePaths.InsertPrefix("-I"); includePaths.Sort(); options["Includes"] = includePaths.JoinStrings(" "); if (conf.ForcedIncludes.Count > 0) { OrderableStrings relativeForceIncludes = new OrderableStrings(Util.PathGetRelative(projectFileInfo.DirectoryName, conf.ForcedIncludes)); PathMakeUnix(relativeForceIncludes); relativeForceIncludes.InsertPrefix("-include "); relativeForceIncludes.Sort(); options["Includes"] += " " + relativeForceIncludes.JoinStrings(" "); } // CFLAGS { StringBuilder cflags = new StringBuilder(); // ExtraWarnings SelectOption(conf, Options.Option(Options.Makefile.Compiler.ExtraWarnings.Enable, () => { cflags.Append("-Wextra "); }), Options.Option(Options.Makefile.Compiler.ExtraWarnings.Disable, () => { }) ); // GenerateDebugInformation SelectOption(conf, Options.Option(Options.Makefile.Compiler.GenerateDebugInformation.Enable, () => { cflags.Append("-g "); }), Options.Option(Options.Makefile.Compiler.GenerateDebugInformation.Disable, () => { }) ); // OptimizationLevel SelectOption(conf, Options.Option(Options.Makefile.Compiler.OptimizationLevel.Disable, () => { }), Options.Option(Options.Makefile.Compiler.OptimizationLevel.Standard, () => { cflags.Append("-O1 "); }), Options.Option(Options.Makefile.Compiler.OptimizationLevel.Full, () => { cflags.Append("-O2 "); }), Options.Option(Options.Makefile.Compiler.OptimizationLevel.FullWithInlining, () => { cflags.Append("-O3 "); }), Options.Option(Options.Makefile.Compiler.OptimizationLevel.ForSize, () => { cflags.Append("-Os "); }) ); // Warnings SelectOption(conf, Options.Option(Options.Makefile.Compiler.Warnings.NormalWarnings, () => { }), Options.Option(Options.Makefile.Compiler.Warnings.MoreWarnings, () => { cflags.Append("-Wall "); }), Options.Option(Options.Makefile.Compiler.Warnings.Disable, () => { cflags.Append("-w "); }) ); // WarningsAsErrors SelectOption(conf, Options.Option(Options.Makefile.Compiler.TreatWarningsAsErrors.Enable, () => { cflags.Append("-Werror "); }), Options.Option(Options.Makefile.Compiler.TreatWarningsAsErrors.Disable, () => { }) ); // AdditionalCompilerOptions cflags.Append(conf.AdditionalCompilerOptions.JoinStrings(" ")); options["CFLAGS"] = cflags.ToString(); } // CXXFLAGS { StringBuilder cxxflags = new StringBuilder(); // CppLanguageStandard SelectOption(conf, Options.Option(Options.Makefile.Compiler.CppLanguageStandard.Default, () => { cxxflags.Append(""); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.Cpp98, () => { cxxflags.Append("-std=c++98 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.Cpp11, () => { cxxflags.Append("-std=c++11 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.Cpp14, () => { cxxflags.Append("-std=c++14 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.Cpp17, () => { cxxflags.Append("-std=c++17 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.Cpp2a, () => { cxxflags.Append("-std=c++2a "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.GnuCpp98, () => { cxxflags.Append("-std=gnu++98 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.GnuCpp11, () => { cxxflags.Append("-std=gnu++11 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.GnuCpp14, () => { cxxflags.Append("-std=gnu++14 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.GnuCpp17, () => { cxxflags.Append("-std=gnu++17 "); }), Options.Option(Options.Makefile.Compiler.CppLanguageStandard.GnuCpp2a, () => { cxxflags.Append("-std=gnu++2a "); }) ); // Exceptions SelectOption(conf, Options.Option(Options.Makefile.Compiler.Exceptions.Enable, () => { cxxflags.Append("-fexceptions "); }), Options.Option(Options.Makefile.Compiler.Exceptions.Disable, () => { cxxflags.Append("-fno-exceptions "); }) ); // RTTI SelectOption(conf, Options.Option(Options.Makefile.Compiler.Rtti.Enable, () => { cxxflags.Append("-frtti "); }), Options.Option(Options.Makefile.Compiler.Rtti.Disable, () => { cxxflags.Append("-fno-rtti "); }) ); options["CXXFLAGS"] = cxxflags.ToString(); } #endregion #region Linker // OutputFile options["OutputFile"] = conf.TargetFileFullNameWithExtension.Replace(" ", @"\ "); // LibraryFiles options["LibraryFiles"] = GenerateLibraryReferences(conf.LibraryFiles, conf); // LibraryPaths OrderableStrings libraryPaths = new OrderableStrings(); libraryPaths.AddRange(Util.PathGetRelative(projectFileInfo.DirectoryName, conf.LibraryPaths)); libraryPaths.AddRange(Util.PathGetRelative(projectFileInfo.DirectoryName, conf.DependenciesOtherLibraryPaths)); libraryPaths.AddRange(Util.PathGetRelative(projectFileInfo.DirectoryName, conf.DependenciesBuiltTargetsLibraryPaths)); PathMakeUnix(libraryPaths); libraryPaths.InsertPrefix("-L"); libraryPaths.Sort(); options["LibraryPaths"] = libraryPaths.JoinStrings(" "); // Dependencies var deps = new OrderableStrings(); foreach (Project.Configuration depConf in conf.ResolvedDependencies) { switch (depConf.Output) { case Project.Configuration.OutputType.None: continue; case Project.Configuration.OutputType.Lib: case Project.Configuration.OutputType.DotNetClassLibrary: deps.Add(Path.Combine(depConf.TargetLibraryPath, depConf.TargetFileFullNameWithExtension), depConf.TargetFileOrderNumber); break; case Project.Configuration.OutputType.Dll: default: deps.Add(Path.Combine(depConf.TargetPath, depConf.TargetFileFullNameWithExtension), depConf.TargetFileOrderNumber); break; } } var depsRelative = Util.PathGetRelative(projectFileInfo.DirectoryName, deps); PathMakeUnix(depsRelative); depsRelative.Sort(); options["LDDEPS"] = depsRelative.JoinStrings(" "); // DependenciesLibraryFiles options["DependenciesLibraryFiles"] = GenerateLibraryReferences(conf.DependenciesOtherLibraryFiles, conf, depsRelative); // LinkCommand if (conf.Output == Project.Configuration.OutputType.Lib) { options["LinkCommand"] = Template.Project.LinkCommandLib; } else if (conf.Output == Project.Configuration.OutputType.Dll) { options["LinkCommand"] = Template.Project.LinkCommandDll; } else { options["LinkCommand"] = Template.Project.LinkCommandExe; } if (conf.AdditionalLibrarianOptions.Any()) { throw new NotImplementedException(nameof(conf.AdditionalLibrarianOptions) + " not supported with Makefile generator"); } string linkerAdditionalOptions = conf.AdditionalLinkerOptions.JoinStrings(" "); options["AdditionalLinkerOptions"] = linkerAdditionalOptions; // this is supported in both gcc and clang SelectOption(conf, Options.Option(Options.Makefile.Linker.LibGroup.Enable, () => { options["LibsStartGroup"] = " -Wl,--start-group "; options["LibsEndGroup"] = " -Wl,--end-group "; }), Options.Option(Options.Makefile.Linker.LibGroup.Disable, () => { options["LibsStartGroup"] = string.Empty; options["LibsEndGroup"] = string.Empty; }) ); #endregion return(options); }