diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index b344ca3d0..a6c00a635 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -5,6 +5,7 @@ on: [push, pull_request] jobs: build: runs-on: ${{ matrix.os }} + continue-on-error: true strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] @@ -40,7 +41,7 @@ jobs: run: ./CompileSharpmake.sh Sharpmake.sln "${{ matrix.configuration }}" - name: GenerateMdbFiles.bat - if: runner.os == 'Windows' + if: runner.os == 'Windows' && matrix.configuration == 'release' shell: cmd run: GenerateMdbFiles.bat diff --git a/.gitignore b/.gitignore index 4c38c1754..a1b31d83d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ # Samples and FunctionalTests generated projects samples/*/projects/* -samples/HelloXCode/codebase/temp* +samples/*/codebase/temp* Sharpmake.FunctionalTests/*/projects/* !**/reference/**/*.* ## Ignore Visual Studio temporary files, build results, and @@ -66,3 +66,6 @@ Sharpmake.VC.db # Desktop Services Store on MacOS **/.DS_Store + +# Discard tmp files +[Tt]mp/ \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..fc644ed16 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +opensource@ubisoft.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..cb9198b9d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,19 @@ +## Contributing + +### Tests + +We will only accept merge requests that pass every tests. The unit tests are written with NUnit and the regression tests are ran by comparing the samples' output with a reference output. You can run the regression_tests.py script after having built the solution in Visual Studio to run the regression tests. + +Because the regression tests just do a direct comparison with the output, it is possible to get a false negative after having done a good change. In that case, please update the tests so they match the output after your change. You can run the UpdateSamplesOutput.bat and UpdateSharpmakeProjects.bat batch files to automatically overwrite the reference output files. + +Naturally, we also recommend that you put your own tests after fixing a bug or adding a feature to help us avoid regressions. + +Functional tests are generating test projects and building them to test functionality + +used toolset for functional tests: + +tools\FastBuild - v1.01. http://www.fastbuild.org + +### Additional Platforms + +If you want to add support for an additional platform, please make sure that the platform is open and that you are not breaking your NDA. Ubisoft has not published platform support for most video game consoles for that exact reason. We will not accept merge requests for new platforms that are not completely open for development. diff --git a/Intro.md b/Intro.md index dbded1ee0..03b2d498a 100644 --- a/Intro.md +++ b/Intro.md @@ -200,7 +200,7 @@ class MySolution : Solution The entry point is the Main, a function called once and found in the main .sharpmake.cs file passed to Sharpmake.exe: ```csharp -static class Main +public static class Main { [Sharpmake.Main] public static void SharpmakeMain(Sharpmake.Arguments arguments) @@ -224,7 +224,7 @@ class MyArguments } } -static class Main +public static class Main { public static MyArguments Arguments = new MyArguments(); diff --git a/README.md b/README.md index e29bbec13..266919b9e 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ functionality used toolset for functional tests: -tools\FastBuild - v1.01. http://www.fastbuild.org +tools\FastBuild - v1.04. http://www.fastbuild.org diff --git a/Sharpmake.Application/Program.cs b/Sharpmake.Application/Program.cs index 868fb6762..ba8dfb807 100644 --- a/Sharpmake.Application/Program.cs +++ b/Sharpmake.Application/Program.cs @@ -175,6 +175,9 @@ private static int Main() // This GC gives a little bit better results than the other ones. "LowLatency" is giving really bad results(twice slower than the other ones). System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.SustainedLowLatency; + AppDomain currentDomain = AppDomain.CurrentDomain; + currentDomain.UnhandledException += AppDomain_UnhandledException; + Mutex oneInstanceMutex = null; Argument parameters = new Argument(); ExitCode exitCode = ExitCode.Success; @@ -412,6 +415,14 @@ private static void AppDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs LogSharpmakeExtensionLoaded(args.LoadedAssembly); } + private static void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs) + { + LogWriteLine(Environment.NewLine + "Unhandled exception Error:"); + LogWriteLine(Util.GetCompleteExceptionMessage(unhandledExceptionEventArgs.ExceptionObject as Exception, "\t")); + + Environment.Exit((int)ExitCode.UnknownError); + } + private static void LogSharpmakeExtensionLoaded(Assembly extensionAssembly) { if (extensionAssembly == null) diff --git a/Sharpmake.Application/Properties/AssemblyInfo.cs b/Sharpmake.Application/Properties/AssemblyInfo.cs index da950712d..bf243ac30 100644 --- a/Sharpmake.Application/Properties/AssemblyInfo.cs +++ b/Sharpmake.Application/Properties/AssemblyInfo.cs @@ -43,4 +43,4 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.15.1.0")] +[assembly: AssemblyVersion("0.16.0.0")] diff --git a/Sharpmake.FunctionalTests/.gitignore b/Sharpmake.FunctionalTests/.gitignore new file mode 100644 index 000000000..71db4089d --- /dev/null +++ b/Sharpmake.FunctionalTests/.gitignore @@ -0,0 +1,2 @@ +projects/ +blob/ \ No newline at end of file diff --git a/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/SharpmakePackage.sharpmake.cs b/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/SharpmakePackage.sharpmake.cs new file mode 100644 index 000000000..7af1ccb46 --- /dev/null +++ b/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/SharpmakePackage.sharpmake.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using Sharpmake; + +namespace SharpmakeGen.FunctionalTests +{ + public abstract class LibProjectBase : CSharpProject + { + public LibProjectBase() + : base(typeof(Target)) + { + RootPath = @"[project.SharpmakeCsPath]"; + SourceRootPath = @"[project.RootPath]\codebase\[project.Name]"; + } + + [Configure] + public virtual void ConfigureAll(Configuration conf, Target target) + { + conf.ProjectFileName = "[project.Name]_[target.DevEnv]_[target.Platform]"; + conf.ProjectPath = @"[project.SharpmakeCsPath]\projects"; + + conf.Output = Configuration.OutputType.DotNetClassLibrary; + + conf.IntermediatePath = @"[conf.ProjectPath]\build\[conf.Name]\[project.Name]"; + conf.TargetPath = @"[conf.ProjectPath]\output\[conf.Name]"; + + // .lib files must be with the .obj files when running in fastbuild distributed mode or we'll have missing symbols due to merging of the .pdb + conf.TargetLibraryPath = "[conf.IntermediatePath]"; + } + } +} \ No newline at end of file diff --git a/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/SharpmakePackageFunctionalTest.sharpmake.cs b/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/SharpmakePackageFunctionalTest.sharpmake.cs new file mode 100644 index 000000000..7d25c80c3 --- /dev/null +++ b/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/SharpmakePackageFunctionalTest.sharpmake.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using Sharpmake; + +[module: Sharpmake.Package(@".\SharpmakePackage.sharpmake.cs")] + + +namespace SharpmakeGen.FunctionalTests +{ + [Generate] + public class SimpleProject : LibProjectBase + { + [Sharpmake.Main] + public static void SharpmakeMain(Sharpmake.Arguments arguments) + { + arguments.Generate(); + } + } +} \ No newline at end of file diff --git a/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/codebase/SimpleProject/SimpleProject.cs b/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/codebase/SimpleProject/SimpleProject.cs new file mode 100644 index 000000000..e7aa06255 --- /dev/null +++ b/Sharpmake.FunctionalTests/SharpmakePackageFunctionalTest/codebase/SimpleProject/SimpleProject.cs @@ -0,0 +1,7 @@ +namespace SimpleProject +{ + public class MyClass + { + + } +} \ No newline at end of file diff --git a/Sharpmake.Generators/FastBuild/Bff.Template.cs b/Sharpmake.Generators/FastBuild/Bff.Template.cs index bb4ebbaea..0bac6832c 100644 --- a/Sharpmake.Generators/FastBuild/Bff.Template.cs +++ b/Sharpmake.Generators/FastBuild/Bff.Template.cs @@ -341,6 +341,7 @@ public static class ConfigurationFile + ' [cmdLineOptions.WarningLevel]' + ' [cmdLineOptions.TreatWarningAsError]' + ' [cmdLineOptions.DiagnosticsFormat]' + + ' [cmdLineOptions.EnableASAN]' + ' [fastBuildCompileAsC]' // Multi-threaded build is already handled by FASTBuild // + ' [cmdLineOptions.MultiProcessorCompilation]' @@ -533,8 +534,6 @@ public static class ConfigurationFile } "; - [Obsolete("Section has been renamed to: GenericExecutableSection")] - public static string GenericExcutableSection = GenericExecutableSection; public static string TestSection = @" //================================================================================================================= diff --git a/Sharpmake.Generators/FastBuild/Bff.Util.cs b/Sharpmake.Generators/FastBuild/Bff.Util.cs index bc40dee53..387b08a84 100644 --- a/Sharpmake.Generators/FastBuild/Bff.Util.cs +++ b/Sharpmake.Generators/FastBuild/Bff.Util.cs @@ -282,7 +282,7 @@ public override string GetCommand(BuildType buildType, Sharpmake.Project.Configu string rebuildCmd = buildType == BuildType.Rebuild ? " -clean" : ""; // $(ProjectDir) has a trailing slash - return $@"$(ProjectDir){fastBuildExecutable}{rebuildCmd} {fastBuildShortProjectName} {fastbuildArguments}"; + return $@"""$(ProjectDir){fastBuildExecutable}""{rebuildCmd} {fastBuildShortProjectName} {fastbuildArguments}"; } } diff --git a/Sharpmake.Generators/FastBuild/Bff.cs b/Sharpmake.Generators/FastBuild/Bff.cs index f143f0246..4d19de86f 100644 --- a/Sharpmake.Generators/FastBuild/Bff.cs +++ b/Sharpmake.Generators/FastBuild/Bff.cs @@ -712,16 +712,6 @@ List skipFiles { switch (platformToolset) { - case Options.Vc.General.PlatformToolset.LLVM_vs2012: - // - llvmClangCompilerOptions = "-m64 -fmsc-version=1700"; - fastBuildPCHForceInclude = @"/FI""[cmdLineOptions.PrecompiledHeaderThrough]"""; - break; - case Options.Vc.General.PlatformToolset.LLVM_vs2014: - // - llvmClangCompilerOptions = "-m64 -fmsc-version=1900"; - fastBuildPCHForceInclude = @"/FI""[cmdLineOptions.PrecompiledHeaderThrough]"""; - break; case Options.Vc.General.PlatformToolset.LLVM: case Options.Vc.General.PlatformToolset.ClangCL: // diff --git a/Sharpmake.Generators/FastBuild/IPlatformBff.cs b/Sharpmake.Generators/FastBuild/IPlatformBff.cs index d42a67d76..d76b43c8b 100644 --- a/Sharpmake.Generators/FastBuild/IPlatformBff.cs +++ b/Sharpmake.Generators/FastBuild/IPlatformBff.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -70,9 +70,6 @@ public interface IPlatformBff /// The file name of the build output. void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration configuration, string fastBuildOutputFile); - [Obsolete("Use " + nameof(SetupExtraLinkerSettings) + " and pass the conf")] - void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration.OutputType outputType, string fastBuildOutputFile); - /// /// Get the extra list of build steps to execute for this platform. /// diff --git a/Sharpmake.Generators/FastBuild/MasterBff.cs b/Sharpmake.Generators/FastBuild/MasterBff.cs index ec0f9d94a..d928e61f7 100644 --- a/Sharpmake.Generators/FastBuild/MasterBff.cs +++ b/Sharpmake.Generators/FastBuild/MasterBff.cs @@ -781,11 +781,5 @@ Strings unresolved resolved.Add(bffToParse); unresolved.Remove(bffToParse); } - - [Obsolete("This method is not supported anymore.")] - public static bool IsMasterBffFilename(string filename) - { - return false; - } } } diff --git a/Sharpmake.Generators/Generic/Makefile.Template.cs b/Sharpmake.Generators/Generic/Makefile.Template.cs index 0e249d888..39487ffbf 100644 --- a/Sharpmake.Generators/Generic/Makefile.Template.cs +++ b/Sharpmake.Generators/Generic/Makefile.Template.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2019-2020 Ubisoft Entertainment +// Copyright (c) 2017, 2019-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -108,10 +108,13 @@ ifndef verbose GCH = [precompIntermediate] PCHCMD = [precompCommand] define PREBUILDCMDS + [precompPreBuildCmds] endef define PRELINKCMDS + [precompPreLinkCmds] endef define POSTBUILDCMDS + [precompPostBuildCmds] endef define POSTFILECMDS endef diff --git a/Sharpmake.Generators/Generic/Makefile.cs b/Sharpmake.Generators/Generic/Makefile.cs index 190a045fb..91316fba9 100644 --- a/Sharpmake.Generators/Generic/Makefile.cs +++ b/Sharpmake.Generators/Generic/Makefile.cs @@ -284,6 +284,10 @@ private string GenerateProject( string precompHeaderOut = ""; string precompIntermediate = ""; string precompCommand = ""; + string precompPreBuildCmds = ""; + string precompPreLinkCmds = ""; + string precompPostBuildCmds = ""; + if (!string.IsNullOrEmpty(conf.PrecompHeader)) { @@ -298,12 +302,22 @@ private string GenerateProject( precompCommand = "-include $(PCHOUT)"; } + if (conf.EventPreBuild.Any()) + precompPreBuildCmds = conf.EventPreBuild.Aggregate((curr, next) => $"{curr} && {next}"); + if (conf.EventPreLink.Any()) + precompPreLinkCmds = conf.EventPreLink.Aggregate((curr, next) => $"{curr} && {next}"); + if (conf.EventPostBuild.Any()) + precompPostBuildCmds = conf.EventPostBuild.Aggregate((curr, next) => $"{curr} && {next}"); + using (fileGenerator.Declare("name", conf.Name.ToLower())) using (fileGenerator.Declare("options", options[conf])) using (fileGenerator.Declare("precompHeader", precompHeader)) using (fileGenerator.Declare("precompHeaderOut", precompHeaderOut)) using (fileGenerator.Declare("precompIntermediate", precompIntermediate)) using (fileGenerator.Declare("precompCommand", precompCommand)) + using (fileGenerator.Declare("precompPreBuildCmds", precompPreBuildCmds)) + using (fileGenerator.Declare("precompPreLinkCmds", precompPreLinkCmds)) + using (fileGenerator.Declare("precompPostBuildCmds", precompPostBuildCmds)) { fileGenerator.Write(Template.Project.ProjectConfigurationVariables); } diff --git a/Sharpmake.Generators/Properties/AssemblyInfo.cs b/Sharpmake.Generators/Properties/AssemblyInfo.cs index c4be53311..1018892ff 100644 --- a/Sharpmake.Generators/Properties/AssemblyInfo.cs +++ b/Sharpmake.Generators/Properties/AssemblyInfo.cs @@ -44,6 +44,6 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.15.1.0")] +[assembly: AssemblyVersion("0.16.0.0")] [assembly: InternalsVisibleTo("Sharpmake")] diff --git a/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs b/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs index b43eb45d8..143a6635a 100644 --- a/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs +++ b/Sharpmake.Generators/VisualStudio/ProjectOptionsGenerator.cs @@ -180,9 +180,9 @@ private void GenerateGeneralOptions(IGenerationContext context, ProjectOptionsGe if (context.Configuration.Target.GetPlatform() == Platform.linux) { - context.Options["ProjectDirectory"] = "/mnt/" + context.ProjectDirectoryCapitalized.Replace(@":", string.Empty).Replace('\\', '/'); - context.Options["OutputDirectoryRemote"] = (@"$(RemoteProjectDir)" + context.Options["OutputDirectory"]).Replace('\\', '/'); - context.Options["IntermediateDirectoryRemote"] = (@"$(RemoteProjectDir)" + context.Options["IntermediateDirectory"]).Replace('\\', '/'); + context.Options["ProjectDirectory"] = Util.ConvertToMountedUnixPath(context.ProjectDirectoryCapitalized); + context.Options["OutputDirectoryRemote"] = (@"$(RemoteProjectDir)" + Util.ConvertToUnixSeparators(Util.EnsureTrailingSeparator(context.Options["OutputDirectory"]))); + context.Options["IntermediateDirectoryRemote"] = (@"$(RemoteProjectDir)" + Util.ConvertToUnixSeparators(Util.EnsureTrailingSeparator(context.Options["IntermediateDirectory"]))); } } @@ -389,8 +389,7 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG Options.Option(Options.Vc.General.CommonLanguageRuntimeSupport.NoClrSupport, () => { context.Options["CLRSupport"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["CLRSupport"] = FileGeneratorUtilities.RemoveLineTag; }), Options.Option(Options.Vc.General.CommonLanguageRuntimeSupport.ClrSupport, () => { context.Options["CLRSupport"] = "true"; context.CommandLineOptions["CLRSupport"] = "/clr"; }), Options.Option(Options.Vc.General.CommonLanguageRuntimeSupport.PureMsilClrSupport, () => { context.Options["CLRSupport"] = "Pure"; context.CommandLineOptions["CLRSupport"] = "/clr:pure"; }), - Options.Option(Options.Vc.General.CommonLanguageRuntimeSupport.SafeMsilClrSupport, () => { context.Options["CLRSupport"] = "Safe"; context.CommandLineOptions["CLRSupport"] = "/clr:safe"; }), - Options.Option(Options.Vc.General.CommonLanguageRuntimeSupport.SafeMsilClrSupportOldSyntax, () => { context.Options["CLRSupport"] = "OldSyntax"; context.CommandLineOptions["CLRSupport"] = "/clr:oldSyntax"; }) + Options.Option(Options.Vc.General.CommonLanguageRuntimeSupport.SafeMsilClrSupport, () => { context.Options["CLRSupport"] = "Safe"; context.CommandLineOptions["CLRSupport"] = "/clr:safe"; }) ); context.SelectOption @@ -653,7 +652,7 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG context.Options["ForcedUsingFiles"] = ForceUsingFiles.Remove(ForceUsingFiles.Length - 1, 1); } - //Options.Vc.Compiler.CompileAsWinRT. + //Options.Vc.Compiler.CompileAsWinRT. // Disable CompileAsWinRT="false" // Enable CompileAsWinRT="true" context.SelectOption @@ -801,6 +800,7 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG Options.Option(Options.Vc.Compiler.EnhancedInstructionSet.SIMD2, () => { context.Options["EnableEnhancedInstructionSet"] = "StreamingSIMDExtensions2"; context.CommandLineOptions["EnableEnhancedInstructionSet"] = "/arch:SSE2"; }), Options.Option(Options.Vc.Compiler.EnhancedInstructionSet.AdvancedVectorExtensions, () => { context.Options["EnableEnhancedInstructionSet"] = "AdvancedVectorExtensions"; context.CommandLineOptions["EnableEnhancedInstructionSet"] = "/arch:AVX"; }), Options.Option(Options.Vc.Compiler.EnhancedInstructionSet.AdvancedVectorExtensions2, () => { context.Options["EnableEnhancedInstructionSet"] = "AdvancedVectorExtensions2"; context.CommandLineOptions["EnableEnhancedInstructionSet"] = "/arch:AVX2"; }), + Options.Option(Options.Vc.Compiler.EnhancedInstructionSet.AdvancedVectorExtensions512, () => { context.Options["EnableEnhancedInstructionSet"] = "AdvancedVectorExtensions512"; context.CommandLineOptions["EnableEnhancedInstructionSet"] = "/arch:AVX512"; }), Options.Option(Options.Vc.Compiler.EnhancedInstructionSet.NoEnhancedInstructions, () => { context.Options["EnableEnhancedInstructionSet"] = "NoExtensions"; context.CommandLineOptions["EnableEnhancedInstructionSet"] = "/arch:IA32"; }) ); @@ -899,7 +899,7 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG Options.Option(Options.Vc.Compiler.ForceLoopScope.Enable, () => { context.Options["ForceConformanceInForLoopScope"] = "true"; context.CommandLineOptions["ForceConformanceInForLoopScope"] = "/Zc:forScope"; }) ); - //Options.Vc.Compiler.OpenMP. + //Options.Vc.Compiler.OpenMP. // Disable OpenMP="false" /openmp- // Enable OpenMP="true" /openmp context.SelectOption @@ -908,8 +908,8 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG Options.Option(Options.Vc.Compiler.OpenMP.Enable, () => { context.Options["OpenMP"] = "true"; context.CommandLineOptions["OpenMP"] = "/openmp"; }) ); - //Options.Vc.Compiler.GenerateXMLDocumentation. - // Disable GenerateXMLDocumentation="false" + //Options.Vc.Compiler.GenerateXMLDocumentation. + // Disable GenerateXMLDocumentation="false" // Enable GenerateXMLDocumentation="true" /openmp context.SelectOption ( @@ -931,7 +931,8 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG ( Options.Option(Options.Vc.Compiler.CallingConvention.cdecl, () => { context.Options["CallingConvention"] = "Cdecl"; context.CommandLineOptions["CallingConvention"] = "/Gd"; }), Options.Option(Options.Vc.Compiler.CallingConvention.fastcall, () => { context.Options["CallingConvention"] = "FastCall"; context.CommandLineOptions["CallingConvention"] = "/Gr"; }), - Options.Option(Options.Vc.Compiler.CallingConvention.stdcall, () => { context.Options["CallingConvention"] = "StdCall"; context.CommandLineOptions["CallingConvention"] = "/Gz"; }) + Options.Option(Options.Vc.Compiler.CallingConvention.stdcall, () => { context.Options["CallingConvention"] = "StdCall"; context.CommandLineOptions["CallingConvention"] = "/Gz"; }), + Options.Option(Options.Vc.Compiler.CallingConvention.vectorcall, () => { context.Options["CallingConvention"] = "VectorCall"; context.CommandLineOptions["CallingConvention"] = "/Gv"; }) ); //Options.Vc.Compiler.ShowIncludes. @@ -974,17 +975,21 @@ private void GenerateCompilerOptions(IGenerationContext context, ProjectOptionsG context.CommandLineOptions["SupportJustMyCode"] = FileGeneratorUtilities.RemoveLineTag; } - //Options.Vc.Compiler.SpectreMitigation. - // Default - // Enabled SpectreMitigation="Spectre" /Qspectre - // Disabled SpectreMitigation="false" context.SelectOption ( Options.Option(Options.Vc.Compiler.SpectreMitigation.Default, () => { context.Options["SpectreMitigation"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["SpectreMitigation"] = FileGeneratorUtilities.RemoveLineTag; }), - Options.Option(Options.Vc.Compiler.SpectreMitigation.Enabled, () => { context.Options["SpectreMitigation"] = "Spectre"; context.CommandLineOptions["SpectreMitigation"] = "/Qspectre"; }), + Options.Option(Options.Vc.Compiler.SpectreMitigation.Spectre, () => { context.Options["SpectreMitigation"] = "Spectre"; context.CommandLineOptions["SpectreMitigation"] = "/Qspectre"; }), + Options.Option(Options.Vc.Compiler.SpectreMitigation.SpectreLoad, () => { context.Options["SpectreMitigation"] = "SpectreLoad"; context.CommandLineOptions["SpectreMitigation"] = "/Qspectre-load"; }), + Options.Option(Options.Vc.Compiler.SpectreMitigation.SpectreLoadCF, () => { context.Options["SpectreMitigation"] = "SpectreLoadCF"; context.CommandLineOptions["SpectreMitigation"] = "/Qspectre-load-cf"; }), Options.Option(Options.Vc.Compiler.SpectreMitigation.Disabled, () => { context.Options["SpectreMitigation"] = "false"; context.CommandLineOptions["SpectreMitigation"] = FileGeneratorUtilities.RemoveLineTag; }) ); + context.SelectOption + ( + Options.Option(Options.Vc.Compiler.EnableAsan.Disable, () => { context.Options["EnableASAN"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["EnableASAN"] = FileGeneratorUtilities.RemoveLineTag; }), + Options.Option(Options.Vc.Compiler.EnableAsan.Enable, () => { context.Options["EnableASAN"] = "true"; context.CommandLineOptions["EnableASAN"] = "/fsanitize=address"; }) + ); + if (context.DevelopmentEnvironment == DevEnv.vs2017 || context.DevelopmentEnvironment == DevEnv.vs2019) { //Options.Vc.Compiler.DefineCPlusPlus. See: https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ @@ -1190,8 +1195,6 @@ private static void SelectPlatformToolsetOption(IGenerationContext context, Proj Options.Option(Options.Vc.General.PlatformToolset.v141, () => { context.Options["PlatformToolset"] = "v141"; }), Options.Option(Options.Vc.General.PlatformToolset.v141_xp, () => { context.Options["PlatformToolset"] = "v141_xp"; }), Options.Option(Options.Vc.General.PlatformToolset.v142, () => { context.Options["PlatformToolset"] = "v142"; }), - Options.Option(Options.Vc.General.PlatformToolset.LLVM_vs2012, () => { context.Options["PlatformToolset"] = "LLVM-vs2012"; context.Options["TrackFileAccess"] = "false"; }), - Options.Option(Options.Vc.General.PlatformToolset.LLVM_vs2014, () => { context.Options["PlatformToolset"] = "LLVM-vs2014"; }), Options.Option(Options.Vc.General.PlatformToolset.LLVM, () => { context.Options["PlatformToolset"] = "llvm"; }), Options.Option(Options.Vc.General.PlatformToolset.ClangCL, () => { context.Options["PlatformToolset"] = "ClangCL"; }) ); @@ -1278,15 +1281,15 @@ private void GenerateLinkerOptions(IGenerationContext context, ProjectOptionsGen throw new ArgumentOutOfRangeException(); } - //ShowProgress - // NotSet ShowProgress="0" - // DisplayAllProgressMessages ShowProgress="1" /VERBOSE - // DisplaysSomeProgressMessages ShowProgress="2" /VERBOSE:LIB context.SelectOption ( Options.Option(Options.Vc.Linker.ShowProgress.NotSet, () => { context.Options["ShowProgress"] = "NotSet"; context.CommandLineOptions["ShowProgress"] = FileGeneratorUtilities.RemoveLineTag; }), - Options.Option(Options.Vc.Linker.ShowProgress.DisplayAllProgressMessages, () => { context.Options["ShowProgress"] = "LinkVerbose"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE"; }), - Options.Option(Options.Vc.Linker.ShowProgress.DisplaysSomeProgressMessages, () => { context.Options["ShowProgress"] = "LinkVerboseLib"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE:Lib"; }) + Options.Option(Options.Vc.Linker.ShowProgress.LinkVerbose, () => { context.Options["ShowProgress"] = "LinkVerbose"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE"; }), + Options.Option(Options.Vc.Linker.ShowProgress.LinkVerboseLib, () => { context.Options["ShowProgress"] = "LinkVerboseLib"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE:Lib"; }), + Options.Option(Options.Vc.Linker.ShowProgress.LinkVerboseICF, () => { context.Options["ShowProgress"] = "LinkVerboseICF"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE:ICF"; }), + Options.Option(Options.Vc.Linker.ShowProgress.LinkVerboseREF, () => { context.Options["ShowProgress"] = "LinkVerboseREF"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE:REF"; }), + Options.Option(Options.Vc.Linker.ShowProgress.LinkVerboseSAFESEH, () => { context.Options["ShowProgress"] = "LinkVerboseSAFESEH"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE:SAFESEH"; }), + Options.Option(Options.Vc.Linker.ShowProgress.LinkVerboseCLR, () => { context.Options["ShowProgress"] = "LinkVerboseCLR"; context.CommandLineOptions["ShowProgress"] = "/VERBOSE:CLR"; }) ); //Incremental @@ -1485,15 +1488,17 @@ private void GenerateLinkerOptions(IGenerationContext context, ProjectOptionsGen Options.Option(Options.Vc.Linker.AssemblyDebug.NoRuntimeTrackingAndEnableOptimizations, () => { context.Options["AssemblyDebug"] = "false"; context.CommandLineOptions["AssemblyDebug"] = "/ASSEMBLYDEBUG:DISABLE"; }) ); - //SubSystem - // Console SubSystem="1" /SUBSYSTEM:CONSOLE - // Windows SubSystem="2" /SUBSYSTEM:WINDOWS - // Native SubSystem="3" /SUBSYSTEM:NATIVE context.SelectOption ( + Options.Option(Options.Vc.Linker.SubSystem.NotSet, () => { context.Options["SubSystem"] = "NotSet"; context.CommandLineOptions["SubSystem"] = FileGeneratorUtilities.RemoveLineTag; }), Options.Option(Options.Vc.Linker.SubSystem.Console, () => { context.Options["SubSystem"] = "Console"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:CONSOLE"; }), - Options.Option(Options.Vc.Linker.SubSystem.Application, () => { context.Options["SubSystem"] = "Windows"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:WINDOWS"; }), - Options.Option(Options.Vc.Linker.SubSystem.Native, () => { context.Options["SubSystem"] = "Native"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:NATIVE"; }) + Options.Option(Options.Vc.Linker.SubSystem.Windows, () => { context.Options["SubSystem"] = "Windows"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:WINDOWS"; }), + Options.Option(Options.Vc.Linker.SubSystem.Native, () => { context.Options["SubSystem"] = "Native"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:NATIVE"; }), + Options.Option(Options.Vc.Linker.SubSystem.EFI_Application, () => { context.Options["SubSystem"] = "EFI Application"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:EFI_APPLICATION"; }), + Options.Option(Options.Vc.Linker.SubSystem.EFI_Boot_Service_Driver, () => { context.Options["SubSystem"] = "EFI Boot Service Driver"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER"; }), + Options.Option(Options.Vc.Linker.SubSystem.EFI_ROM, () => { context.Options["SubSystem"] = "EFI ROM"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:EFI_ROM"; }), + Options.Option(Options.Vc.Linker.SubSystem.EFI_Runtime, () => { context.Options["SubSystem"] = "EFI Runtime"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:EFI_RUNTIME_DRIVER"; }), + Options.Option(Options.Vc.Linker.SubSystem.POSIX, () => { context.Options["SubSystem"] = "POSIX"; context.CommandLineOptions["SubSystem"] = "/SUBSYSTEM:POSIX"; }) ); @@ -1547,9 +1552,6 @@ private void GenerateLinkerOptions(IGenerationContext context, ProjectOptionsGen } } - //AllowIsolation - // Disabled AllowIsolation=false /ALLOWISOLATION:NO - // Enable AllowIsolation=true /ALLOWISOLATION context.SelectOption ( Options.Option(Options.Vc.Linker.AllowIsolation.Enabled, () => { context.Options["AllowIsolation"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["AllowIsolation"] = FileGeneratorUtilities.RemoveLineTag; }), @@ -1654,6 +1656,7 @@ private void GenerateLinkerOptions(IGenerationContext context, ProjectOptionsGen ( Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.Default, () => { context.Options["LinkTimeCodeGeneration"] = "false"; context.CommandLineOptions["LinkTimeCodeGeneration"] = FileGeneratorUtilities.RemoveLineTag; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.UseLinkTimeCodeGeneration, () => { context.Options["LinkTimeCodeGeneration"] = "true"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG"; }), + Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.UseFastLinkTimeCodeGeneration, () => { context.Options["LinkTimeCodeGeneration"] = "true"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG"; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.ProfileGuidedOptimizationInstrument, () => { context.Options["LinkTimeCodeGeneration"] = "true"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG"; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.ProfileGuidedOptimizationOptimize, () => { context.Options["LinkTimeCodeGeneration"] = "true"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG"; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.ProfileGuidedOptimizationUpdate, () => { context.Options["LinkTimeCodeGeneration"] = "true"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG"; }) @@ -1664,6 +1667,7 @@ private void GenerateLinkerOptions(IGenerationContext context, ProjectOptionsGen context.SelectOption ( Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.Default, () => { context.Options["LinkTimeCodeGeneration"] = "Default"; context.CommandLineOptions["LinkTimeCodeGeneration"] = FileGeneratorUtilities.RemoveLineTag; }), + Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.UseFastLinkTimeCodeGeneration, () => { context.Options["LinkTimeCodeGeneration"] = "UseFastLinkTimeCodeGeneration"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG:incremental"; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.UseLinkTimeCodeGeneration, () => { context.Options["LinkTimeCodeGeneration"] = "UseLinkTimeCodeGeneration"; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG"; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.ProfileGuidedOptimizationInstrument, () => { context.Options["LinkTimeCodeGeneration"] = "PGInstrument"; profileGuideOptimization = true; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG:PGInstrument"; }), Options.Option(Options.Vc.Linker.LinkTimeCodeGeneration.ProfileGuidedOptimizationOptimize, () => { context.Options["LinkTimeCodeGeneration"] = "PGOptimization"; profileGuideOptimization = true; context.CommandLineOptions["LinkTimeCodeGeneration"] = "/LTCG:PGOptimize"; }), @@ -1690,26 +1694,21 @@ private void GenerateLinkerOptions(IGenerationContext context, ProjectOptionsGen context.Options["FunctionOrder"] = (fctOrder != null) ? fctOrder.Order : FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["FunctionOrder"] = (fctOrder != null) ? @"/ORDER:@""" + fctOrder.Order + @"""" : FileGeneratorUtilities.RemoveLineTag; - // ForceFileOutput context.SelectOption ( Options.Option(Options.Vc.Linker.ForceFileOutput.Default, () => { context.Options["ForceFileOutput"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["ForceFileOutput"] = FileGeneratorUtilities.RemoveLineTag; }), - Options.Option(Options.Vc.Linker.ForceFileOutput.MultiplyDefinedSymbolOnly, () => { context.Options["ForceFileOutput"] = "MultiplyDefinedSymbolOnly"; context.CommandLineOptions["ForceFileOutput"] = "/FORCE:MULTIPLE"; }) + Options.Option(Options.Vc.Linker.ForceFileOutput.Enable, () => { context.Options["ForceFileOutput"] = "Enabled"; context.CommandLineOptions["ForceFileOutput"] = "/FORCE"; }), + Options.Option(Options.Vc.Linker.ForceFileOutput.MultiplyDefinedSymbolOnly, () => { context.Options["ForceFileOutput"] = "MultiplyDefinedSymbolOnly"; context.CommandLineOptions["ForceFileOutput"] = "/FORCE:MULTIPLE"; }), + Options.Option(Options.Vc.Linker.ForceFileOutput.UndefinedSymbolOnly, () => { context.Options["ForceFileOutput"] = "UndefinedSymbolOnly"; context.CommandLineOptions["ForceFileOutput"] = "/FORCE:UNRESOLVED"; }) ); - //CreateHotPatchableImage - // Disable - // Enable CreateHotPatchableImage="Enabled" /FUNCTIONPADMIN - // X86Image CreateHotPatchableImage="X86Image" /FUNCTIONPADMIN:5 - // X64Image CreateHotPatchableImage="X64Image" /FUNCTIONPADMIN:6 - // ItaniumImage CreateHotPatchableImage="ItaniumImage" /FUNCTIONPADMIN:16 context.SelectOption ( - Options.Option(Options.Vc.Linker.CreateHotPatchableImage.Disable, () => { context.Options["CreateHotPatchableImage"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["CreateHotPatchableImage"] = FileGeneratorUtilities.RemoveLineTag; }), - Options.Option(Options.Vc.Linker.CreateHotPatchableImage.Enable, () => { context.Options["CreateHotPatchableImage"] = "Enabled"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN"; }), - Options.Option(Options.Vc.Linker.CreateHotPatchableImage.X86Image, () => { context.Options["CreateHotPatchableImage"] = "X86Image"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN:5"; }), - Options.Option(Options.Vc.Linker.CreateHotPatchableImage.X64Image, () => { context.Options["CreateHotPatchableImage"] = "X64Image"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN:6"; }), - Options.Option(Options.Vc.Linker.CreateHotPatchableImage.ItaniumImage, () => { context.Options["CreateHotPatchableImage"] = "ItaniumImage"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN:16"; }) + Options.Option(Options.Vc.Linker.CreateHotPatchableImage.Disable, () => { context.Options["CreateHotPatchableImage"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["CreateHotPatchableImage"] = FileGeneratorUtilities.RemoveLineTag; }), + Options.Option(Options.Vc.Linker.CreateHotPatchableImage.Enable, () => { context.Options["CreateHotPatchableImage"] = "Enabled"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN"; }), + Options.Option(Options.Vc.Linker.CreateHotPatchableImage.X86Image, () => { context.Options["CreateHotPatchableImage"] = "X86Image"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN:5"; }), + Options.Option(Options.Vc.Linker.CreateHotPatchableImage.X64Image, () => { context.Options["CreateHotPatchableImage"] = "X64Image"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN:6"; }), + Options.Option(Options.Vc.Linker.CreateHotPatchableImage.ItaniumImage, () => { context.Options["CreateHotPatchableImage"] = "ItaniumImage"; context.CommandLineOptions["CreateHotPatchableImage"] = "/FUNCTIONPADMIN:16"; }) ); context.SelectOption @@ -2011,12 +2010,6 @@ private void GenerateLLVMOptions(IGenerationContext context, ProjectOptionsGener ); } - [Obsolete("Use MakeBuildStepName taking the 2 extra arguments projectRootPath and rootPath", error: true)] - public static string MakeBuildStepName(Project.Configuration conf, Project.Configuration.BuildStepBase eventBuildStep, Vcxproj.BuildStep buildStep) - { - return null; - } - public static string MakeBuildStepName(Project.Configuration conf, Project.Configuration.BuildStepBase eventBuildStep, Vcxproj.BuildStep buildStep, string projectRootPath, string projectPath) { if (!eventBuildStep.IsResolved) diff --git a/Sharpmake.Generators/VisualStudio/Pyproj.Template.cs b/Sharpmake.Generators/VisualStudio/Pyproj.Template.cs index 130646ead..99e2d30ff 100644 --- a/Sharpmake.Generators/VisualStudio/Pyproj.Template.cs +++ b/Sharpmake.Generators/VisualStudio/Pyproj.Template.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2019-2020 Ubisoft Entertainment +// Copyright (c) 2017, 2019-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -38,7 +38,6 @@ public static class Project public static string ProjectDescription = @" - Debug 2.0 [guid] [projectHome] @@ -51,7 +50,6 @@ public static class Project [interpreterId] [interpreterVersion] - 10.0 [ptvsTargetsFile] diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs index dd45aefa7..560e88e3f 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Ubisoft Entertainment +// Copyright (c) 2020-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -125,11 +125,6 @@ public virtual void SelectPreprocessorDefinitionsBff(IBffGenerationContext conte } } - [Obsolete("Use " + nameof(SetupExtraLinkerSettings) + " and pass the conf", error: true)] - public void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration.OutputType outputType, string fastBuildOutputFile) - { - } - public void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration configuration, string fastBuildOutputFile) { string outputTypeArgument; diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BaseMicrosoftPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BaseMicrosoftPlatform.cs index 736ec5fa9..fefbb0424 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BaseMicrosoftPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BaseMicrosoftPlatform.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -101,7 +101,7 @@ protected void GetLinkerExecutableInfo(Project.Configuration conf, out string li if (useLldLink == Options.Vc.LLVM.UseLldLink.Enable || (useLldLink == Options.Vc.LLVM.UseLldLink.Default && platformToolset.IsLLVMToolchain())) { - linkerPathOverride = Path.Combine(ClangForWindows.Settings.LLVMInstallDir, "bin"); + linkerPathOverride = platformToolset == Options.Vc.General.PlatformToolset.ClangCL ? ClangForWindows.GetWindowsClangExecutablePath(conf.Target.GetFragment()) : ClangForWindows.GetWindowsClangExecutablePath(); linkerExeOverride = "lld-link.exe"; librarianExeOverride = "llvm-lib.exe"; } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs index 3094672e2..bc92cde8a 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.Vcxproj.Template.cs @@ -184,6 +184,7 @@ public abstract partial class BasePlatform [options.CLRSupport] [options.WindowsTargetPlatformVersion] [options.SpectreMitigation] + [options.EnableASAN] "; diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs index 6a6bec12f..cbbadb812 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/BasePlatform.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -109,12 +109,6 @@ public virtual void SelectPreprocessorDefinitionsBff(IBffGenerationContext conte } } - [Obsolete("Use " + nameof(SetupExtraLinkerSettings) + " and pass the conf")] - public virtual void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration.OutputType outputType, string fastBuildOutputFile) - { - SetupExtraLinkerSettings(fileGenerator, outputType); - } - public virtual void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration configuration, string fastBuildOutputFile) { SetupExtraLinkerSettings(fileGenerator, configuration.Output); @@ -475,12 +469,6 @@ protected virtual IEnumerable GetPlatformIncludePathsWithPref yield break; } - [Obsolete("Implement GetPlatformIncludePathsWithPrefixImpl instead")] - protected virtual IEnumerable GetPlatformIncludePathsImpl(IGenerationContext context) - { - yield break; - } - protected virtual IEnumerable GetResourceIncludePathsImpl(IGenerationContext context) { var resourceIncludePaths = new OrderableStrings(); diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/DefaultPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/DefaultPlatform.cs index 667845d74..a9a030ebd 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/DefaultPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/DefaultPlatform.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -108,12 +108,6 @@ public override bool AddLibPrefix(Configuration conf) return false; } - [Obsolete("Use " + nameof(SetupExtraLinkerSettings) + " and pass the conf")] - public override void SetupExtraLinkerSettings(IFileGenerator fileGenerator, Project.Configuration.OutputType outputType, string fastBuildOutputFile) - { - base.SetupExtraLinkerSettings(fileGenerator, outputType, fastBuildOutputFile); - } - public override void AddCompilerSettings(IDictionary masterCompilerSettings, Project.Configuration conf) { } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.Vcxproj.Template.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.Vcxproj.Template.cs index bea0237fd..f18eb420e 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.Vcxproj.Template.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Linux/LinuxPlatform.Vcxproj.Template.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Ubisoft Entertainment +// Copyright (c) 2020-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -97,8 +97,8 @@ public sealed partial class LinuxPlatform private const string _projectConfigurationsGeneral2 = @" [options.OutputFileName] - [options.OutputDirectoryRemote]\ - [options.IntermediateDirectoryRemote]\ + [options.OutputDirectoryRemote] + [options.IntermediateDirectoryRemote] [options.OutputFileExtension] [options.GenerateManifest] [options.PostBuildEventEnable] @@ -125,8 +125,8 @@ public sealed partial class LinuxPlatform $(TargetDir) [options.ProjectDirectory] -[options.OutputDirectoryRemote]\ -[options.IntermediateDirectoryRemote]\ +[options.OutputDirectoryRemote] +[options.IntermediateDirectoryRemote] cd [relativeMasterBffPath] [conf.FastBuildCustomActionsBeforeBuildCommand] [fastBuildMakeCommandBuild] diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Properties/AssemblyInfo.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Properties/AssemblyInfo.cs index 1268d200c..4348ae04f 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Properties/AssemblyInfo.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Properties/AssemblyInfo.cs @@ -44,6 +44,6 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.15.1.0")] +[assembly: AssemblyVersion("0.16.0.0")] [assembly: SharpmakeExtension] diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/BaseWindowsPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/BaseWindowsPlatform.cs index 0100d8053..0b4cfa3b9 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/BaseWindowsPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/BaseWindowsPlatform.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -45,7 +45,7 @@ public override IEnumerable GetImplicitlyDefinedSymbols(IGenerationConte case Project.Configuration.OutputType.Exe: context.SelectOption( Options.Option(Options.Vc.Linker.SubSystem.Console, () => { defines.Add("_CONSOLE"); }), - Options.Option(Options.Vc.Linker.SubSystem.Application, () => { defines.Add("_WINDOWS"); })); + Options.Option(Options.Vc.Linker.SubSystem.Windows, () => { defines.Add("_WINDOWS"); })); break; case Project.Configuration.OutputType.Lib: defines.Add("_LIB"); @@ -101,23 +101,6 @@ public override void SetupSdkOptions(IGenerationContext context) } } - Options.Vc.General.PlatformToolset platformToolset = Options.GetObject(conf); - if (platformToolset.IsLLVMToolchain()) - { - Options.Vc.General.PlatformToolset overridenPlatformToolset = Options.Vc.General.PlatformToolset.Default; - if (Options.WithArgOption.Get(conf, ref overridenPlatformToolset)) - platformToolset = overridenPlatformToolset; - - devEnv = platformToolset.GetDefaultDevEnvForToolset() ?? devEnv; - - context.Options["ExecutablePath"] = ClangForWindows.GetWindowsClangExecutablePath() + ";" + devEnv.GetWindowsExecutablePath(conf.Platform); - if (Options.GetObject(conf) == Options.Vc.LLVM.UseClangCl.Enable) - { - context.Options["IncludePath"] = ClangForWindows.GetWindowsClangIncludePath() + ";" + devEnv.GetWindowsIncludePath(); - context.Options["LibraryPath"] = ClangForWindows.GetWindowsClangLibraryPath() + ";" + devEnv.GetWindowsLibraryPath(conf.Platform, Util.IsDotNet(conf) ? conf.Target.GetFragment() : default(DotNetFramework?)); - } - } - var systemIncludes = new OrderableStrings(conf.DependenciesIncludeSystemPaths); systemIncludes.AddRange(conf.IncludeSystemPaths); if (systemIncludes.Count > 0) diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/ClangForWindowsSettings.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/ClangForWindowsSettings.cs index 7393e1d9e..ea21e0e08 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/ClangForWindowsSettings.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/ClangForWindowsSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020 Ubisoft Entertainment +// Copyright (c) 2019-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Collections.Concurrent; using System.IO; using System.Linq; using Sharpmake.Generators; @@ -26,16 +27,31 @@ public static string GetWindowsClangExecutablePath() return Path.Combine(Settings.LLVMInstallDir, "bin"); } + public static string GetWindowsClangExecutablePath(DevEnv devEnv) + { + return Path.Combine(Settings.LLVMInstallDirVsEmbedded(devEnv), "bin"); + } + public static string GetWindowsClangIncludePath() { return Path.Combine(Settings.LLVMInstallDir, "lib", "clang", Settings.ClangVersion, "include"); } + public static string GetWindowsClangIncludePath(DevEnv devEnv) + { + return Path.Combine(Settings.LLVMInstallDirVsEmbedded(devEnv), "lib", "clang", Settings.ClangVersionVsEmbedded(devEnv), "include"); + } + public static string GetWindowsClangLibraryPath() { return Path.Combine(Settings.LLVMInstallDir, "lib", "clang", Settings.ClangVersion, "lib", "windows"); } + public static string GetWindowsClangLibraryPath(DevEnv devEnv) + { + return Path.Combine(Settings.LLVMInstallDirVsEmbedded(devEnv), "lib", "clang", Settings.ClangVersionVsEmbedded(devEnv), "lib", "windows"); + } + public static class Settings { public static bool OverridenLLVMInstallDir { get; private set; } @@ -55,6 +71,15 @@ public static string LLVMInstallDir } } + public static string LLVMInstallDirVsEmbedded(DevEnv devEnv) + { + if (OverridenLLVMInstallDir) + return LLVMInstallDir; + + string vsDir = devEnv.GetVisualStudioDir(); + return Path.Combine(vsDir, "VC", "Tools", "Llvm", "x64"); + } + private static string s_clangVersion; public static string ClangVersion { @@ -77,6 +102,18 @@ public static string ClangVersion throw new Error($"Cannot find required files for Clang {s_clangVersion} in {LLVMInstallDir}"); } } + + private static readonly ConcurrentDictionary s_vsEmbeddedClangVersion = new ConcurrentDictionary(); + public static string ClangVersionVsEmbedded(DevEnv devEnv) + { + if (OverridenLLVMInstallDir) + return ClangVersion; + + return s_vsEmbeddedClangVersion.GetOrAdd(devEnv, d => + { + return Util.GetClangVersionFromLLVMInstallDir(LLVMInstallDirVsEmbedded(devEnv)); + }); + } } public static void WriteLLVMOverrides(IVcxprojGenerationContext context, IFileGenerator generator) @@ -90,13 +127,25 @@ public static string GetLLVMOverridesSection(IVcxprojGenerationContext context, { if (Settings.OverridenLLVMInstallDir) { - bool hasClangConfiguration = context.ProjectConfigurations.Any(conf => Options.GetObject(conf).IsLLVMToolchain()); - - if (hasClangConfiguration) + var allPlatformToolsets = context.ProjectConfigurations.Select(Options.GetObject); + var llvmToolsets = allPlatformToolsets.Where(t => t.IsLLVMToolchain()).Distinct().ToList(); + if (llvmToolsets.Count > 0) { - using (resolver.NewScopedParameter("custompropertyname", "LLVMInstallDir")) - using (resolver.NewScopedParameter("custompropertyvalue", Settings.LLVMInstallDir.TrimEnd(Util._pathSeparators))) // trailing separator will be added by LLVM.Cpp.Common.props - return resolver.Resolve(Vcxproj.Template.Project.CustomProperty); + if (llvmToolsets.Count == 1) + { + if (context.DevelopmentEnvironmentsRange.MinDevEnv != context.DevelopmentEnvironmentsRange.MaxDevEnv) + throw new Error("Different vs versions not supported in the same vcxproj"); + var devEnv = context.DevelopmentEnvironmentsRange.MinDevEnv; + + var llvmInstallDir = llvmToolsets[0] == Options.Vc.General.PlatformToolset.ClangCL ? Settings.LLVMInstallDirVsEmbedded(devEnv) : Settings.LLVMInstallDir; + using (resolver.NewScopedParameter("custompropertyname", "LLVMInstallDir")) + using (resolver.NewScopedParameter("custompropertyvalue", llvmInstallDir.TrimEnd(Util._pathSeparators))) // trailing separator will be added by LLVM.Cpp.Common.props + return resolver.Resolve(Vcxproj.Template.Project.CustomProperty); + } + else + { + throw new Error("Varying llvm platform toolsets in the same vcxproj file! That's not supported"); + } } } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs index 49df27317..ceddf421a 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Windows/Win64Platform.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -164,12 +164,10 @@ bool useCCompiler case Options.Vc.General.PlatformToolset.v142: compilerDevEnv = DevEnv.vs2019; break; - case Options.Vc.General.PlatformToolset.LLVM_vs2012: - case Options.Vc.General.PlatformToolset.LLVM_vs2014: case Options.Vc.General.PlatformToolset.LLVM: case Options.Vc.General.PlatformToolset.ClangCL: - platformToolSetPath = ClangForWindows.Settings.LLVMInstallDir; + platformToolSetPath = platformToolset == Options.Vc.General.PlatformToolset.ClangCL ? ClangForWindows.Settings.LLVMInstallDirVsEmbedded(devEnv) : ClangForWindows.Settings.LLVMInstallDir; pathToCompiler = Path.Combine(platformToolSetPath, "bin"); compilerExeName = "clang-cl.exe"; @@ -421,18 +419,22 @@ protected override IEnumerable GetPlatformIncludePathsWithPre string includePrefix = "/I"; var platformToolset = Options.GetObject(context.Configuration); + DevEnv devEnv = platformToolset.GetDefaultDevEnvForToolset() ?? context.DevelopmentEnvironment; + if (platformToolset.IsLLVMToolchain() && Options.GetObject(context.Configuration) == Options.Vc.LLVM.UseClangCl.Enable) { includePrefix = "/clang:-isystem"; - string clangIncludePath = ClangForWindows.GetWindowsClangIncludePath(); - includes.Add(new IncludeWithPrefix(includePrefix, clangIncludePath)); Options.Vc.General.PlatformToolset overridenPlatformToolset = Options.Vc.General.PlatformToolset.Default; if (Options.WithArgOption.Get(context.Configuration, ref overridenPlatformToolset)) + { platformToolset = overridenPlatformToolset; - } + devEnv = platformToolset.GetDefaultDevEnvForToolset() ?? context.DevelopmentEnvironment; + } - DevEnv devEnv = platformToolset.GetDefaultDevEnvForToolset() ?? context.DevelopmentEnvironment; + string clangIncludePath = platformToolset == Options.Vc.General.PlatformToolset.ClangCL ? ClangForWindows.GetWindowsClangIncludePath(devEnv) : ClangForWindows.GetWindowsClangIncludePath(); + includes.Add(new IncludeWithPrefix(includePrefix, clangIncludePath)); + } // when using clang-cl, mark MSVC includes, so they are properly recognized IEnumerable msvcIncludePaths = EnumerateSemiColonSeparatedString(devEnv.GetWindowsIncludePath()); diff --git a/Sharpmake.Platforms/Sharpmake.NvShield/Properties/AssemblyInfo.cs b/Sharpmake.Platforms/Sharpmake.NvShield/Properties/AssemblyInfo.cs index 50d5021f7..1f6d7a429 100644 --- a/Sharpmake.Platforms/Sharpmake.NvShield/Properties/AssemblyInfo.cs +++ b/Sharpmake.Platforms/Sharpmake.NvShield/Properties/AssemblyInfo.cs @@ -44,6 +44,6 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.15.1.0")] +[assembly: AssemblyVersion("0.16.0.0")] [assembly: SharpmakeExtension] diff --git a/Sharpmake.Platforms/Sharpmake.X360/Properties/AssemblyInfo.cs b/Sharpmake.Platforms/Sharpmake.X360/Properties/AssemblyInfo.cs index cf79ec998..79265a99b 100644 --- a/Sharpmake.Platforms/Sharpmake.X360/Properties/AssemblyInfo.cs +++ b/Sharpmake.Platforms/Sharpmake.X360/Properties/AssemblyInfo.cs @@ -44,6 +44,6 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.15.1.0")] +[assembly: AssemblyVersion("0.16.0.0")] [assembly: SharpmakeExtension] diff --git a/Sharpmake.UnitTests/Sharpmake.UnitTests.sharpmake.cs b/Sharpmake.UnitTests/Sharpmake.UnitTests.sharpmake.cs index 3640383a3..edb202f85 100644 --- a/Sharpmake.UnitTests/Sharpmake.UnitTests.sharpmake.cs +++ b/Sharpmake.UnitTests/Sharpmake.UnitTests.sharpmake.cs @@ -24,7 +24,7 @@ public override void ConfigureAll(Configuration conf, Target target) { base.ConfigureAll(conf, target); - conf.TargetPath = @"[project.RootPath]\tmp\unittests\[target.Optimization]"; + conf.TargetPath = @"[project.RootPath]\tmp\unittests\[lower:target.Optimization]"; conf.AddPrivateDependency(target); conf.AddPrivateDependency(target); diff --git a/Sharpmake/Assembler.cs b/Sharpmake/Assembler.cs index 908d98d18..9e3ca8ca6 100644 --- a/Sharpmake/Assembler.cs +++ b/Sharpmake/Assembler.cs @@ -32,12 +32,6 @@ public class Assembler public const Options.CSharp.LanguageVersion SharpmakeScriptsCSharpVersion = Options.CSharp.LanguageVersion.CSharp7; public const DotNetFramework SharpmakeDotNetFramework = DotNetFramework.v4_7_2; - /// - /// Extra user directory to load assembly from using statement detection - /// - [Obsolete("AssemblyDirectory is not used anymore")] - public List AssemblyDirectory { get { return _assemblyDirectory; } } - /// /// Extra user assembly to use while compiling /// @@ -490,7 +484,6 @@ private Assembly Compile(IBuilderContext builderContext, IEnumerable return Assembly.Load(dllStream.GetBuffer(), pdbStream.GetBuffer()); } - } return null; diff --git a/Sharpmake/AttributeParsers.cs b/Sharpmake/AttributeParsers.cs index 1655da386..217afc958 100644 --- a/Sharpmake/AttributeParsers.cs +++ b/Sharpmake/AttributeParsers.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2020 Ubisoft Entertainment +// Copyright (c) 2018-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -175,7 +175,7 @@ public override void ParseParameter(string[] parameters, FileInfo sourceFilePath public class PackageAttributeParser : SimpleSourceAttributeParser { - private readonly Dictionary _assemblies = new Dictionary(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary s_assemblies = new Dictionary(StringComparer.OrdinalIgnoreCase); public PackageAttributeParser() : base("Package", 1, "Sharpmake") { @@ -199,14 +199,14 @@ public override void ParseParameter(string[] parameters, FileInfo sourceFilePath } IAssemblyInfo assemblyInfo; - if (_assemblies.TryGetValue(includeAbsolutePath, out assemblyInfo)) + if (s_assemblies.TryGetValue(includeAbsolutePath, out assemblyInfo)) { if (assemblyInfo == null) throw new Error($"Circular Sharpmake.Package dependency on {includeFilename}"); context.AddReference(assemblyInfo); return; } - _assemblies[includeAbsolutePath] = null; + s_assemblies[includeAbsolutePath] = null; string[] files; if (Util.IsPathWithWildcards(includeFilename)) @@ -224,7 +224,7 @@ public override void ParseParameter(string[] parameters, FileInfo sourceFilePath } assemblyInfo = context.BuildLoadAndAddReferenceToSharpmakeFilesAssembly(files); - _assemblies[includeAbsolutePath] = assemblyInfo; + s_assemblies[includeAbsolutePath] = assemblyInfo; } } diff --git a/Sharpmake/DebugProjectGenerator.cs b/Sharpmake/DebugProjectGenerator.cs index 9ae0ef65b..9fcedf4dc 100644 --- a/Sharpmake/DebugProjectGenerator.cs +++ b/Sharpmake/DebugProjectGenerator.cs @@ -29,16 +29,11 @@ public static class DebugProjectGenerator internal static string RootPath { get; private set; } internal static string[] MainSources { get; private set; } - [Obsolete("Implement IDebugProjectExtension instead to override sharpmake package version")] - public static string PackageVersion { get; set; } - - [Obsolete("Implement IDebugProjectExtension instead to override sharpmake package version")] - public static string PackageName { get; set; } - public interface IDebugProjectExtension { void AddSharpmakePackage(Project.Configuration config); void AddReferences(Project.Configuration config, IEnumerable additionalReferences = null); + string GetSharpmakeExecutableFullPath(); } public class DefaultDebugProjectExtension : IDebugProjectExtension @@ -77,6 +72,19 @@ public virtual bool ShouldUseLocalSharpmakeDll() { return true; } + + public virtual string GetSharpmakeExecutableFullPath() + { + string sharpmakeApplicationExePath = Process.GetCurrentProcess().MainModule.FileName; + + if (Util.IsRunningInMono()) + { + // When running within Mono, sharpmakeApplicationExePath will at this point wrongly refer to the + // mono (or mono-sgen) executable. Fix it so that it points to Sharpmake.Application.exe. + sharpmakeApplicationExePath = $"{AppDomain.CurrentDomain.BaseDirectory}{AppDomain.CurrentDomain.FriendlyName}"; + } + return sharpmakeApplicationExePath; + } } public static IDebugProjectExtension DebugProjectExtension { get; set; } = new DefaultDebugProjectExtension(); @@ -241,21 +249,12 @@ internal static Target GetTargets() /// public static void SetupProjectOptions(this Project.Configuration conf, string startArguments) { - string sharpmakeApplicationExePath = Process.GetCurrentProcess().MainModule.FileName; - - if (Util.IsRunningInMono()) - { - // When running within Mono, sharpmakeApplicationExePath will at this point wrongly refer to the - // mono (or mono-sgen) executable. Fix it so that it points to Sharpmake.Application.exe. - sharpmakeApplicationExePath = $"{AppDomain.CurrentDomain.BaseDirectory}{AppDomain.CurrentDomain.FriendlyName}"; - } - conf.CsprojUserFile = new Project.Configuration.CsprojUserFileSettings(); conf.CsprojUserFile.StartAction = Project.Configuration.CsprojUserFileSettings.StartActionSetting.Program; string quote = "\'"; // Use single quote that is cross platform safe conf.CsprojUserFile.StartArguments = $@"/sources(@{quote}{string.Join(";", MainSources)}{quote}) {startArguments}"; - conf.CsprojUserFile.StartProgram = sharpmakeApplicationExePath; + conf.CsprojUserFile.StartProgram = DebugProjectExtension.GetSharpmakeExecutableFullPath(); } } diff --git a/Sharpmake/ExtensionMethods.cs b/Sharpmake/ExtensionMethods.cs index 268de2f5b..206909d5e 100644 --- a/Sharpmake/ExtensionMethods.cs +++ b/Sharpmake/ExtensionMethods.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020 Ubisoft Entertainment +// Copyright (c) 2017-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -755,8 +755,6 @@ public static bool IsDefaultToolsetForDevEnv(this Options.Vc.General.PlatformToo case Options.Vc.General.PlatformToolset.v120_xp: case Options.Vc.General.PlatformToolset.v140_xp: case Options.Vc.General.PlatformToolset.v141_xp: - case Options.Vc.General.PlatformToolset.LLVM_vs2012: - case Options.Vc.General.PlatformToolset.LLVM_vs2014: case Options.Vc.General.PlatformToolset.LLVM: case Options.Vc.General.PlatformToolset.ClangCL: case Options.Vc.General.PlatformToolset.Default: @@ -788,8 +786,6 @@ public static bool IsDefaultToolsetForDevEnv(this Options.Vc.General.PlatformToo return DevEnv.vs2017; case Options.Vc.General.PlatformToolset.v142: return DevEnv.vs2019; - case Options.Vc.General.PlatformToolset.LLVM_vs2012: - case Options.Vc.General.PlatformToolset.LLVM_vs2014: case Options.Vc.General.PlatformToolset.LLVM: case Options.Vc.General.PlatformToolset.ClangCL: return null; @@ -831,8 +827,6 @@ public static bool IsLLVMToolchain(this Options.Vc.General.PlatformToolset platf { switch (platformToolset) { - case Options.Vc.General.PlatformToolset.LLVM_vs2012: - case Options.Vc.General.PlatformToolset.LLVM_vs2014: case Options.Vc.General.PlatformToolset.LLVM: case Options.Vc.General.PlatformToolset.ClangCL: return true; diff --git a/Sharpmake/FakeFileTree.cs b/Sharpmake/FakeFileTree.cs index 9965be2e7..05242e336 100644 --- a/Sharpmake/FakeFileTree.cs +++ b/Sharpmake/FakeFileTree.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2019 Ubisoft Entertainment +// Copyright (c) 2017-2019, 2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -266,6 +266,8 @@ public static string[] DirectoryGetDirectories(string path, string searchPattern return new string[] { }; } + internal static readonly char[] WildcardCharacters = { '*', '?' }; + public static bool IsPathWithWildcards(string path) { return path.IndexOfAny(Util.WildcardCharacters) != -1; diff --git a/Sharpmake/FastBuildSettings.cs b/Sharpmake/FastBuildSettings.cs index f4d8f8e27..3c3842dca 100644 --- a/Sharpmake/FastBuildSettings.cs +++ b/Sharpmake/FastBuildSettings.cs @@ -104,25 +104,6 @@ public enum CacheTypes // Configuration Files Generation Settings - /// - /// Include the IDE version in master bff filename - /// - [Obsolete("MasterBff is now named after the solution")] - public static bool IncludeCompilerInMasterBFFFilename = true; - - /// - /// Separate the Master bff content per platform - /// - [Obsolete("MasterBff contains what its solution contains")] - public static bool SeparateMasterBFFPerPlatform = false; - - /// - /// The path of the master BFF is the folder relative to the source tree root. - /// ex: "projects" - /// - [Obsolete("MasterBff is now in the same folder as the solution")] - public static string FastBuildMasterBFFPath = null; // PLEASE OVERRIDE this in your Sharpmake main - /// /// The path to the executable used to start a fastbuild compilation. This path is relative to the source tree root. /// ex: @"tools\FastBuild\start-fbuild.bat" diff --git a/Sharpmake/KitsRootPaths.cs b/Sharpmake/KitsRootPaths.cs index 32f529647..cd70ec16d 100644 --- a/Sharpmake/KitsRootPaths.cs +++ b/Sharpmake/KitsRootPaths.cs @@ -33,9 +33,6 @@ public class KitsRootPaths private static ConcurrentDictionary s_windowsTargetPlatformVersionInstalled = new ConcurrentDictionary(); - [Obsolete("WindowsTargetPlatformVersion is per DevEnv, please use " + nameof(GetWindowsTargetPlatformVersionForDevEnv) + " instead", error: true)] - public static Options.Vc.General.WindowsTargetPlatformVersion WindowsTargetPlatformVersion { get; private set; } = Options.Vc.General.WindowsTargetPlatformVersion.v8_1; - private static KitsRootPaths s_kitsRootsInstance = new KitsRootPaths(); public KitsRootPaths() @@ -150,12 +147,6 @@ public static Options.Vc.General.WindowsTargetPlatformVersion GetWindowsTargetPl throw new NotImplementedException("No WindowsTargetPlatformVersion associated with " + devEnv); } - [Obsolete("WindowsTargetPlatformVersion is per DevEnv, please use " + nameof(GetWindowsTargetPlatformVersionForDevEnv) + " instead", error: true)] - public static string GetWindowsTargetPlatformVersion() - { - throw new Error(); - } - public static string GetNETFXKitsDir(DotNetFramework dotNetFramework) { string netFxKitsDir; diff --git a/Sharpmake/Options.CSharp.cs b/Sharpmake/Options.CSharp.cs index 90619c5ef..f739e81cf 100644 --- a/Sharpmake/Options.CSharp.cs +++ b/Sharpmake/Options.CSharp.cs @@ -28,15 +28,6 @@ public enum DefaultConfiguration Other } - [Obsolete("Use the DefaultPlatform CSharpProject member")] - public enum DefaultPlatform - { - [Default] - AnyCPU, - x86, - x64 - } - public enum FileAlignment { None, diff --git a/Sharpmake/Options.Vc.cs b/Sharpmake/Options.Vc.cs index 7f97b9100..98f9426ea 100644 --- a/Sharpmake/Options.Vc.cs +++ b/Sharpmake/Options.Vc.cs @@ -21,6 +21,12 @@ public static class Vc { public static class General { + /// + /// Platform Toolset + /// + /// + /// Specifies which build tools will be used. + /// public enum PlatformToolset { [Default] @@ -45,16 +51,23 @@ public enum PlatformToolset v141_xp, // Visual Studio 2017 - Windows XP [DevEnvVersion(minimum = DevEnv.vs2019)] v142, // Visual Studio 2019 - [DevEnvVersion(minimum = DevEnv.vs2012)] - LLVM_vs2012, // LLVM from Visual Studio 2012 - [DevEnvVersion(minimum = DevEnv.vs2015)] - LLVM_vs2014, // LLVM from Visual Studio 2015 [DevEnvVersion(minimum = DevEnv.vs2017)] LLVM, // LLVM from Visual Studio 2017 [DevEnvVersion(minimum = DevEnv.vs2019)] ClangCL, // LLVM as of Visual Studio 2019 official extension + + [Obsolete("Use either LLVM or ClangCL", error: true)] + LLVM_vs2012, + [Obsolete("Use either LLVM or ClangCL", error: true)] + LLVM_vs2014, } + /// + /// Windows SDK Version + /// + /// + /// Specifies which version of the Windows SDK to use. + /// public enum WindowsTargetPlatformVersion { v8_1, @@ -70,33 +83,114 @@ public enum WindowsTargetPlatformVersion Latest, // latest available in host machine } + /// + /// Character Set + /// + /// + /// Tells the compiler to use the specified character set; aids in localization issues. + /// public enum CharacterSet { + /// + /// Not Set + /// Default, + + /// + /// Use Unicode Character Set + /// Unicode, + + /// + /// Use Multi-Byte Character Set + /// [Default] MultiByte } + /// + /// Whole Program Optimization + /// + /// + /// Enables cross-module optimizations by delaying code generation to link time; requires that linker option 'Link Time Code Generation' be turned on. + /// public enum WholeProgramOptimization { + /// + /// No Whole Program Optimization + /// [Default] Disable, + + /// + /// Use Link Time Code Generation + /// LinkTime, + + /// + /// Profile Guided Optimization - Instrument + /// Instrument, + + /// + /// Profile Guided Optimization - Optimize + /// Optimize, + + /// + /// Profile Guided Optimization - Update + /// Update } + /// + /// Debug Information Format + /// + /// + /// Specifies the type of debugging information generated by the compiler. This requires compatible linker settings. + /// public enum DebugInformation { + /// + /// None + /// + /// + /// Produces no debugging information, so compilation may be faster. + /// Disable, + + /// + /// C7 compatible + /// + /// + /// Select the type of debugging information created for your program and whether this information is kept in object (.obj) files or in a program database (PDB). + /// C7Compatible, + + /// + /// Program Database + /// + /// + /// Produces a program database (PDB) that contains type information and symbolic debugging information for use with the debugger. The symbolic debugging information includes the names and types of variables, as well as functions and line numbers. + /// [Default] ProgramDatabase, + + /// + /// Program Database for Edit And Continue + /// + /// + /// Produces a program database, as described above, in a format that supports the Edit and Continue feature. + /// ProgramDatabaseEnC } + /// + /// Use Debug Libraries + /// + /// + /// Specifies whether this configuration should use debug libraries and debug switches + /// public enum UseDebugLibraries { [Default(DefaultTarget.Debug)] @@ -105,26 +199,55 @@ public enum UseDebugLibraries Disabled } + /// + /// Warning Level + /// + /// + /// Select how strict you want the compiler to be about code errors. + /// public enum WarningLevel { + /// + /// Turn Off All Warnings + /// + /// + /// Level 0 disables all warnings. + /// Level0, + + /// + /// Level 1 displays severe warnings. Level 1 is the default warning level at the command line. + /// Level1, + + /// + /// Level 2 displays all level 1 warnings and warnings less severe than level 1. + /// Level2, + + /// + /// Level 3 displays all level 2 warnings and all other warnings recommended for production purposes. + /// Level3, + + /// + /// Level 4 displays all level 3 warnings plus informational warnings, which in most cases can be safely ignored. + /// [Default] Level4, - EnableAllWarnings - } - [Obsolete("Use option TreatWarningsAsErrors instead")] - public enum TreatWarningAsError - { - Enable, - [Default] - Disable + /// + /// Enables all warnings, including those disabled by default. + /// + EnableAllWarnings } - + /// + /// Treat Warnings As Errors + /// + /// + /// Treats all compiler warnings as errors. For a new project, it may be best to use /WX in all compilations; resolving all warnings will ensure the fewest possible hard-to-find code defects. + /// public enum TreatWarningsAsErrors { Enable, @@ -132,16 +255,39 @@ public enum TreatWarningsAsErrors Disable } + /// + /// Diagnostics Format + /// + /// + /// Enables rich diagnostics, with column information and source context in diagnostic messages. + /// public enum DiagnosticsFormat { - [Default] - Classic, // default, only show the line number + /// + /// Provides column information in the diagnostic message, as well as outputting the relevant line of source code with a caret indicating the offending column. + /// [DevEnvVersion(minimum = DevEnv.vs2017)] - ColumnInfo, // line + column + Caret, + + /// + /// Additionally provides the column number within the line where the diagnostic is issued, where applicable. + /// [DevEnvVersion(minimum = DevEnv.vs2017)] - Caret // context + caret + ColumnInfo, + + /// + /// Retains the prior, concise diagnostic messages with the line number. + /// + [Default] + Classic } + /// + /// Enable Managed Incremental Build + /// + /// + /// Enables managed incremental build scenarios using metagen. + /// public enum EnableManagedIncrementalBuild { [Default] @@ -149,13 +295,45 @@ public enum EnableManagedIncrementalBuild Disable } + /// + /// Common Language RunTime Support + /// + /// + /// Use the .NET runtime service. This switch is incompatible with some other switches; see the documentation on the /clr family of switches for details. + /// public enum CommonLanguageRuntimeSupport { + /// + /// No Common Language RunTime Support + /// [Default] NoClrSupport, + + /// + /// Common Language RunTime Support + /// + /// + /// Creates metadata for your application that can be consumed by other CLR applications, and allows your application to consume types and data in the metadata of other CLR components. + /// ClrSupport, // clr + + /// + /// Pure MSIL Common Language RunTime Support + /// + /// + /// Produces an MSIL-only output file with no native executable code, although it can contain native types compiled to MSIL. + /// PureMsilClrSupport, // clr:pure + + /// + /// Safe MSIL Common Language RunTime Support + /// + /// + /// Produces an MSIL-only (no native executable code) and verifiable output file. + /// SafeMsilClrSupport, // clr:safe + + [Obsolete("This option is not supported by msvc anymore.", true)] SafeMsilClrSupportOldSyntax // clr:oldSyntax } @@ -167,15 +345,6 @@ public enum MfcSupport UseMfcDynamic } - [Obsolete("Please use " + nameof(PreferredToolArchitecture) + " instead", true)] - public enum NativeEnvironment - { - [DevEnvVersion(minimum = DevEnv.vs2012)] - Enable, - [Default] - Disable - } - public enum PreferredToolArchitecture { [Default] @@ -229,6 +398,9 @@ public enum CopyCppRuntimeToOutputDir public static class Compiler { + /// + /// Multi-processor Compilation + /// public enum MultiProcessorCompilation { [Default] @@ -236,26 +408,83 @@ public enum MultiProcessorCompilation Disable } + /// + /// Select option for code optimization; choose Custom to use specific optimization options. + /// public enum Optimization { + /// + /// Disable optimization. + /// [Default(DefaultTarget.Debug)] Disable, + + /// + /// Maximum Optimization (Favor Size) + /// + /// + /// Equivalent to /Og /Os /Oy /Ob2 /Gs /GF /Gy + /// MinimizeSize, + + /// + /// Maximum Optimization (Favor Speed) + /// + /// + /// Equivalent to /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy + /// MaximizeSpeed, + + /// + /// Optimizations (Favor Speed) + /// + /// + /// Equivalent to /Og /Oi /Ot /Oy /Ob2 + /// [Default(DefaultTarget.Release)] FullOptimization } + /// + /// Inline Function Expansion + /// + /// + /// Select the level of inline function expansion for the build. + /// public enum Inline { Default, + + /// + /// Only __inline + /// + /// + /// Expands only functions marked as inline, __inline, __forceinline or __inline or, in a C++ member function, defined within a class declaration. + /// [Default(DefaultTarget.Debug)] OnlyInline, // set as debug default because good enough for debug builds and much faster. + + /// + /// Any Suitable + /// + /// + /// Expands functions marked as inline or __inline and any other function that the compiler chooses (expansion occurs at the compiler's discretion, often referred to as auto-inlining). + /// [Default(DefaultTarget.Release)] AnySuitable, + + /// + /// Disables inline expansion, which is on by default. + /// Disable } + /// + /// Enable Intrinsic Functions + /// + /// + /// Using intrinsic functions generates faster, but possibly larger, code. + /// public enum Intrinsic { [Default] @@ -263,15 +492,38 @@ public enum Intrinsic Disable } + /// + /// Favor Size Or Speed + /// + /// + /// Whether to favor code size or code speed; 'Global Optimization' must be turned on. + /// public enum FavorSizeOrSpeed { + /// + /// No size nor speed optimization. + /// [Default(DefaultTarget.Debug)] Neither, + + /// + /// Favor Fast Code. Maximizes the speed of EXEs and DLLs by instructing the compiler to favor speed over size. (This is the default.) + /// [Default(DefaultTarget.Release)] FastCode, + + /// + /// Favor Small Code. Minimizes the size of EXEs and DLLs by instructing the compiler to favor size over speed. + /// SmallCode } + /// + /// Omit Frame Pointers + /// + /// + /// Suppresses creation of frame pointers on the call stack. + /// public enum OmitFramePointers { [Default] @@ -279,6 +531,12 @@ public enum OmitFramePointers Enable } + /// + /// Enable Fiber-Safe Optimizations + /// + /// + /// Enables memory space optimization when using fibers and thread local storage access. + /// public enum FiberSafe { [Default] @@ -286,6 +544,12 @@ public enum FiberSafe Enable } + /// + /// Ignore Standard Include Paths + /// + /// + /// Prevents the compiler from searching for include files in directories specified in the INCLUDE environment variables. + /// public enum IgnoreStandardIncludePath { [Default] @@ -293,14 +557,28 @@ public enum IgnoreStandardIncludePath Enable } + /// + /// Preprocess to a File + /// + /// + /// Preprocesses C and C++ source files and writes the preprocessed output to a file. This option suppresses compilation, thus it does not produce an .obj file. + /// public enum GenerateProcessorFile { [Default] Disable, + WithLineNumbers, + + /// + /// Preprocess without #line directives. + /// WithoutLineNumbers } + /// + /// Suppresses comment strip from source code; requires that one of the 'Preprocessing' options be set. + /// public enum KeepComment { [Default] @@ -308,6 +586,9 @@ public enum KeepComment Enable } + /// + /// Enables the compiler to create a single read-only copy of identical strings in the program image and in memory during execution, resulting in smaller programs, an optimization called string pooling. /O1, /O2, and /ZI automatically set /GF option. + /// public enum StringPooling { Disable, @@ -315,6 +596,9 @@ public enum StringPooling Enable } + /// + /// Enables minimal rebuild, which determines whether C++ source files that include changed C++ class definitions (stored in header (.h) files) need to be recompiled. + /// public enum MinimalRebuild { [Default(DefaultTarget.Release)] @@ -323,15 +607,42 @@ public enum MinimalRebuild Enable } + /// + /// Enable C++ Exceptions + /// + /// + /// Specifies the model of exception handling to be used by the compiler. + /// public enum Exceptions { + /// + /// No exception handling. + /// [Default] Disable, + + /// + /// The exception-handling model that catches C++ exceptions only and tells the compiler to assume that extern C functions never throw a C++ exception. (/EHsc) + /// Enable, + + /// + /// The exception-handling model that catches C++ exceptions only and tells the compiler to assume that extern C functions do throw an exception. (/EHs) + /// EnableWithExternC, + + /// + /// The exception-handling model that catches asynchronous (structured) and synchronous (C++) exceptions. (/EHa) + /// EnableWithSEH } + /// + /// Smaller Type Check + /// + /// + /// Enable checking for conversion to smaller types, incompatible with any optimization type other than debug. + /// public enum TypeChecks { [Default] @@ -339,40 +650,142 @@ public enum TypeChecks Enable } + /// + /// Perform basic runtime error checks, incompatible with any optimization type other than debug. + /// public enum RuntimeChecks { [Default] Default, + + /// + /// Enables stack frame run-time error checking. + /// StackFrames, + + /// + /// Reports when a variable is used without having been initialized. + /// UninitializedVariables, + + /// + /// Both (/RTC1, equiv. to /RTCsu) + /// Both } + /// + /// Specify runtime library for linking. + /// public enum RuntimeLibrary { + /// + /// Multi-threaded + /// + /// + /// Causes your application to use the multithread, static version of the run-time library. + /// [Default(DefaultTarget.Release)] MultiThreaded, + + /// + /// Multi-threaded Debug + /// + /// + /// Defines _DEBUG and _MT. This option also causes the compiler to place the library name LIBCMTD.lib into the .obj file so that the linker will use LIBCMTD.lib to resolve external symbols. + /// [Default(DefaultTarget.Debug)] MultiThreadedDebug, + + /// + /// Multi-threaded DLL + /// + /// + /// Causes your application to use the multithread- and DLL-specific version of the run-time library. Defines _MT and _DLL and causes the compiler to place the library name MSVCRT.lib into the .obj file. + /// MultiThreadedDLL, + + /// + /// Multi-threaded Debug DLL + /// + /// + /// Defines _DEBUG, _MT, and _DLL and causes your application to use the debug multithread- and DLL-specific version of the run-time library. It also causes the compiler to place the library name MSVCRTD.lib into the .obj file. + /// MultiThreadedDebugDLL, } + /// + /// Struct Member Alignment + /// + /// + /// Specifies 1, 2, 4, or 8-byte boundaries for struct member alignment. + /// public enum StructAlignment { + /// + /// Default alignment settings. + /// [Default] Default, + + /// + /// 1 Byte + /// + /// + /// Packs structures on 1-byte boundaries. Same as /Zp. + /// Alignment1, + + /// + /// 2 Bytes + /// + /// + /// Packs structures on 2-byte boundaries. + /// Alignment2, + + /// + /// 4 Byte + /// + /// + /// Packs structures on 4-byte boundaries. + /// Alignment4, + + /// + /// 8 Bytes + /// + /// + /// Packs structures on 8-byte boundaries (default). + /// Alignment8, + + /// + /// 16 Bytes + /// + /// + /// Packs structures on 16-byte boundaries. + /// Alignment16 } + /// + /// Security Check + /// + /// + /// The Security Check helps detect stack-buffer over-runs, a common attempted attack upon a program's security. + /// public enum BufferSecurityCheck { + /// + /// Disable Security Check. (/GS-) + /// [Default(DefaultTarget.Release)] Disable, + + /// + /// Enable Security Check. (/GS) + /// [Default(DefaultTarget.Debug)] Enable, } @@ -385,6 +798,12 @@ public enum OptimizeGlobalData Enable, } + /// + /// Enable Function-Level Linking + /// + /// + /// Allows the compiler to package individual functions in the form of packaged functions (COMDATs). Required for edit and continue to work. + /// public enum FunctionLevelLinking { [Default(DefaultTarget.Debug)] @@ -393,28 +812,86 @@ public enum FunctionLevelLinking Enable, } + /// + /// Enable Enhanced Instruction Set + /// + /// + /// Enable use of instructions found on processors that support enhanced instruction sets, e.g., the SSE, SSE2, AVX, AVX2 and AVX-512 enhancements to IA-32; AVX, AVX2 and AVX-512 to x64. Currently /arch:SSE and /arch:SSE2 are only available when building for the x86 architecture. If no option is specified, the compiler will use instructions found on processors that support SSE2. Use of enhanced instructions can be disabled with /arch:IA32. (/arch:SSE, /arch:SSE2, /arch:AVX, /arch:AVX2, /arch:AVX512, /arch:IA32) + /// public enum EnhancedInstructionSet { + /// + /// Not Set + /// [Default] Disable, + + /// + /// Streaming SIMD Extensions. (/arch:SSE) + /// SIMD, + + /// + /// Streaming SIMD Extensions 2. (/arch:SSE2) + /// SIMD2, + + /// + /// Advanced Vector Extensions. (/arch:AVX) + /// [DevEnvVersion(minimum = DevEnv.vs2012)] AdvancedVectorExtensions, + + /// + /// Advanced Vector Extensions 2. (/arch:AVX2) + /// [DevEnvVersion(minimum = DevEnv.vs2013)] AdvancedVectorExtensions2, + + /// + /// Advanced Vector Extensions 512. (/arch:AVX512) + /// + [DevEnvVersion(minimum = DevEnv.vs2019)] + AdvancedVectorExtensions512, + + /// + /// No Enhanced Instructions. (/arch:IA32) + /// [DevEnvVersion(minimum = DevEnv.vs2012)] NoEnhancedInstructions, } + /// + /// Floating Point Model + /// + /// + /// Sets the floating point model. + /// public enum FloatingPointModel { + /// + /// Improves the consistency of floating-point tests for equality and inequality. + /// Precise, + + /// + /// The strictest floating-point model. /fp:strict causes fp_contract to be OFF and fenv_access to be ON. /fp:except is implied and can be disabled by explicitly specifying /fp:except-. When used with /fp:except-, /fp:strict enforces strict floating-point semantics but without respect for exceptional events. + /// Strict, + + /// + /// Creates the fastest code in the majority of cases. + /// [Default] Fast } + /// + /// Enable Floating Point Exceptions + /// + /// + /// Reliable floating-point exception model. Exceptions will be raised immediately after they are triggered. + /// public enum FloatingPointExceptions { [Default] @@ -422,6 +899,12 @@ public enum FloatingPointExceptions Enable, } + /// + /// Create Hotpatchable Image + /// + /// + /// When hotpatching is on, the compiler ensures that first instruction of each function is two bytes, which is required for hot patching. + /// public enum CreateHotPatchableCode { [Default] @@ -430,14 +913,33 @@ public enum CreateHotPatchableCode Enable, } + /// + /// Conformance mode + /// + /// + /// Enables or suppresses conformance mode. (/permissive-, /permissive). + /// public enum ConformanceMode { + /// + /// No + /// [Default] Disable, + + /// + /// Yes + /// [DevEnvVersion(minimum = DevEnv.vs2017)] Enable, } + /// + /// Disable Language Extensions + /// + /// + /// Suppresses or enables language extensions. + /// public enum DisableLanguageExtensions { [Default] @@ -452,14 +954,12 @@ public enum CharUnsigned Enable, } - [Obsolete("Use option RemoveUnreferencedCodeData instead")] - public enum RemovedUnreferencedCOMDAT - { - Disable, - [Default] - Enable, - } - + /// + /// Remove unreferenced code and data + /// + /// + /// When specified, compiler no longer generates symbol information for unreferenced code and data. + /// public enum RemoveUnreferencedCodeData { Disable, @@ -467,6 +967,12 @@ public enum RemoveUnreferencedCodeData Enable, } + /// + /// Treat WChar_t As Built in Type + /// + /// + /// When specified, the type wchar_t becomes a native type that maps to __wchar_t in the same way that short maps to __int16. /Zc:wchar_t is on by default. + /// public enum BuiltInWChartType { Disable, @@ -474,6 +980,12 @@ public enum BuiltInWChartType Enable, } + /// + /// Force Conformance in For Loop Scope + /// + /// + /// Used to implement standard C++ behavior for the for statement loops with Microsoft extensions (/Za, /Ze (Disable Language Extensions)). /Zc:forScope is on by default. + /// public enum ForceLoopScope { Disable, @@ -481,6 +993,12 @@ public enum ForceLoopScope Enable } + /// + /// Enable Run-Time Type Information + /// + /// + /// Adds code for checking C++ object types at run time (runtime type information). + /// public enum RTTI { [Default] @@ -502,14 +1020,55 @@ public enum GenerateXMLDocumentation Enable } + /// + /// Calling Convention + /// + /// + /// Select the default calling convention for your application (can be overridden by function). + /// public enum CallingConvention { + /// + /// __cdecl + /// + /// + /// Specifies the __cdecl calling convention for all functions except C++ member functions and functions marked __stdcall or __fastcall. + /// [Default] cdecl, + + /// + /// __fastcall + /// + /// + /// Specifies the __fastcall calling convention for all functions except C++ member sfunctions and functions marked __cdecl or __stdcall. All __fastcall functions must have prototypes. + /// fastcall, + + /// + /// __stdcall + /// + /// + /// Specifies the __stdcall calling convention for all functions except C++ member functions and functions marked __cdecl or __fastcall. All __stdcall functions must have prototypes. + /// stdcall, + + /// + /// __vectorcall + /// + /// + /// Specifies the __vectorcall calling convention for all functions except C++ member functions and functions marked __cdecl, __fastcall, or __stdcall. All __vectorcall functions must have prototypes. + /// + [DevEnvVersion(minimum = DevEnv.vs2013)] + vectorcall } + /// + /// Consume Windows Runtime Extension + /// + /// + /// Consume the Windows Run Time languages extensions. + /// public enum CompileAsWinRT { [Default] @@ -518,6 +1077,12 @@ public enum CompileAsWinRT Enable } + /// + /// Show Includes + /// + /// + /// Generates a list of include files with compiler output. + /// public enum ShowIncludes { [Default] @@ -554,35 +1119,78 @@ public AdditionalUsingDirectories(params string[] dirs) { } } + /// + /// C++ Language Standard + /// + /// + /// Determines the C++ language standard the compiler will enforce. It is recommended to use the latest version when possible. (/std:c++14, /std:c++17, /std:c++latest) + /// public enum CppLanguageStandard { CPP98, + [Default] CPP11, + + /// + /// ISO C++14 Standard + /// [DevEnvVersion(minimum = DevEnv.vs2015)] CPP14, + + /// + /// ISO C++17 Standard + /// [DevEnvVersion(minimum = DevEnv.vs2017)] CPP17, + GNU98, GNU11, [DevEnvVersion(minimum = DevEnv.vs2015)] GNU14, [DevEnvVersion(minimum = DevEnv.vs2017)] GNU17, + + /// + /// Preview - Features from the Latest C++ Working Draft + /// [DevEnvVersion(minimum = DevEnv.vs2015)] Latest } + /// + /// C Language Standard + /// + /// + /// Determines the C language standard the compiler will enforce. It is recommended to use the latest version when possible. + /// public enum CLanguageStandard { + /// + /// Default (Legacy MSVC) + /// [Default] Legacy, + + /// + /// ISO C11 Standard + /// [DevEnvVersion(minimum = DevEnv.vs2019)] C11, + + /// + /// ISO C17 (2018) Standard + /// [DevEnvVersion(minimum = DevEnv.vs2019)] C17 } + /// + /// Support Just My Code Debugging + /// + /// + /// Adds supporting code for enabling Just My Code debugging in this compilation unit. + /// public enum SupportJustMyCode { [Default] @@ -592,13 +1200,66 @@ public enum SupportJustMyCode No } + /// + /// Spectre Mitigation + /// + /// + /// Spectre mitigations for CVE 2017-5753. + /// public enum SpectreMitigation { [Default] Default, + + /// + /// Enable Spectre mitigation feature for CVE 2017-5753 + /// [DevEnvVersion(minimum = DevEnv.vs2017)] - Enabled, - Disabled + Spectre, + + /// + /// All Loads + /// + /// + /// Enable Spectre mitigations for all load instructions + /// + [DevEnvVersion(minimum = DevEnv.vs2017)] + SpectreLoad, + + /// + /// All Control Flow Loads + /// + /// + /// Enable Spectre mitigations for all control flow load instructions + /// + [DevEnvVersion(minimum = DevEnv.vs2017)] + SpectreLoadCF, + + /// + /// Disabled + /// + /// + /// Not Set. + /// + [DevEnvVersion(minimum = DevEnv.vs2017)] + Disabled, + + [Obsolete("Use '" + nameof(Spectre) + "' enum entry instead", error: false)] + Enabled = Spectre + } + + /// + /// Enable Address Sanitizer + /// + /// + /// Compiles and links program with AddressSanitizer. Currently available for x86 and x64 builds. + /// + public enum EnableAsan + { + [Default] + Disable, + [DevEnvVersion(minimum = DevEnv.vs2019)] + Enable } } @@ -614,6 +1275,12 @@ public enum RunCodeAnalysis public static class Librarian { + /// + /// Treat Lib Warning As Errors + /// + /// + /// Causes no output file to be generated if lib generates a warning. + /// public enum TreatLibWarningAsErrors { Enable, @@ -639,14 +1306,77 @@ public enum EmbedManifest No } + /// + /// Show Progress + /// + /// + /// Prints Linker Progress Messages + /// public enum ShowProgress { + /// + /// Not Set + /// + /// + /// No verbosity. + /// [Default] NotSet, - DisplayAllProgressMessages, - DisplaysSomeProgressMessages + + /// + /// Display all progress messages + /// + LinkVerbose, + + /// + /// For Libraries Searched + /// + /// + /// Displays progress messages indicating just the libraries searched. + /// + LinkVerboseLib, + + /// + /// About COMDAT folding during optimized linking + /// + /// + /// Displays information about COMDAT folding during optimized linking. + /// + LinkVerboseICF, + + /// + /// About data removed during optimized linking + /// + /// + /// Displays information about functions and data removed during optimized linking. + /// + LinkVerboseREF, + + /// + /// About Modules incompatible with SEH + /// + /// + /// Displays information about modoules incompatible with Safe Exception Handling. + /// + LinkVerboseSAFESEH, + + /// + /// About linker activity related to managed code + /// + /// + /// Display information about linker activity related to managed code. + /// + LinkVerboseCLR, + + [Obsolete("Use '" + nameof(LinkVerbose) + "' enum entry instead", error: false)] + DisplayAllProgressMessages = LinkVerbose, + [Obsolete("Use '" + nameof(LinkVerboseLib) + "' enum entry instead", error: false)] + DisplaysSomeProgressMessages = LinkVerboseLib } + /// + /// Enable Incremental Linking + /// public enum Incremental { Default, @@ -655,6 +1385,12 @@ public enum Incremental Enable, } + /// + /// Suppress Startup Banner + /// + /// + /// Prevents display of the copyright message and version number. + /// public enum SuppressStartupBanner { Disable, @@ -662,6 +1398,12 @@ public enum SuppressStartupBanner Enable } + /// + /// Link Library Dependencies + /// + /// + /// Specifies whether or not library outputs from project dependencies are automatically linked in. + /// public enum LinkLibraryDependencies { Default, @@ -687,6 +1429,12 @@ public enum CopyLocalSatelliteAssemblies Disable } + /// + /// Ignore Import Library + /// + /// + /// Specifies that the import library generated by this configuration should not be imported into dependent projects. + /// public enum IgnoreImportLibrary { Enable, @@ -694,6 +1442,12 @@ public enum IgnoreImportLibrary Disable } + /// + /// Use Library Dependency Inputs + /// + /// + /// Specifies whether or not the inputs to the librarian tool are used rather than the library file itself when linking in library outputs of project dependencies. + /// public enum UseLibraryDependencyInputs { [Default] @@ -702,6 +1456,12 @@ public enum UseLibraryDependencyInputs Disable } + /// + /// Ignore All Default Libraries + /// + /// + /// The /NODEFAULTLIB option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. + /// public enum IgnoreAllDefaultLibraries { Enable, @@ -723,6 +1483,12 @@ public DelayLoadDLLs(params string[] values) { } } + /// + /// Generate Manifest + /// + /// + /// Specifies that the linker should create a side-by-side manifest file. + /// public enum GenerateManifest { [Default] @@ -731,19 +1497,50 @@ public enum GenerateManifest } /// + /// Generate Debug Info + /// + /// + /// This option enables creation of debugging information for the .exe file or the DLL. + /// /// Enable will write /DEBUG, and let MS linker decide to use FastLink or Full PDBs /// If you want to force DEBUG:FULL, set both GenerateDebugInformation /// and GenerateFullProgramDatabaseFile to Enable - /// + /// public enum GenerateDebugInformation { + /// + /// Generate Debug Information + /// + /// + /// Create a complete Program Database (PDB) ideal for distribution to Microsoft Symbol Server. + /// [Default] Enable, + + /// + /// Generate Debug Information optimized for faster links + /// + /// + /// Produces a program database (PDB) ideal for edit-link-debug cycle. + /// [DevEnvVersion(minimum = DevEnv.vs2015)] EnableFastLink, + + /// + /// No + /// + /// + /// Produces no debugging information. + /// Disable, } + /// + /// Generate Full Program Database File + /// + /// + /// This option generates a full PDB from a partial PDB generated when /Debug:fastlink is specified. Full PDB allows sharing the binary and the PDB with others. + /// public enum GenerateFullProgramDatabaseFile { [Default] @@ -753,6 +1550,12 @@ public enum GenerateFullProgramDatabaseFile Enable } + /// + /// Generate Map File + /// + /// + /// The /MAP option tells the linker to create a mapfile. + /// public enum GenerateMapFile { Disable, @@ -761,6 +1564,12 @@ public enum GenerateMapFile Full } + /// + /// Map Exports + /// + /// + /// The /MAPINFO option tells the linker to include the specified information in a mapfile, which is created if you specify the /MAP option. EXPORTS tells the linker to include exported functions. + /// public enum MapExports { Enable, @@ -768,6 +1577,12 @@ public enum MapExports Disable } + /// + /// Debuggable Assembly + /// + /// + /// /ASSEMBLYDEBUG emits the DebuggableAttribute attribute with debug information tracking and disables JIT optimizations. + /// public enum AssemblyDebug { [Default] @@ -776,12 +1591,62 @@ public enum AssemblyDebug NoRuntimeTrackingAndEnableOptimizations } + /// + /// The /SUBSYSTEM option tells the operating system how to run the .exe file.The choice of subsystem affects the entry point symbol (or entry point function) that the linker will choose. + /// public enum SubSystem { + /// + /// Not Set + /// + /// + /// No subsystem set. + /// + NotSet, + + /// + /// Win32 character-mode application. Console applications are given a console by the operating system. If main or wmain is defined, CONSOLE is the default. + /// [Default] Console, - Application, - Native + + /// + /// Application does not require a console, probably because it creates its own windows for interaction with the user. If WinMain or wWinMain is defined, WINDOWS is the default. + /// + Windows, + + /// + /// Device drivers for Windows NT. If /DRIVER:WDM is specified, NATIVE is the default. + /// + Native, + + /// + /// EFI Application. + /// + EFI_Application, + + /// + /// EFI Boot Service Driver. + /// + EFI_Boot_Service_Driver, + + /// + /// EFI ROM. + /// + EFI_ROM, + + /// + /// EFI Runtime. + /// + EFI_Runtime, + + /// + /// Application that runs with the POSIX subsystem in Windows NT. + /// + POSIX, + + [Obsolete("Use '" + nameof(Windows) + "' enum entry instead", error: false)] + Application = Windows } public enum DLLDefine @@ -827,7 +1692,12 @@ public StackSize(int reserveSize, int commintSize) } } - + /// + /// Enable Large Addresses + /// + /// + /// The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. By default, /LARGEADDRESSAWARE:NO is enabled if /LARGEADDRESSAWARE is not otherwise specified on the linker line. + /// public enum LargeAddress { [Default] @@ -836,6 +1706,12 @@ public enum LargeAddress SupportLargerThan2Gb } + /// + /// Allow Isolation + /// + /// + /// Specifies behavior for manifest lookup. + /// public enum AllowIsolation { [Default] @@ -843,6 +1719,12 @@ public enum AllowIsolation Disabled } + /// + /// References + /// + /// + /// EliminateUnreferencedData (/OPT:REF) eliminates functions and/or data that are never referenced while KeepUnreferencedData (/OPT:NOREF) keeps functions and/or data that are never referenced. + /// public enum Reference { [Default(Options.DefaultTarget.Debug)] @@ -851,6 +1733,9 @@ public enum Reference EliminateUnreferencedData } + /// + /// Enable COMDAT Folding + /// public enum EnableCOMDATFolding { [Default(Options.DefaultTarget.Debug)] @@ -859,13 +1744,58 @@ public enum EnableCOMDATFolding RemoveRedundantCOMDATs } + /// + /// Link Time Code Generation + /// + /// + /// Specifies link-time code generation. + /// public enum LinkTimeCodeGeneration { + /// + /// Default LTCG setting. + /// [Default] Default, + + /// + /// Use Fast Link Time Code Generation + /// + /// + /// Use Link Time Code Generation. + /// + UseFastLinkTimeCodeGeneration, + + /// + /// Use Link Time Code Generation + /// + /// + /// Use Link Time Code Generation. + /// UseLinkTimeCodeGeneration, + + /// + /// Profile Guided Optimization - Instrument + /// + /// + /// Specifies link-time code generation. + /// ProfileGuidedOptimizationInstrument, + + /// + /// Profile Guided Optimization - Optimization + /// + /// + /// Specifies that the linker should use the profile data created after running the instrumented binary to create an optimized image. + /// ProfileGuidedOptimizationOptimize, + + /// + /// Profile Guided Optimization - Update + /// + /// + /// Allows and tracks list of input files to be added or modified from what was specified in the :PGINSTRUMENT phase. + /// ProfileGuidedOptimizationUpdate } @@ -876,6 +1806,9 @@ public class FunctionOrder public string Order; } + /// + /// Randomized Base Address + /// public enum RandomizedBaseAddress { [Default] @@ -884,6 +1817,12 @@ public enum RandomizedBaseAddress Disable } + /// + /// Fixed Base Address + /// + /// + /// Creates a program that can be loaded only at its preferred base address. + /// public enum FixedBaseAddress { [Default] @@ -892,21 +1831,78 @@ public enum FixedBaseAddress Disable } + /// + /// Create Hot Patchable Image + /// + /// + /// Prepares an image for hotpatching. + /// public enum CreateHotPatchableImage { [Default] Disable, + + /// + /// Prepares an image for hotpatching. + /// Enable, + + /// + /// X86 Image Only + /// + /// + /// Prepares an X86 image for hotpatching. + /// X86Image, + + /// + /// X64 Image Only + /// + /// + /// Prepares an X64 image for hotpatching. + /// X64Image, + + /// + /// Itanium Image Only + /// + /// + /// Prepares an Itanium image for hotpatching. + /// ItaniumImage } + /// + /// Force File Output + /// + /// + /// Tells the linker to create an .exe file or DLL even if a symbol is referenced but not defined or is multiply defined. It may create invalid exe file. + /// public enum ForceFileOutput { [Default] Default, - MultiplyDefinedSymbolOnly + + /// + /// /FORCE with no arguments implies both multiple and unresolved. + /// + Enable, + + /// + /// Multiply Defined Symbol Only + /// + /// + /// Use /FORCE:MULTIPLE to create an output file whether or not LINK finds more than one definition for a symbol. + /// + MultiplyDefinedSymbolOnly, + + /// + /// Undefined Symbol Only + /// + /// + /// Use /FORCE:UNRESOLVED to create an output file whether or not LINK finds an undefined symbol. /FORCE:UNRESOLVED is ignored if the entry point symbol is unresolved. + /// + UndefinedSymbolOnly } public class DisableSpecificWarnings : Strings @@ -930,14 +1926,40 @@ public BaseAddress(object obj) } } + /// + /// Generate Windows Metadata + /// + /// + /// Enables or disable generation of Windows Metadata. + /// public enum GenerateWindowsMetadata { [Default] Default, + + /// + /// Yes + /// + /// + /// Enable generation of Windows Metadata files. + /// Enable, + + /// + /// No + /// + /// + /// Disable the generation of Windows Metadata files. + /// Disable } + /// + /// Treat Linker Warning As Errors + /// + /// + /// Causes no output file to be generated if the linker generates a warning. + /// public enum TreatLinkerWarningAsErrors { Enable, @@ -961,10 +1983,27 @@ public enum EnableDpiAwareness public static class SourceFile { + /// + /// Precompiled Header + /// + /// + /// Create/Use Precompiled Header : Enables creation or use of a precompiled header during the build. + /// public enum PrecompiledHeader { + /// + /// Not Using Precompiled Headers + /// NotUsingPrecompiledHeaders, + + /// + /// Instructs the compiler to create a precompiled header (.pch) file that represents the state of compilation at a certain point. + /// CreatePrecompiledHeader, + + /// + /// Instructs the compiler to use an existing precompiled header (.pch) file in the current compilation. + /// UsePrecompiledHeader } } @@ -991,14 +2030,6 @@ public UndefinePreprocessorDefinitions(params string[] definitions) : base(definitions) { } } - - [Obsolete("Please use " + nameof(Project.Configuration.ResourceIncludePaths) + " instead", true)] - public class AdditionalIncludeDirectories : Strings - { - public AdditionalIncludeDirectories(params string[] dirs) - : base(dirs) - { } - } } public static class LLVM diff --git a/Sharpmake/Options.XCode.cs b/Sharpmake/Options.XCode.cs index 533870feb..997e43fe8 100644 --- a/Sharpmake/Options.XCode.cs +++ b/Sharpmake/Options.XCode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2020 Ubisoft Entertainment +// Copyright (c) 2017, 2020-2021 Ubisoft Entertainment // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -186,14 +186,6 @@ public ExternalResourceFolders(params string[] paths) { } } - [Obsolete("AssetCatalog is not used anymore.", error: true)] - public class AssetCatalog : Strings - { - public AssetCatalog(params string[] paths) - : base(paths) - { } - } - public class ExternalResourceFiles : Strings { public ExternalResourceFiles(params string[] paths) diff --git a/Sharpmake/PathUtil.cs b/Sharpmake/PathUtil.cs new file mode 100644 index 000000000..2274fc1b1 --- /dev/null +++ b/Sharpmake/PathUtil.cs @@ -0,0 +1,817 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; + +namespace Sharpmake +{ + public static partial class Util + { + public static readonly char UnixSeparator = '/'; + public static readonly char WindowsSeparator = '\\'; + private static readonly string s_unixMountPointForWindowsDrives = "/mnt/"; + + public static readonly bool UsesUnixSeparator = Path.DirectorySeparatorChar == UnixSeparator; + + public static readonly char OtherSeparator = UsesUnixSeparator ? Util.WindowsSeparator : Util.UnixSeparator; + + public static readonly char[] _pathSeparators = { Util.WindowsSeparator, Util.UnixSeparator }; + + public static void PathMakeStandard(IList paths) + { + for (int i = 0; i < paths.Count; ++i) + paths[i] = PathMakeStandard(paths[i]); + } + + public static string PathMakeStandard(string path) + { + return PathMakeStandard(path, !Util.IsRunningOnUnix()); + } + + public static string PathMakeStandard(string path, bool forceToLower) + { + // cleanup the path by replacing the other separator by the correct one for this OS + // then trim every trailing separators + var standardPath = path.Replace(OtherSeparator, Path.DirectorySeparatorChar).TrimEnd(Path.DirectorySeparatorChar); + return forceToLower ? standardPath.ToLower() : standardPath; + } + + public static string EnsureTrailingSeparator(string path) + { + // return the path passed in with only one trailing separator + return path.TrimEnd(OtherSeparator).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; + } + + public static bool PathIsSame(string path1, string path2) + { + return PathMakeStandard(path1).Equals(PathMakeStandard(path2), StringComparison.OrdinalIgnoreCase); + } + + public static List PathGetRelative(string sourceFullPath, Strings destFullPaths, bool ignoreCase = false) + { + List result = new List(destFullPaths.Count); + + foreach (string destFullPath in destFullPaths.Values) + { + result.Add(PathGetRelative(sourceFullPath, destFullPath, ignoreCase)); + } + return result; + } + + public static OrderableStrings PathGetRelative(string sourceFullPath, OrderableStrings destFullPaths, bool ignoreCase = false) + { + OrderableStrings result = new OrderableStrings(destFullPaths); + + for (int i = 0; i < result.Count; ++i) + { + result[i] = PathGetRelative(sourceFullPath, result[i], ignoreCase); + } + return result; + } + + public static OrderableStrings PathGetRelative(string sourceFullPath, IEnumerable destFullPaths, bool ignoreCase = false) + { + OrderableStrings result = new OrderableStrings(destFullPaths); + + for (int i = 0; i < result.Count; ++i) + { + result[i] = PathGetRelative(sourceFullPath, result[i], ignoreCase); + } + return result; + } + public static void PathSplitFileNameFromPath(string fileFullPath, out string fileName, out string pathName) + { + string[] fileFullPathParts = fileFullPath.Split(_pathSeparators, StringSplitOptions.RemoveEmptyEntries); + + fileName = ""; + pathName = ""; + + for (int i = 0; i < fileFullPathParts.Length; ++i) + { + if (i == fileFullPathParts.Length - 1) + { + fileName = fileFullPathParts[i]; + } + else + { + pathName += fileFullPathParts[i] + Path.DirectorySeparatorChar; + } + } + + pathName = pathName.TrimEnd(Path.DirectorySeparatorChar); + } + + public static string RegexPathCombine(params string[] parts) + { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < parts.Length; ++i) + { + stringBuilder.Append(parts[i]); + if (i != (parts.Length - 1)) + { + stringBuilder.Append(System.Text.RegularExpressions.Regex.Escape(Path.DirectorySeparatorChar.ToString())); + } + } + return stringBuilder.ToString(); + } + + public static string GetConvertedRelativePath( + string absolutePath, + string relativePath, + string newRelativeToFullPath, + bool ignoreCase, + string rootPath = null + ) + { + string tmpAbsolute = PathGetAbsolute(absolutePath, relativePath); + string newRelativePath = PathGetRelative(newRelativeToFullPath, tmpAbsolute, ignoreCase); + + if (rootPath != null) + { + string cleanPath = Util.SimplifyPath(rootPath); + if (!tmpAbsolute.StartsWith(cleanPath, StringComparison.OrdinalIgnoreCase)) + return tmpAbsolute; + } + + return newRelativePath; + } + + private sealed unsafe class PathHelper + { + public static readonly int MaxPath = 260; + private int _capacity; + + // Array of stack members. + private char* _buffer; + private int _bufferLength; + + public PathHelper(char* buffer, int length) + { + _buffer = buffer; + _capacity = length; + _bufferLength = 0; + } + + // This method is called when we find a .. in the path. + public bool RemoveLastDirectory(int lowestRemovableIndex) + { + if (Length == 0) + return false; + + Trace.Assert(_buffer[_bufferLength - 1] == Path.DirectorySeparatorChar); + + int lastSlash = -1; + + for (int i = _bufferLength - 2; i >= lowestRemovableIndex; i--) + { + if (_buffer[i] == Path.DirectorySeparatorChar) + { + lastSlash = i; + break; + } + } + + if (lastSlash == -1) + { + if (lowestRemovableIndex == 0) + { + _bufferLength = 0; + return true; + } + else + { + return false; + } + } + + // Truncate the path. + _bufferLength = lastSlash; + + return true; + } + + public void Append(char value) + { + if (Length + 1 >= _capacity) + throw new PathTooLongException("Path too long:"); + + if (value == Path.DirectorySeparatorChar) + { + // Skipping consecutive backslashes. + if (_bufferLength > 0 && _buffer[_bufferLength - 1] == Path.DirectorySeparatorChar) + return; + } + + // Important note: Must imcrement _bufferLength at the same time as writing into it as otherwise if + // you are stepping in the debugger and ToString() is implicitly called by the debugger this could truncate the string + // before the increment takes place + _buffer[_bufferLength++] = value; + } + + // Append a substring path component to the + public void Append(string str, int substStringIndex, int subStringLength) + { + if (Length + subStringLength >= _capacity) + throw new PathTooLongException("Path too long:"); + + Trace.Assert(substStringIndex < str.Length); + Trace.Assert(substStringIndex + subStringLength <= str.Length); + + + int endLoop = substStringIndex + subStringLength; + for (int i = substStringIndex; i < endLoop; ++i) + { + // Important note: Must imcrement _bufferLength at the same time as writing into it as otherwise if + // you are stepping in the debugger and ToString() is implicitly called by the debugger this could truncate the string + // before the increment takes place + char value = str[i]; + _buffer[_bufferLength++] = value; + } + } + + public void RemoveChar(int index) + { + Debug.Assert(index < _bufferLength); + for (int i = index; i < _bufferLength - 1; ++i) + { + _buffer[i] = _buffer[i + 1]; + } + --_bufferLength; + } + + public override string ToString() + { + return new string(_buffer, 0, _bufferLength); + } + + public int Length + { + get + { + return _bufferLength; + } + } + + internal char this[int index] + { + get + { + Debug.Assert(index < _bufferLength); + return _buffer[index]; + } + } + }; + + private static ConcurrentDictionary s_cachedSimplifiedPaths = new ConcurrentDictionary(); + + public static unsafe string SimplifyPath(string path) + { + if (path.Length == 0) + return string.Empty; + + if (path == ".") + return path; + + string simplifiedPath = s_cachedSimplifiedPaths.GetOrAdd(path, s => + { + // First construct a path helper to help with the conversion + char* arrayPtr = stackalloc char[PathHelper.MaxPath]; + PathHelper pathHelper = new PathHelper(arrayPtr, PathHelper.MaxPath); + + int index = 0; + int pathLength = path.Length; + int numDot = 0; + int lowestRemovableIndex = 0; + for (; index < pathLength; ++index) + { + char currentChar = path[index]; + if (currentChar == OtherSeparator) + currentChar = Path.DirectorySeparatorChar; + + if (currentChar == '.') + { + ++numDot; + if (numDot > 2) + { + throw new ArgumentException($"Invalid path format: {path}"); + } + } + else + { + if (numDot == 1) + { + if (currentChar == Path.DirectorySeparatorChar) + { + // Path starts a path of the format .\ + numDot = 0; + continue; + } + else + { + pathHelper.Append('.'); + } + numDot = 0; + pathHelper.Append(currentChar); + } + else if (numDot == 2) + { + if (currentChar != Path.DirectorySeparatorChar) + throw new ArgumentException($"Invalid path format: {path}"); + + // Path contains a path of the format ..\ + bool success = pathHelper.RemoveLastDirectory(lowestRemovableIndex); + if (!success) + { + pathHelper.Append('.'); + pathHelper.Append('.'); + lowestRemovableIndex = pathHelper.Length; + } + numDot = 0; + if (pathHelper.Length > 0) + pathHelper.Append(currentChar); + } + else + { + if (Util.IsRunningOnUnix() && + index == 0 && currentChar == Path.DirectorySeparatorChar && Path.IsPathRooted(path)) + pathHelper.Append(currentChar); + + if (currentChar != Path.DirectorySeparatorChar || pathHelper.Length > 0) + pathHelper.Append(currentChar); + } + } + } + if (numDot == 2) + { + // Path contains a path of the format \..\ + if (!pathHelper.RemoveLastDirectory(lowestRemovableIndex)) + { + pathHelper.Append('.'); + pathHelper.Append('.'); + } + } + + return pathHelper.ToString(); + }); + + return simplifiedPath; + } + + // Note: This method assumes that SimplifyPath has been called for the argument. + internal static unsafe void SplitStringUsingStack(string path, char separator, int* splitIndexes, int* splitLengths, ref int splitElementsUsedCount, int splitArraySize) + { + int lastSeparatorIndex = -1; + int pathLength = path.Length; + for (int index = 0; index < pathLength; ++index) + { + char currentChar = path[index]; + + if (currentChar == separator) + { + if (splitElementsUsedCount == splitArraySize) + throw new Exception("Too much path separators"); + + int startIndex = lastSeparatorIndex + 1; + int length = index - startIndex; + if (length > 0) + { + splitIndexes[splitElementsUsedCount] = startIndex; + splitLengths[splitElementsUsedCount] = length; + lastSeparatorIndex = index; + ++splitElementsUsedCount; + } + } + } + + if (lastSeparatorIndex < pathLength - 1) + { + int startIndex = lastSeparatorIndex + 1; + splitIndexes[splitElementsUsedCount] = startIndex; + splitLengths[splitElementsUsedCount] = pathLength - startIndex; + ++splitElementsUsedCount; + } + } + + public static unsafe string PathGetRelative(string sourceFullPath, string destFullPath, bool ignoreCase = false) + { + sourceFullPath = SimplifyPath(sourceFullPath); + destFullPath = SimplifyPath(destFullPath); + + int* sourcePathIndexes = stackalloc int[128]; + int* sourcePathLengths = stackalloc int[128]; + int sourcePathNbrElements = 0; + SplitStringUsingStack(sourceFullPath, Path.DirectorySeparatorChar, sourcePathIndexes, sourcePathLengths, ref sourcePathNbrElements, 128); + + int* destPathIndexes = stackalloc int[128]; + int* destPathLengths = stackalloc int[128]; + int destPathNbrElements = 0; + SplitStringUsingStack(destFullPath, Path.DirectorySeparatorChar, destPathIndexes, destPathLengths, ref destPathNbrElements, 128); + + int samePathCounter = 0; + + // Find out common path length. + //StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + int maxPathLength = Math.Min(sourcePathNbrElements, destPathNbrElements); + for (int i = 0; i < maxPathLength; i++) + { + int sourceLength = sourcePathLengths[i]; + if (sourceLength != destPathLengths[i]) + break; + + if (string.Compare(sourceFullPath, sourcePathIndexes[i], destFullPath, destPathIndexes[i], sourceLength, StringComparison.OrdinalIgnoreCase) != 0) + break; + + samePathCounter++; + } + + if (samePathCounter == 0) + return destFullPath; + + if (sourcePathNbrElements == destPathNbrElements && sourcePathNbrElements == samePathCounter) + return "."; + + char* arrayPtr = stackalloc char[PathHelper.MaxPath]; + PathHelper pathHelper = new PathHelper(arrayPtr, PathHelper.MaxPath); + + for (int i = samePathCounter; i < sourcePathNbrElements; i++) + { + if (pathHelper.Length > 0) + pathHelper.Append(Path.DirectorySeparatorChar); + pathHelper.Append('.'); + pathHelper.Append('.'); + } + + for (int i = samePathCounter; i < destPathNbrElements; i++) + { + if (pathHelper.Length > 0) + pathHelper.Append(Path.DirectorySeparatorChar); + pathHelper.Append(destFullPath, destPathIndexes[i], destPathLengths[i]); + } + + return pathHelper.ToString(); + } + + + public static List PathGetAbsolute(string sourceFullPath, Strings destFullPaths) + { + List result = new List(destFullPaths.Count); + + foreach (string destFullPath in destFullPaths.Values) + { + result.Add(PathGetAbsolute(sourceFullPath, destFullPath)); + } + return result; + } + + private static ConcurrentDictionary s_cachedCombinedToAbsolute = new ConcurrentDictionary(); + + public static string PathGetAbsolute(string absolutePath, string relativePath) + { + if (string.IsNullOrEmpty(relativePath)) + return absolutePath; + + // Handle environment variables and string that contains more than 1 path + if (relativePath.StartsWith("$", StringComparison.Ordinal) || relativePath.Count(x => x == ';') > 1) + return relativePath; + + string cleanRelative = SimplifyPath(relativePath); + if (Path.IsPathRooted(cleanRelative)) + return cleanRelative; + + string resultPath = s_cachedCombinedToAbsolute.GetOrAdd(string.Format("{0}|{1}", absolutePath, relativePath), combined => + { + string firstPart = PathMakeStandard(absolutePath); + if (firstPart.Last() == Path.VolumeSeparatorChar) + firstPart += Path.DirectorySeparatorChar; + + string result = Path.Combine(firstPart, cleanRelative); + return Path.GetFullPath(result); + }); + + return resultPath; + } + + public static void ResolvePath(string root, ref IEnumerable paths) + { + paths = paths.Select(path => ResolvePath(root, path)); + } + + internal static void ResolvePathAndFixCase(string root, ref IEnumerable paths) + { + paths = paths.Select(path => ResolvePathAndFixCase(root, path)); + } + + [Flags] + internal enum KeyValuePairResolveType + { + ResolveKey = 1 << 0, + ResolveValue = 1 << 1, + ResolveAll = ResolveKey | ResolveValue + } + + internal static void ResolvePathAndFixCase(string root, KeyValuePairResolveType resolveType, ref HashSet> paths) + { + if (paths.Count == 0) + return; + + foreach (var keyValuePair in paths.ToList()) + { + string key = keyValuePair.Key; + string value = keyValuePair.Value; + + if (resolveType.HasFlag(KeyValuePairResolveType.ResolveKey)) + key = ResolvePathAndFixCase(root, key); + + if (resolveType.HasFlag(KeyValuePairResolveType.ResolveValue)) + value = ResolvePathAndFixCase(root, value); + + if (keyValuePair.Key != key || keyValuePair.Value != value) + { + paths.Remove(keyValuePair); + paths.Add(new KeyValuePair(key, value)); + } + } + } + + public static void ResolvePath(string root, ref Strings paths) + { + List sortedPaths = paths.Values; + foreach (string path in sortedPaths) + { + string resolvedPath = ResolvePath(root, path); + paths.UpdateValue(path, resolvedPath); + } + } + + internal static void ResolvePathAndFixCase(string root, ref Strings paths) + { + List sortedPaths = paths.Values; + foreach (string path in sortedPaths) + { + string fixedCase = ResolvePathAndFixCase(root, path); + paths.UpdateValue(path, fixedCase); + } + } + + public static void ResolvePath(string root, ref OrderableStrings paths) + { + for (int i = 0; i < paths.Count; ++i) + { + string resolvedPath = ResolvePath(root, paths[i]); + i = paths.SetOrRemoveAtIndex(i, resolvedPath); + } + paths.Sort(); + } + + internal static void ResolvePathAndFixCase(string root, ref OrderableStrings paths) + { + for (int i = 0; i < paths.Count; ++i) + { + string fixedCase = ResolvePathAndFixCase(root, paths[i]); + i = paths.SetOrRemoveAtIndex(i, fixedCase); + } + paths.Sort(); + } + + public static void ResolvePath(string root, ref string path) + { + path = ResolvePath(root, path); + } + + internal static void ResolvePathAndFixCase(string root, ref string path) + { + path = ResolvePathAndFixCase(root, path); + } + + public static string ResolvePath(string root, string path) + { + return Util.PathGetAbsolute(root, Util.PathMakeStandard(path)); + } + + internal static string ResolvePathAndFixCase(string root, string path) + { + string resolvedPath = ResolvePath(root, path); + return GetProperFilePathCapitalization(resolvedPath); + } + + + /// + /// Gets the absolute path up to the intersection of two specified absolute paths. + /// + /// First absolute path. + /// Second absolute path. + /// Returns an absolute path up to the intersection of both specified paths. + public static string GetPathIntersection(string absPathA, string absPathB) + { + var builder = new StringBuilder(); + + string stdPathA = PathMakeStandard(absPathA); + string stdPathB = PathMakeStandard(absPathB); + + string[] pathTokensA = stdPathA.Split(Path.DirectorySeparatorChar); + string[] pathTokensB = stdPathB.Split(Path.DirectorySeparatorChar); + + int maxPossibleCommonChunks = Math.Min(pathTokensA.Length, pathTokensB.Length); + for (int i = 0; i < maxPossibleCommonChunks; ++i) + { + if (pathTokensA[i] != pathTokensB[i]) + break; + + builder.Append(pathTokensA[i] + Path.DirectorySeparatorChar); + } + + return builder.ToString(); + } + + private static string GetProperFilePathCapitalization(string filename) + { + StringBuilder builder = new StringBuilder(); + FileInfo fileInfo = new FileInfo(filename); + DirectoryInfo dirInfo = fileInfo.Directory; + GetProperDirectoryCapitalization(dirInfo, null, ref builder); + string properFileName = fileInfo.Name; + if (dirInfo != null && dirInfo.Exists) + { + foreach (var fsInfo in dirInfo.EnumerateFileSystemInfos()) + { + if (((fsInfo.Attributes & FileAttributes.Directory) != FileAttributes.Directory) + && string.Compare(fsInfo.Name, fileInfo.Name, StringComparison.OrdinalIgnoreCase) == 0) + { + properFileName = fsInfo.Name; + break; + } + } + } + return Path.Combine(builder.ToString(), properFileName); + } + + private static ConcurrentDictionary s_capitalizedPaths = new ConcurrentDictionary(); + + private static void GetProperDirectoryCapitalization(DirectoryInfo dirInfo, DirectoryInfo childInfo, ref StringBuilder pathBuilder) + { + string lowerPath = dirInfo.FullName.ToLower(); + string capitalizedPath; + if (s_capitalizedPaths.TryGetValue(lowerPath, out capitalizedPath)) + { + pathBuilder.Append(capitalizedPath); + } + else + { + if (dirInfo.Parent != null) + { + GetProperDirectoryCapitalization(dirInfo.Parent, dirInfo, ref pathBuilder); + } + else + { + // Make root drive always uppercase + pathBuilder.Append(dirInfo.Name.ToUpper()); + } + } + s_capitalizedPaths.TryAdd(lowerPath, pathBuilder.ToString()); + + if (childInfo != null) + { + // Note: Avoid double directory separator when at the root. + if (dirInfo.Parent != null) + pathBuilder.Append(Path.DirectorySeparatorChar); + bool appendChild = true; + if (dirInfo.Exists) + { + var resultDirs = dirInfo.GetDirectories(childInfo.Name, SearchOption.TopDirectoryOnly); + if (resultDirs.Length > 0) + { + pathBuilder.Append(resultDirs[0].Name); + appendChild = false; + } + else + { + foreach (var fsInfo in dirInfo.EnumerateFileSystemInfos()) + { + if (string.Compare(fsInfo.Name, childInfo.Name, StringComparison.OrdinalIgnoreCase) == 0) + { + pathBuilder.Append(fsInfo.Name); + appendChild = false; + break; + } + } + } + } + if (appendChild) + pathBuilder.Append(childInfo.Name); + } + } + + public static OrderableStrings PathGetCapitalized(OrderableStrings fullPaths) + { + OrderableStrings result = new OrderableStrings(fullPaths); + + for (int i = 0; i < result.Count; ++i) + { + result[i] = GetCapitalizedPath(result[i]); + } + return result; + } + + public static string GetCapitalizedPath(string path) + { + if (CountFakeFiles() > 0) + return path; + + // Don't touch paths starting with .. + if (path.StartsWith("..", StringComparison.Ordinal)) + return path; + string pathLC = path.ToLower(); + string capitalizedPath; + if (s_capitalizedPaths.TryGetValue(pathLC, out capitalizedPath)) + { + return capitalizedPath; + } + + if (File.Exists(path)) + { + capitalizedPath = GetProperFilePathCapitalization(path); + } + else + { + StringBuilder pathBuilder = new StringBuilder(); + DirectoryInfo dirInfo = new DirectoryInfo(path); + GetProperDirectoryCapitalization(dirInfo, null, ref pathBuilder); + + capitalizedPath = pathBuilder.ToString(); + } + s_capitalizedPaths.TryAdd(pathLC, capitalizedPath); + return capitalizedPath; + } + + /// + /// Returns path with drive letter in lower case. + /// + /// WSL mounts windows drive using lowercase letters: /mnt/c, /mnt/d... + /// + /// The path to be modified. + /// + internal static string DecapitalizeDriveLetter(string path) + { + if (path.Length < 2 || path[1] != ':') + return path; + return path.Substring(0, 1).ToLower() + path.Substring(1); + } + + internal static string ConvertToUnixSeparators(string path) + { + return path.Replace(WindowsSeparator, UnixSeparator); + } + + internal static string ConvertToMountedUnixPath(string path) + { + return s_unixMountPointForWindowsDrives + ConvertToUnixSeparators(DecapitalizeDriveLetter(EnsureTrailingSeparator(path)).Replace(@":", string.Empty)); + } + + /// + /// The input path got its beginning of path matching the inputHeadPath replaced by the replacementHeadPath. + /// + /// Throws if the fullInputPath doesn't start with inputHeadPath. + /// + /// Function is case insensitive but preserves path casing. + /// + /// The path to be modified. + /// The subpath in the head of fullInputPath to replace. + /// The subpath that will replace the inputHeadPath + /// + public static string ReplaceHeadPath(this string fullInputPath, string inputHeadPath, string replacementHeadPath) + { + // Normalize paths before comparing and combining them, to prevent false mismatch between '\\' and '/'. + fullInputPath = Util.PathMakeStandard(fullInputPath, false); + inputHeadPath = Util.PathMakeStandard(inputHeadPath, false); + replacementHeadPath = Util.PathMakeStandard(replacementHeadPath, false); + + inputHeadPath = EnsureTrailingSeparator(inputHeadPath); + + if (!fullInputPath.StartsWith(inputHeadPath, StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException($"The subpath to be replaced '{inputHeadPath}'\n is not found at the beginning of the input path '{fullInputPath}'."); + } + + var pathRelativeToOutput = fullInputPath.Substring(inputHeadPath.Length); + var modifiedPath = Path.Combine(replacementHeadPath, pathRelativeToOutput); + + return modifiedPath; + } + } +} diff --git a/Sharpmake/Project.Configuration.cs b/Sharpmake/Project.Configuration.cs index 9f457b267..1c2388ad3 100644 --- a/Sharpmake/Project.Configuration.cs +++ b/Sharpmake/Project.Configuration.cs @@ -85,50 +85,6 @@ public enum DependencySetting DefaultForceUsing = ForceUsingAssembly | IncludePaths | Defines, - - - //////////////////////////////////////////////////////////////////////// - // OLD AND DEPRECATED FLAGS - [Obsolete("Please use OnlyBuildOrder instead.", error: false)] - OnlyDependencyInSolution = -1, - - [Obsolete("Please use OnlyBuildOrder instead.", error: false)] - ForcedDependencyInSolution = -1, - - [Obsolete("Please replace by OnlyBuildOrder if that's what you wanted, otherwise remove it, it isn't needed.", error: false)] - ProjectReference = -1, - - [Obsolete("Please replace by LibraryFiles.", error: false)] - InheritLibraryFiles = -1, - - [Obsolete("Please replace by LibraryPaths.", error: false)] - InheritLibraryPaths = -1, - - [Obsolete("Please replace by IncludePaths.", error: false)] - InheritIncludePaths = -1, - - [Obsolete("Please replace by Defines.", error: false)] - InheritDefines = -1, - - [Obsolete("Please remove this.", error: false)] - InheritDependencies = -1, - - [Obsolete("Please replace by LibraryFiles if needed, sharpmake controls the dependency inheritance.", error: false)] - InheritFromDependenciesLibraryFiles = -1, - - [Obsolete("Please replace by LibraryPaths if needed, sharpmake controls the dependency inheritance.", error: false)] - InheritFromDependenciesLibraryPaths = -1, - - [Obsolete("Please replace by IncludePaths if needed, sharpmake controls the dependency inheritance.", error: false)] - InheritFromDependenciesIncludePaths = -1, - - [Obsolete("Please replace by Defines if needed, sharpmake controls the dependency inheritance.", error: false)] - InheritFromDependenciesDefines = -1, - - [Obsolete("Please replace by OnlyBuildOrder if needed, sharpmake controls the dependency inheritance.", error: false)] - InheritFromDependenciesNothing = -1, - [Obsolete("Please replace by OnlyBuildOrder if needed, sharpmake controls the dependency inheritance.", error: false)] - InheritFromDependenciesDependencies = -1, } /// @@ -436,19 +392,28 @@ public enum DeoptimizationWritableFiles public enum UACExecutionLevel { /// - /// Use the same privileges as the process that created the program. + /// UAC Execution Level: as invoker. /// + /// + /// Use the same privileges as the process that created the program. + /// asInvoker, /// - /// Use the highest privileges available to the current user. + /// UAC Execution Level: highest available. /// + /// + /// Use the highest privileges available to the current user. + /// highestAvailable, /// + /// UAC Execution Level: require administrator. + /// + /// /// Always run with administrator privileges. This will usually open a UAC dialog /// box for the user. - /// + /// requireAdministrator } @@ -2048,17 +2013,11 @@ internal void AddMasterBff(string masterBff) private readonly Strings _fastBuildMasterBffList = new Strings(); private readonly object _fastBuildMasterBffListLock = new object(); - [Obsolete("Sharpmake will determine the projects to build.")] - public bool IsMainProject = false; - /// /// Gets or sets whether FASTBuild blobs (unities) will be used in the build. /// public bool FastBuildBlobbed = true; - [Obsolete("Use FastBuildDistribution instead.")] - public bool FastBuildDisableDistribution = false; - /// /// Gets or sets whether FASTBuild tasks will be distributed on the network. /// @@ -2448,28 +2407,6 @@ public virtual void AddPublicDependency( SetDependency(projectType, target, dependencySetting); } - // These dependencies will be propagated to other dependent projects, but not across dll dependencies. - [Obsolete("Protected dependencies are deprecated, please use public/private instead.", error: false)] - public void AddProtectedDependency( - ITarget target, - DependencySetting dependencySetting = DependencySetting.Default, - [CallerFilePath] string sourceFilePath = "", - [CallerLineNumber] int sourceLineNumber = 0) - { - AddPublicDependency(target, typeof(TPROJECT), dependencySetting, sourceFilePath, sourceLineNumber); - } - - [Obsolete("Protected dependencies are deprecated, please use public/private instead.", error: false)] - public void AddProtectedDependency( - ITarget target, - Type projectType, - DependencySetting dependencySetting = DependencySetting.Default, - [CallerFilePath] string sourceFilePath = "", - [CallerLineNumber] int sourceLineNumber = 0) - { - AddPublicDependency(target, projectType, dependencySetting, sourceFilePath, sourceLineNumber); - } - // These dependencies will never be propagated to other projects that depend on us public void AddPrivateDependency( ITarget target, @@ -2500,29 +2437,11 @@ public virtual void AddPrivateDependency( SetDependency(projectType, target, dependencySetting); } - // These dependencies will only be added to solutions for build ordering - [Obsolete("Solution only dependencies are deprecated, please use Private with OnlyBuildOrder flag instead.", error: false)] - public void AddSolutionOnlyDependency( - ITarget target, - [CallerFilePath] string sourceFilePath = "", - [CallerLineNumber] int sourceLineNumber = 0) - { - AddPrivateDependency(target, typeof(TPROJECT), DependencySetting.OnlyBuildOrder, sourceFilePath, sourceLineNumber); - } - [Obsolete("Solution only dependencies are deprecated, please use Private with OnlyBuildOrder flag instead.", error: false)] - public void AddSolutionOnlyDependency( - ITarget target, - Type projectType, - [CallerFilePath] string sourceFilePath = "", - [CallerLineNumber] int sourceLineNumber = 0) - { - AddPrivateDependency(target, projectType, DependencySetting.OnlyBuildOrder, sourceFilePath, sourceLineNumber); - } - public bool HaveDependency() { return HaveDependency(typeof(TPROJECT)); } + public bool HaveDependency(Type projectType) { return UnResolvedPrivateDependencies.ContainsKey(projectType) || UnResolvedProtectedDependencies.ContainsKey(projectType) || UnResolvedPublicDependencies.ContainsKey(projectType); @@ -3151,13 +3070,6 @@ internal void SetDefaultOutputExtension() if (string.IsNullOrEmpty(OutputExtension)) OutputExtension = PlatformRegistry.Get(Platform).GetDefaultOutputExtension(Output); } - - #region Deprecated - [Obsolete("This delegate was used only by " + nameof(FastBuildFileIncludeCondition) + " which had no effect. It will be removed.")] - public delegate bool FastBuildFileIncludeConditionDelegate(Project.Configuration conf); - [Obsolete("This property could be set but was never used by Sharpmake. It will be removed.")] - public FastBuildFileIncludeConditionDelegate FastBuildFileIncludeCondition = null; - #endregion } } } diff --git a/Sharpmake/Project.cs b/Sharpmake/Project.cs index fcbb8911a..27e3600ff 100644 --- a/Sharpmake/Project.cs +++ b/Sharpmake/Project.cs @@ -1956,19 +1956,6 @@ public static string GetCapitalizedFile(string file) } #endregion - - #region Deprecated - [Obsolete("Use " + nameof(SourceFilesBlobExtensions) + ".")] - public Strings SourceFilesBlobExtension => SourceFilesBlobExtensions; - [Obsolete("Use " + nameof(ResourceFilesExtensions) + ".")] - public Strings ResourceFilesExtension => ResourceFilesExtensions; - [Obsolete("Use " + nameof(NatvisFilesExtensions) + ".")] - public Strings NatvisFilesExtension => NatvisFilesExtensions; - [Obsolete("Use " + nameof(SourceFilesExtensions) + ".")] - protected Strings SourceFilesExtension => SourceFilesExtensions; - [Obsolete("Use " + nameof(SourceFilesCompileExtensions) + ".")] - protected Strings SourceFilesCompileExtension => SourceFilesCompileExtensions; - #endregion } [Sharpmake.Generate] @@ -2224,10 +2211,6 @@ public AspNetProject(Type targetType) this.InitAspNetProject(); } - [Obsolete("Not needed anymore, InitAspNetProject() handle it")] - public void AddCommonWebExtensions() - { } - public void AddDefaultReferences(Configuration conf) { CSharpProjectExtensions.AddAspNetReferences(conf); @@ -2433,11 +2416,6 @@ internal CSharpProject(Type targetType, Type configurationType, bool isInternal) InitCSharpSpecifics(); } - [Obsolete("This method was meant to only be called internally, think again if you were calling it from your scripts.")] - public static void AddCSharpSpecificPreImportProjects(List importProjects, DevEnv devEnv) - { - } - public void AddCSharpSpecificImportProjects(List importProjects, DevEnv devEnv) { if (ProjectTypeGuids == CSharpProjectType.Vsix) @@ -2579,13 +2557,6 @@ public virtual string GetLinkFolder(string file) return "Resources"; } - - #region Deprecated - [Obsolete("Use " + nameof(NoneExtensions) + ".")] - public Strings NoneExtension => NoneExtensions; - [Obsolete("Use " + nameof(EmbeddedResourceExtensions) + ".")] - public Strings EmbeddedResourceExtension => EmbeddedResourceExtensions; - #endregion } public class PythonVirtualEnvironment diff --git a/Sharpmake/Properties/AssemblyInfo.cs b/Sharpmake/Properties/AssemblyInfo.cs index 7404398ef..8fb55336a 100644 --- a/Sharpmake/Properties/AssemblyInfo.cs +++ b/Sharpmake/Properties/AssemblyInfo.cs @@ -44,9 +44,9 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.15.1.0")] +[assembly: AssemblyVersion("0.16.0.0")] #pragma warning disable CS7035 -[assembly: AssemblyFileVersion("0.15.1.0 (LocalBuild)")] +[assembly: AssemblyFileVersion("0.16.0.0 (LocalBuild)")] #pragma warning restore [assembly: InternalsVisibleTo("Sharpmake.Application")] diff --git a/Sharpmake/Resolver.cs b/Sharpmake/Resolver.cs index bf845273d..f74dd2288 100644 --- a/Sharpmake/Resolver.cs +++ b/Sharpmake/Resolver.cs @@ -607,10 +607,10 @@ private enum PropertyModifier Lower } - private static readonly char[] _modifierNameSplitter = new [] { ':' }; + private static readonly char[] s_modifierNameSplitter = new[] { ':' }; private static string ExtractNameAndModifier(string rawInput, out PropertyModifier modifier) { - string[] chunks = rawInput.Split(_modifierNameSplitter); + string[] chunks = rawInput.Split(s_modifierNameSplitter); if (chunks.Length < 2) { @@ -639,10 +639,10 @@ private static string ApplyModifier(PropertyModifier modifier, string input) } } - private static readonly char[] _memberPathSplitter = new[] { _pathSeparator }; + private static readonly char[] s_memberPathSplitter = new[] { _pathSeparator }; private string GetMemberStringValue(string memberPath, bool throwIfNotFound) { - string[] names = memberPath.Split(_memberPathSplitter); + string[] names = memberPath.Split(s_memberPathSplitter); if (names.Length == 0) { diff --git a/Sharpmake/Sharpmake.csproj b/Sharpmake/Sharpmake.csproj index b34b1cb9c..b6110da97 100644 --- a/Sharpmake/Sharpmake.csproj +++ b/Sharpmake/Sharpmake.csproj @@ -108,6 +108,7 @@ + diff --git a/Sharpmake/Util.cs b/Sharpmake/Util.cs index 539d45493..6179c3d23 100644 --- a/Sharpmake/Util.cs +++ b/Sharpmake/Util.cs @@ -32,13 +32,6 @@ namespace Sharpmake { public static partial class Util { - public static readonly char UnixSeparator = '/'; - public static readonly char WindowsSeparator = '\\'; - - public static readonly bool UsesUnixSeparator = Path.DirectorySeparatorChar == UnixSeparator; - - public static readonly char OtherSeparator = UsesUnixSeparator ? Util.WindowsSeparator : Util.UnixSeparator; - public const string DoubleQuotes = @""""; public const string EscapedDoubleQuotes = @"\"""; @@ -71,17 +64,6 @@ public static bool FlagsTest(T value, T flags) return ((intValue & intflag) == intflag); } - public static void PathMakeStandard(IList paths) - { - for (int i = 0; i < paths.Count; ++i) - paths[i] = PathMakeStandard(paths[i]); - } - - public static string PathMakeStandard(string path) - { - return PathMakeStandard(path, !Util.IsRunningOnUnix()); - } - /// /// Finds the first occurrence of directive and returns the /// requested param value. Ex: @@ -107,726 +89,6 @@ public static string GetTextTemplateDirectiveParam(string filePath, string direc return null; } - public static string PathMakeStandard(string path, bool forceToLower) - { - // cleanup the path by replacing the other separator by the correct one for this OS - // then trim every trailing separators - var standardPath = path.Replace(OtherSeparator, Path.DirectorySeparatorChar).TrimEnd(Path.DirectorySeparatorChar); - return forceToLower ? standardPath.ToLower() : standardPath; - } - - public static string EnsureTrailingSeparator(string path) - { - // return the path passed in with only one trailing separator - return path.TrimEnd(OtherSeparator).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; - } - - public static bool PathIsSame(string path1, string path2) - { - return PathMakeStandard(path1).Equals(PathMakeStandard(path2), StringComparison.OrdinalIgnoreCase); - } - - public static List PathGetRelative(string sourceFullPath, Strings destFullPaths, bool ignoreCase = false) - { - List result = new List(destFullPaths.Count); - - foreach (string destFullPath in destFullPaths.Values) - { - result.Add(PathGetRelative(sourceFullPath, destFullPath, ignoreCase)); - } - return result; - } - - public static OrderableStrings PathGetRelative(string sourceFullPath, OrderableStrings destFullPaths, bool ignoreCase = false) - { - OrderableStrings result = new OrderableStrings(destFullPaths); - - for (int i = 0; i < result.Count; ++i) - { - result[i] = PathGetRelative(sourceFullPath, result[i], ignoreCase); - } - return result; - } - - public static OrderableStrings PathGetRelative(string sourceFullPath, IEnumerable destFullPaths, bool ignoreCase = false) - { - OrderableStrings result = new OrderableStrings(destFullPaths); - - for (int i = 0; i < result.Count; ++i) - { - result[i] = PathGetRelative(sourceFullPath, result[i], ignoreCase); - } - return result; - } - - public static readonly char[] _pathSeparators = { Util.WindowsSeparator, Util.UnixSeparator }; - internal static readonly char[] WildcardCharacters = { '*', '?' }; - - public static void PathSplitFileNameFromPath(string fileFullPath, out string fileName, out string pathName) - { - string[] fileFullPathParts = fileFullPath.Split(_pathSeparators, StringSplitOptions.RemoveEmptyEntries); - - fileName = ""; - pathName = ""; - - for (int i = 0; i < fileFullPathParts.Length; ++i) - { - if (i == fileFullPathParts.Length - 1) - { - fileName = fileFullPathParts[i]; - } - else - { - pathName += fileFullPathParts[i] + Path.DirectorySeparatorChar; - } - } - - pathName = pathName.TrimEnd(Path.DirectorySeparatorChar); - } - - public static string RegexPathCombine(params string[] parts) - { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < parts.Length; ++i) - { - stringBuilder.Append(parts[i]); - if (i != (parts.Length - 1)) - { - stringBuilder.Append(System.Text.RegularExpressions.Regex.Escape(Path.DirectorySeparatorChar.ToString())); - } - } - return stringBuilder.ToString(); - } - - public static string GetConvertedRelativePath( - string absolutePath, - string relativePath, - string newRelativeToFullPath, - bool ignoreCase, - string rootPath = null - ) - { - string tmpAbsolute = PathGetAbsolute(absolutePath, relativePath); - string newRelativePath = PathGetRelative(newRelativeToFullPath, tmpAbsolute, ignoreCase); - - if (rootPath != null) - { - string cleanPath = Util.SimplifyPath(rootPath); - if (!tmpAbsolute.StartsWith(cleanPath, StringComparison.OrdinalIgnoreCase)) - return tmpAbsolute; - } - - return newRelativePath; - } - - private sealed unsafe class PathHelper - { - public static readonly int MaxPath = 260; - private int _capacity; - - // Array of stack members. - private char* _buffer; - private int _bufferLength; - - public PathHelper(char* buffer, int length) - { - _buffer = buffer; - _capacity = length; - _bufferLength = 0; - } - - // This method is called when we find a .. in the path. - public bool RemoveLastDirectory(int lowestRemovableIndex) - { - if (Length == 0) - return false; - - Trace.Assert(_buffer[_bufferLength - 1] == Path.DirectorySeparatorChar); - - int lastSlash = -1; - - for (int i = _bufferLength - 2; i >= lowestRemovableIndex; i--) - { - if (_buffer[i] == Path.DirectorySeparatorChar) - { - lastSlash = i; - break; - } - } - - if (lastSlash == -1) - { - if (lowestRemovableIndex == 0) - { - _bufferLength = 0; - return true; - } - else - { - return false; - } - } - - // Truncate the path. - _bufferLength = lastSlash; - - return true; - } - - public void Append(char value) - { - if (Length + 1 >= _capacity) - throw new PathTooLongException("Path too long:"); - - if (value == Path.DirectorySeparatorChar) - { - // Skipping consecutive backslashes. - if (_bufferLength > 0 && _buffer[_bufferLength - 1] == Path.DirectorySeparatorChar) - return; - } - - // Important note: Must imcrement _bufferLength at the same time as writing into it as otherwise if - // you are stepping in the debugger and ToString() is implicitly called by the debugger this could truncate the string - // before the increment takes place - _buffer[_bufferLength++] = value; - } - - // Append a substring path component to the - public void Append(string str, int substStringIndex, int subStringLength) - { - if (Length + subStringLength >= _capacity) - throw new PathTooLongException("Path too long:"); - - Trace.Assert(substStringIndex < str.Length); - Trace.Assert(substStringIndex + subStringLength <= str.Length); - - - int endLoop = substStringIndex + subStringLength; - for (int i = substStringIndex; i < endLoop; ++i) - { - // Important note: Must imcrement _bufferLength at the same time as writing into it as otherwise if - // you are stepping in the debugger and ToString() is implicitly called by the debugger this could truncate the string - // before the increment takes place - char value = str[i]; - _buffer[_bufferLength++] = value; - } - } - - public void RemoveChar(int index) - { - Debug.Assert(index < _bufferLength); - for (int i = index; i < _bufferLength - 1; ++i) - { - _buffer[i] = _buffer[i + 1]; - } - --_bufferLength; - } - - public override string ToString() - { - return new string(_buffer, 0, _bufferLength); - } - - public int Length - { - get - { - return _bufferLength; - } - } - - internal char this[int index] - { - get - { - Debug.Assert(index < _bufferLength); - return _buffer[index]; - } - } - }; - - private static ConcurrentDictionary s_cachedSimplifiedPaths = new ConcurrentDictionary(); - - public static unsafe string SimplifyPath(string path) - { - if (path.Length == 0) - return string.Empty; - - if (path == ".") - return path; - - string simplifiedPath = s_cachedSimplifiedPaths.GetOrAdd(path, s => - { - // First construct a path helper to help with the conversion - char* arrayPtr = stackalloc char[PathHelper.MaxPath]; - PathHelper pathHelper = new PathHelper(arrayPtr, PathHelper.MaxPath); - - int index = 0; - int pathLength = path.Length; - int numDot = 0; - int lowestRemovableIndex = 0; - for (; index < pathLength; ++index) - { - char currentChar = path[index]; - if (currentChar == OtherSeparator) - currentChar = Path.DirectorySeparatorChar; - - if (currentChar == '.') - { - ++numDot; - if (numDot > 2) - { - throw new ArgumentException($"Invalid path format: {path}"); - } - } - else - { - if (numDot == 1) - { - if (currentChar == Path.DirectorySeparatorChar) - { - // Path starts a path of the format .\ - numDot = 0; - continue; - } - else - { - pathHelper.Append('.'); - } - numDot = 0; - pathHelper.Append(currentChar); - } - else if (numDot == 2) - { - if (currentChar != Path.DirectorySeparatorChar) - throw new ArgumentException($"Invalid path format: {path}"); - - // Path contains a path of the format ..\ - bool success = pathHelper.RemoveLastDirectory(lowestRemovableIndex); - if (!success) - { - pathHelper.Append('.'); - pathHelper.Append('.'); - lowestRemovableIndex = pathHelper.Length; - } - numDot = 0; - if (pathHelper.Length > 0) - pathHelper.Append(currentChar); - } - else - { - if (Util.IsRunningOnUnix() && - index == 0 && currentChar == Path.DirectorySeparatorChar && Path.IsPathRooted(path)) - pathHelper.Append(currentChar); - - if (currentChar != Path.DirectorySeparatorChar || pathHelper.Length > 0) - pathHelper.Append(currentChar); - } - } - } - if (numDot == 2) - { - // Path contains a path of the format \..\ - if (!pathHelper.RemoveLastDirectory(lowestRemovableIndex)) - { - pathHelper.Append('.'); - pathHelper.Append('.'); - } - } - - return pathHelper.ToString(); - }); - - return simplifiedPath; - } - - - // Note: This method assumes that SimplifyPath has been called for the argument. - internal static unsafe void SplitStringUsingStack(string path, char separator, int* splitIndexes, int* splitLengths, ref int splitElementsUsedCount, int splitArraySize) - { - int lastSeparatorIndex = -1; - int pathLength = path.Length; - for (int index = 0; index < pathLength; ++index) - { - char currentChar = path[index]; - - if (currentChar == separator) - { - if (splitElementsUsedCount == splitArraySize) - throw new Exception("Too much path separators"); - - int startIndex = lastSeparatorIndex + 1; - int length = index - startIndex; - if (length > 0) - { - splitIndexes[splitElementsUsedCount] = startIndex; - splitLengths[splitElementsUsedCount] = length; - lastSeparatorIndex = index; - ++splitElementsUsedCount; - } - } - } - - if (lastSeparatorIndex < pathLength - 1) - { - int startIndex = lastSeparatorIndex + 1; - splitIndexes[splitElementsUsedCount] = startIndex; - splitLengths[splitElementsUsedCount] = pathLength - startIndex; - ++splitElementsUsedCount; - } - } - - public static unsafe string PathGetRelative(string sourceFullPath, string destFullPath, bool ignoreCase = false) - { - sourceFullPath = SimplifyPath(sourceFullPath); - destFullPath = SimplifyPath(destFullPath); - - int* sourcePathIndexes = stackalloc int[128]; - int* sourcePathLengths = stackalloc int[128]; - int sourcePathNbrElements = 0; - SplitStringUsingStack(sourceFullPath, Path.DirectorySeparatorChar, sourcePathIndexes, sourcePathLengths, ref sourcePathNbrElements, 128); - - int* destPathIndexes = stackalloc int[128]; - int* destPathLengths = stackalloc int[128]; - int destPathNbrElements = 0; - SplitStringUsingStack(destFullPath, Path.DirectorySeparatorChar, destPathIndexes, destPathLengths, ref destPathNbrElements, 128); - - int samePathCounter = 0; - - // Find out common path length. - //StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - int maxPathLength = Math.Min(sourcePathNbrElements, destPathNbrElements); - for (int i = 0; i < maxPathLength; i++) - { - int sourceLength = sourcePathLengths[i]; - if (sourceLength != destPathLengths[i]) - break; - - if (string.Compare(sourceFullPath, sourcePathIndexes[i], destFullPath, destPathIndexes[i], sourceLength, StringComparison.OrdinalIgnoreCase) != 0) - break; - - samePathCounter++; - } - - if (samePathCounter == 0) - return destFullPath; - - if (sourcePathNbrElements == destPathNbrElements && sourcePathNbrElements == samePathCounter) - return "."; - - char* arrayPtr = stackalloc char[PathHelper.MaxPath]; - PathHelper pathHelper = new PathHelper(arrayPtr, PathHelper.MaxPath); - - for (int i = samePathCounter; i < sourcePathNbrElements; i++) - { - if (pathHelper.Length > 0) - pathHelper.Append(Path.DirectorySeparatorChar); - pathHelper.Append('.'); - pathHelper.Append('.'); - } - - for (int i = samePathCounter; i < destPathNbrElements; i++) - { - if (pathHelper.Length > 0) - pathHelper.Append(Path.DirectorySeparatorChar); - pathHelper.Append(destFullPath, destPathIndexes[i], destPathLengths[i]); - } - - return pathHelper.ToString(); - } - - - public static List PathGetAbsolute(string sourceFullPath, Strings destFullPaths) - { - List result = new List(destFullPaths.Count); - - foreach (string destFullPath in destFullPaths.Values) - { - result.Add(PathGetAbsolute(sourceFullPath, destFullPath)); - } - return result; - } - - private static ConcurrentDictionary s_cachedCombinedToAbsolute = new ConcurrentDictionary(); - - public static string PathGetAbsolute(string absolutePath, string relativePath) - { - if (string.IsNullOrEmpty(relativePath)) - return absolutePath; - - // Handle environment variables and string that contains more than 1 path - if (relativePath.StartsWith("$", StringComparison.Ordinal) || relativePath.Count(x => x == ';') > 1) - return relativePath; - - string cleanRelative = SimplifyPath(relativePath); - if (Path.IsPathRooted(cleanRelative)) - return cleanRelative; - - string resultPath = s_cachedCombinedToAbsolute.GetOrAdd(string.Format("{0}|{1}", absolutePath, relativePath), combined => - { - string firstPart = PathMakeStandard(absolutePath); - if (firstPart.Last() == Path.VolumeSeparatorChar) - firstPart += Path.DirectorySeparatorChar; - - string result = Path.Combine(firstPart, cleanRelative); - return Path.GetFullPath(result); - }); - - return resultPath; - } - - public static void ResolvePath(string root, ref IEnumerable paths) - { - paths = paths.Select(path => ResolvePath(root, path)); - } - - internal static void ResolvePathAndFixCase(string root, ref IEnumerable paths) - { - paths = paths.Select(path => ResolvePathAndFixCase(root, path)); - } - - [Flags] - internal enum KeyValuePairResolveType - { - ResolveKey = 1 << 0, - ResolveValue = 1 << 1, - ResolveAll = ResolveKey | ResolveValue - } - - internal static void ResolvePathAndFixCase(string root, KeyValuePairResolveType resolveType, ref HashSet> paths) - { - if (paths.Count == 0) - return; - - foreach (var keyValuePair in paths.ToList()) - { - string key = keyValuePair.Key; - string value = keyValuePair.Value; - - if (resolveType.HasFlag(KeyValuePairResolveType.ResolveKey)) - key = ResolvePathAndFixCase(root, key); - - if (resolveType.HasFlag(KeyValuePairResolveType.ResolveValue)) - value = ResolvePathAndFixCase(root, value); - - if (keyValuePair.Key != key || keyValuePair.Value != value) - { - paths.Remove(keyValuePair); - paths.Add(new KeyValuePair(key, value)); - } - } - } - - public static void ResolvePath(string root, ref Strings paths) - { - List sortedPaths = paths.Values; - foreach (string path in sortedPaths) - { - string resolvedPath = ResolvePath(root, path); - paths.UpdateValue(path, resolvedPath); - } - } - - internal static void ResolvePathAndFixCase(string root, ref Strings paths) - { - List sortedPaths = paths.Values; - foreach (string path in sortedPaths) - { - string fixedCase = ResolvePathAndFixCase(root, path); - paths.UpdateValue(path, fixedCase); - } - } - - public static void ResolvePath(string root, ref OrderableStrings paths) - { - for (int i = 0; i < paths.Count; ++i) - { - string resolvedPath = ResolvePath(root, paths[i]); - i = paths.SetOrRemoveAtIndex(i, resolvedPath); - } - paths.Sort(); - } - - internal static void ResolvePathAndFixCase(string root, ref OrderableStrings paths) - { - for (int i = 0; i < paths.Count; ++i) - { - string fixedCase = ResolvePathAndFixCase(root, paths[i]); - i = paths.SetOrRemoveAtIndex(i, fixedCase); - } - paths.Sort(); - } - - public static void ResolvePath(string root, ref string path) - { - path = ResolvePath(root, path); - } - - internal static void ResolvePathAndFixCase(string root, ref string path) - { - path = ResolvePathAndFixCase(root, path); - } - - public static string ResolvePath(string root, string path) - { - return Util.PathGetAbsolute(root, Util.PathMakeStandard(path)); - } - - internal static string ResolvePathAndFixCase(string root, string path) - { - string resolvedPath = ResolvePath(root, path); - return GetProperFilePathCapitalization(resolvedPath); - } - - - /// - /// Gets the absolute path up to the intersection of two specified absolute paths. - /// - /// First absolute path. - /// Second absolute path. - /// Returns an absolute path up to the intersection of both specified paths. - public static string GetPathIntersection(string absPathA, string absPathB) - { - var builder = new StringBuilder(); - - string stdPathA = PathMakeStandard(absPathA); - string stdPathB = PathMakeStandard(absPathB); - - string[] pathTokensA = stdPathA.Split(Path.DirectorySeparatorChar); - string[] pathTokensB = stdPathB.Split(Path.DirectorySeparatorChar); - - int maxPossibleCommonChunks = Math.Min(pathTokensA.Length, pathTokensB.Length); - for (int i = 0; i < maxPossibleCommonChunks; ++i) - { - if (pathTokensA[i] != pathTokensB[i]) - break; - - builder.Append(pathTokensA[i] + Path.DirectorySeparatorChar); - } - - return builder.ToString(); - } - - private static string GetProperFilePathCapitalization(string filename) - { - StringBuilder builder = new StringBuilder(); - FileInfo fileInfo = new FileInfo(filename); - DirectoryInfo dirInfo = fileInfo.Directory; - GetProperDirectoryCapitalization(dirInfo, null, ref builder); - string properFileName = fileInfo.Name; - if (dirInfo != null && dirInfo.Exists) - { - foreach (var fsInfo in dirInfo.EnumerateFileSystemInfos()) - { - if (((fsInfo.Attributes & FileAttributes.Directory) != FileAttributes.Directory) - && string.Compare(fsInfo.Name, fileInfo.Name, StringComparison.OrdinalIgnoreCase) == 0) - { - properFileName = fsInfo.Name; - break; - } - } - } - return Path.Combine(builder.ToString(), properFileName); - } - - private static ConcurrentDictionary s_capitalizedPaths = new ConcurrentDictionary(); - - private static void GetProperDirectoryCapitalization(DirectoryInfo dirInfo, DirectoryInfo childInfo, ref StringBuilder pathBuilder) - { - string lowerPath = dirInfo.FullName.ToLower(); - string capitalizedPath; - if (s_capitalizedPaths.TryGetValue(lowerPath, out capitalizedPath)) - { - pathBuilder.Append(capitalizedPath); - } - else - { - if (dirInfo.Parent != null) - { - GetProperDirectoryCapitalization(dirInfo.Parent, dirInfo, ref pathBuilder); - } - else - { - // Make root drive always uppercase - pathBuilder.Append(dirInfo.Name.ToUpper()); - } - } - s_capitalizedPaths.TryAdd(lowerPath, pathBuilder.ToString()); - - if (childInfo != null) - { - // Note: Avoid double directory separator when at the root. - if (dirInfo.Parent != null) - pathBuilder.Append(Path.DirectorySeparatorChar); - bool appendChild = true; - if (dirInfo.Exists) - { - var resultDirs = dirInfo.GetDirectories(childInfo.Name, SearchOption.TopDirectoryOnly); - if (resultDirs.Length > 0) - { - pathBuilder.Append(resultDirs[0].Name); - appendChild = false; - } - else - { - foreach (var fsInfo in dirInfo.EnumerateFileSystemInfos()) - { - if (string.Compare(fsInfo.Name, childInfo.Name, StringComparison.OrdinalIgnoreCase) == 0) - { - pathBuilder.Append(fsInfo.Name); - appendChild = false; - break; - } - } - } - } - if (appendChild) - pathBuilder.Append(childInfo.Name); - } - } - - public static OrderableStrings PathGetCapitalized(OrderableStrings fullPaths) - { - OrderableStrings result = new OrderableStrings(fullPaths); - - for (int i = 0; i < result.Count; ++i) - { - result[i] = GetCapitalizedPath(result[i]); - } - return result; - } - - public static string GetCapitalizedPath(string path) - { - if (CountFakeFiles() > 0) - return path; - - // Don't touch paths starting with .. - if (path.StartsWith("..", StringComparison.Ordinal)) - return path; - string pathLC = path.ToLower(); - string capitalizedPath; - if (s_capitalizedPaths.TryGetValue(pathLC, out capitalizedPath)) - { - return capitalizedPath; - } - - if (File.Exists(path)) - { - capitalizedPath = GetProperFilePathCapitalization(path); - } - else - { - StringBuilder pathBuilder = new StringBuilder(); - DirectoryInfo dirInfo = new DirectoryInfo(path); - GetProperDirectoryCapitalization(dirInfo, null, ref pathBuilder); - - capitalizedPath = pathBuilder.ToString(); - } - s_capitalizedPaths.TryAdd(pathLC, capitalizedPath); - return capitalizedPath; - } - private static bool AreStreamsEqual(Stream stream1, Stream stream2) { const int BufferSize = 4096; @@ -997,7 +259,7 @@ private static Dictionary ReadCleanupDatabase(string databaseF readStream.Close(); } } - catch (SerializationException) + catch { // File is likely corrupted. // This is no big deal except that cleanup won't occur. @@ -1427,6 +689,7 @@ private static int SequenceCompare(IEnumerable source1, IEnumerable source2) } } } + public static string JoinStrings(ICollection container, string separator, bool escapeXml = false) { return JoinStrings(container, separator, "", "", escapeXml); @@ -2253,12 +1516,6 @@ public static string GetPlatformString(Platform platform, Project project, ITarg return PlatformRegistry.Query(platform)?.GetPlatformString(target) ?? platform.ToString(); } - [Obsolete("GetPlatformString() now requires a `target` parameter.")] - public static string GetPlatformString(Platform platform, Project project, bool isForSolution = false) - { - return GetPlatformString(platform, project, null, isForSolution); - } - public static string CallerInfoTag = "CALLER_INFO: "; public static string FormatCallerInfo(string sourceFilePath, int sourceLineNumber) { @@ -2323,37 +1580,6 @@ public static MemoryStream RemoveLineTags(MemoryStream inputMemoryStream, string return cleanMemoryStream; } - /// - /// The input path got its beginning of path matching the inputHeadPath replaced by the replacementHeadPath. - /// - /// Throws if the fullInputPath doesn't start with inputHeadPath. - /// - /// Function is case insensitive but preserves path casing. - /// - /// The path to be modified. - /// The subpath in the head of fullInputPath to replace. - /// The subpath that will replace the inputHeadPath - /// - public static string ReplaceHeadPath(this string fullInputPath, string inputHeadPath, string replacementHeadPath) - { - // Normalize paths before comparing and combining them, to prevent false mismatch between '\\' and '/'. - fullInputPath = Util.PathMakeStandard(fullInputPath, false); - inputHeadPath = Util.PathMakeStandard(inputHeadPath, false); - replacementHeadPath = Util.PathMakeStandard(replacementHeadPath, false); - - inputHeadPath = EnsureTrailingSeparator(inputHeadPath); - - if (!fullInputPath.StartsWith(inputHeadPath, StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException($"The subpath to be replaced '{inputHeadPath}'\n is not found at the beginning of the input path '{fullInputPath}'."); - } - - var pathRelativeToOutput = fullInputPath.Substring(inputHeadPath.Length); - var modifiedPath = Path.Combine(replacementHeadPath, pathRelativeToOutput); - - return modifiedPath; - } - public static uint Rotl32(uint x, int r) { return (x << r) | (x >> (32 - r)); diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 07fd3d30e..171695803 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -247,7 +247,10 @@ namespace HelloWorld conf.SolutionPath = @"[solution.SharpmakeCsPath]\generated"; conf.AddProject(target); } - + } + + public static class Main + { [Sharpmake.Main] public static void SharpmakeMain(Sharpmake.Arguments arguments) { @@ -1487,7 +1490,10 @@ namespace CSharpHelloWorld conf.AddProject(target); } - + } + + public static class Main + { [Sharpmake.Main] public static void SharpmakeMain(Sharpmake.Arguments arguments) { diff --git a/functional_test.py b/functional_test.py index 0d8062873..51a3d9b93 100644 --- a/functional_test.py +++ b/functional_test.py @@ -13,10 +13,11 @@ class FunctionalTest(object): - def __init__(self, directory, script_name, project_root = ""): + def __init__(self, directory, script_name, extra_args = [], project_root = ""): self.directory = directory self.script_name = script_name self.runs_on_unix = os.name == "posix" + self.extra_args = extra_args if project_root == "": self.project_root = directory else: @@ -41,6 +42,7 @@ def run_test(self): sources, verbose ] + args.extend(self.extra_args) cmd_line = "{} \"{}\"".format(sharpmake_path, " ".join(args)) if self.runs_on_unix: @@ -120,10 +122,18 @@ def __init__(self): def build(self, projectDir): return build_with_fastbuild(projectDir, self.directory) +class SharpmakePackageFunctionalTest(FunctionalTest): + def __init__(self): + super(SharpmakePackageFunctionalTest, self).__init__("SharpmakePackageFunctionalTest", "SharpmakePackageFunctionalTest.sharpmake.cs", ["/generateDebugSolution"]) + + def build(self, projectDir): + return 0 + funcTests = [ FastBuildFunctionalTest(), - NoAllFastBuildProjectFunctionalTest() + NoAllFastBuildProjectFunctionalTest(), + SharpmakePackageFunctionalTest() ] diff --git a/samples/HelloClangCl/HelloClangCl.CommonProject.sharpmake.cs b/samples/HelloClangCl/HelloClangCl.CommonProject.sharpmake.cs new file mode 100644 index 000000000..6783cd65e --- /dev/null +++ b/samples/HelloClangCl/HelloClangCl.CommonProject.sharpmake.cs @@ -0,0 +1,171 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.IO; +using System.Linq; +using Sharpmake; + +namespace HelloClangCl +{ + public static class ConfigurePriorities + { + public const int All = -75; + public const int Platform = -50; + public const int Optimization = -25; + /* SHARPMAKE DEFAULT IS 0 */ + public const int Blobbing = 25; + public const int BuildSystem = 50; + public const int Compiler = 75; + } + + public abstract class CommonProject : Sharpmake.Project + { + protected CommonProject() + : base(typeof(CommonTarget)) + { + RootPath = Globals.RootDirectory; + IsFileNameToLower = false; + IsTargetFileNameToLower = false; + + SourceRootPath = @"[project.RootPath]\[project.Name]"; + } + + [ConfigurePriority(ConfigurePriorities.All)] + [Configure] + public virtual void ConfigureAll(Configuration conf, CommonTarget target) + { + conf.ProjectFileName = "[project.Name]_[target.Platform]"; + if (target.DevEnv != DevEnv.xcode4ios) + conf.ProjectFileName += "_[target.DevEnv]"; + conf.ProjectPath = Path.Combine(Globals.TmpDirectory, @"projects\[project.Name]"); + conf.IsFastBuild = target.BuildSystem == BuildSystem.FastBuild; + + conf.IntermediatePath = Path.Combine(Globals.TmpDirectory, @"obj\[target.DirectoryName]\[project.Name]"); + conf.TargetPath = Path.Combine(Globals.OutputDirectory, "[target.DirectoryName]"); + + // Note: uncomment the following line if we port this sample to windows + //conf.TargetLibraryPath = conf.IntermediatePath; // .lib files must be with the .obj files when running in fastbuild distributed mode or we'll have missing symbols due to merging of the .pdb + conf.TargetLibraryPath = Path.Combine(Globals.TmpDirectory, @"lib\[target.DirectoryName]\[project.Name]"); + + conf.TargetFileName += "_" + target.Optimization.ToString().ToLowerInvariant().First(); // suffix with lowered first letter of optim + if (conf.IsFastBuild) + conf.TargetFileName += "x"; + + conf.Output = Configuration.OutputType.Lib; // defaults to creating static libs + } + + //////////////////////////////////////////////////////////////////////// + #region Platfoms + [ConfigurePriority(ConfigurePriorities.Platform)] + [Configure(Platform.win64)] + public virtual void ConfigureWin64(Configuration conf, CommonTarget target) + { + conf.Defines.Add("_HAS_EXCEPTIONS=0"); + } + #endregion + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + #region Optimizations + [ConfigurePriority(ConfigurePriorities.Optimization)] + [Configure(Optimization.Debug)] + public virtual void ConfigureDebug(Configuration conf, CommonTarget target) + { + conf.DefaultOption = Options.DefaultTarget.Debug; + } + + [ConfigurePriority(ConfigurePriorities.Optimization)] + [Configure(Optimization.Release)] + public virtual void ConfigureRelease(Configuration conf, CommonTarget target) + { + conf.DefaultOption = Options.DefaultTarget.Release; + } + #endregion + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + #region Blobs and unitys + [Configure(Blob.FastBuildUnitys)] + [ConfigurePriority(ConfigurePriorities.Blobbing)] + public virtual void FastBuildUnitys(Configuration conf, CommonTarget target) + { + conf.FastBuildBlobbed = true; + conf.FastBuildUnityPath = Path.Combine(Globals.TmpDirectory, @"unity\[project.Name]"); + conf.IncludeBlobbedSourceFiles = false; + conf.IsBlobbed = false; + } + + [Configure(Blob.NoBlob)] + [ConfigurePriority(ConfigurePriorities.Blobbing)] + public virtual void BlobNoBlob(Configuration conf, CommonTarget target) + { + conf.FastBuildBlobbed = false; + conf.IsBlobbed = false; + + if (conf.IsFastBuild) + conf.ProjectName += "_NoBlob"; + } + #endregion + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + #region Build system + [ConfigurePriority(ConfigurePriorities.BuildSystem)] + [Configure(BuildSystem.FastBuild)] + public virtual void ConfigureFastBuild(Configuration conf, CommonTarget target) + { + conf.SolutionFolder = "FastBuild/" + conf.SolutionFolder; + conf.ProjectName += "_FastBuild"; + conf.ProjectFileName += "_FastBuild"; + + conf.Defines.Add("USES_FASTBUILD"); + + // Force writing to pdb from different cl.exe process to go through the pdb server + if (target.Compiler == Compiler.MSVC) + conf.AdditionalCompilerOptions.Add("/FS"); + } + #endregion + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + #region Compilers and toolchains + [ConfigurePriority(ConfigurePriorities.Compiler)] + [Configure(Compiler.MSVC)] + public virtual void ConfigureMSVC(Configuration conf, CommonTarget target) + { + // no need to specify the PlatformToolset here since we want the default + + conf.Options.Add(Options.Vc.General.WarningLevel.EnableAllWarnings); + conf.Options.Add(Options.Vc.General.TreatWarningsAsErrors.Enable); + } + + [ConfigurePriority(ConfigurePriorities.Compiler)] + [Configure(Compiler.ClangCl)] + public virtual void ConfigureClangCl(Configuration conf, CommonTarget target) + { + conf.Options.Add(Options.Vc.General.PlatformToolset.ClangCL); + + conf.Options.Add(Options.Vc.General.WarningLevel.EnableAllWarnings); + conf.Options.Add(Options.Vc.General.TreatWarningsAsErrors.Enable); + + conf.AdditionalCompilerOptions.Add( + "-Wno-#pragma-messages", + "-Wno-c++98-compat", + "-Wno-microsoft-include" + ); + } + #endregion + //////////////////////////////////////////////////////////////////////// + } +} diff --git a/samples/HelloClangCl/HelloClangCl.CommonSolution.sharpmake.cs b/samples/HelloClangCl/HelloClangCl.CommonSolution.sharpmake.cs new file mode 100644 index 000000000..f97407b06 --- /dev/null +++ b/samples/HelloClangCl/HelloClangCl.CommonSolution.sharpmake.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Sharpmake; + +namespace HelloClangCl +{ + public class CommonSolution : Sharpmake.Solution + { + public CommonSolution() + : base(typeof(CommonTarget)) + { + IsFileNameToLower = false; + } + + [ConfigurePriority(ConfigurePriorities.All)] + [Configure] + public virtual void ConfigureAll(Configuration conf, CommonTarget target) + { + conf.SolutionFileName = "[solution.Name]_[target.Platform]"; + if (target.DevEnv != DevEnv.xcode4ios) + conf.SolutionFileName += "_[target.DevEnv]"; + conf.PlatformName = "[target.SolutionPlatformName]"; + conf.SolutionPath = System.IO.Path.Combine(Globals.TmpDirectory, "solutions"); + } + } +} diff --git a/samples/HelloClangCl/HelloClangCl.CommonTarget.sharpmake.cs b/samples/HelloClangCl/HelloClangCl.CommonTarget.sharpmake.cs new file mode 100644 index 000000000..56140ceea --- /dev/null +++ b/samples/HelloClangCl/HelloClangCl.CommonTarget.sharpmake.cs @@ -0,0 +1,158 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Sharpmake; + +namespace HelloClangCl +{ + [Fragment, Flags] + public enum Optimization + { + Debug = 1 << 0, + Release = 1 << 1 + } + + [Fragment, Flags] + public enum Compiler + { + MSVC = 1 << 0, + ClangCl = 1 << 1 + } + + [DebuggerDisplay("\"{Platform}_{DevEnv}\" {Name}")] + public class CommonTarget : Sharpmake.ITarget + { + public Platform Platform; + public Compiler Compiler; + public DevEnv DevEnv; + public Optimization Optimization; + public Blob Blob; + public BuildSystem BuildSystem; + + public CommonTarget() { } + + public CommonTarget( + Platform platform, + Compiler compiler, + DevEnv devEnv, + Optimization optimization, + Blob blob, + BuildSystem buildSystem + ) + { + Platform = platform; + Compiler = compiler; + DevEnv = devEnv; + Optimization = optimization; + Blob = blob; + BuildSystem = buildSystem; + } + + public override string Name + { + get + { + var nameParts = new List + { + Compiler.ToString(), + Optimization.ToString() + }; + return string.Join(" ", nameParts); + } + } + + public string SolutionPlatformName + { + get + { + var nameParts = new List(); + + nameParts.Add(BuildSystem.ToString()); + + if (BuildSystem == BuildSystem.FastBuild && Blob == Blob.NoBlob) + nameParts.Add(Blob.ToString()); + + return string.Join("_", nameParts); + } + } + + /// + /// returns a string usable as a directory name, to use for instance for the intermediate path + /// + public string DirectoryName + { + get + { + var dirNameParts = new List(); + + dirNameParts.Add(Platform.ToString()); + dirNameParts.Add(Compiler.ToString()); + dirNameParts.Add(Optimization.ToString()); + + if (BuildSystem == BuildSystem.FastBuild) + dirNameParts.Add(BuildSystem.ToString()); + + return string.Join("_", dirNameParts); + } + } + + public override Sharpmake.Optimization GetOptimization() + { + switch (Optimization) + { + case Optimization.Debug: + return Sharpmake.Optimization.Debug; + case Optimization.Release: + return Sharpmake.Optimization.Release; + default: + throw new NotSupportedException("Optimization value " + Optimization.ToString()); + } + } + + public override Platform GetPlatform() + { + return Platform; + } + + public static CommonTarget[] GetDefaultTargets() + { + var result = new List(); + result.AddRange(GetWin64Targets()); + return result.ToArray(); + } + + public static CommonTarget[] GetWin64Targets() + { + var defaultTarget = new CommonTarget( + Platform.win64, + Compiler.MSVC | Compiler.ClangCl, + DevEnv.vs2019, + Optimization.Debug | Optimization.Release, + Blob.NoBlob, + BuildSystem.MSBuild + ); + + // make a fastbuild version of the target + var fastBuildTarget = (CommonTarget)defaultTarget.Clone( + Blob.FastBuildUnitys, + BuildSystem.FastBuild + ); + + return new[] { defaultTarget, fastBuildTarget }; + } + } +} diff --git a/samples/HelloClangCl/HelloClangCl.Main.sharpmake.cs b/samples/HelloClangCl/HelloClangCl.Main.sharpmake.cs new file mode 100644 index 000000000..30ef83a56 --- /dev/null +++ b/samples/HelloClangCl/HelloClangCl.Main.sharpmake.cs @@ -0,0 +1,97 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Sharpmake; +using Sharpmake.Generators.FastBuild; + +[module: Sharpmake.DebugProjectName("Sharpmake.HelloClangCl")] + +[module: Sharpmake.Include("HelloClangCl.*.sharpmake.cs")] +[module: Sharpmake.Include("codebase/*.sharpmake.cs")] +[module: Sharpmake.Include("codebase/*/*.sharpmake.cs")] + +namespace HelloClangCl +{ + public static class Globals + { + // branch root path relative to current sharpmake file location + public const string RelativeRootPath = @".\codebase"; + public static string RootDirectory; + public static string TmpDirectory { get { return Path.Combine(RootDirectory, "temp"); } } + public static string OutputDirectory { get { return Path.Combine(TmpDirectory, "bin"); } } + } + + public static class Main + { + private static void ConfigureRootDirectory() + { + FileInfo fileInfo = Util.GetCurrentSharpmakeFileInfo(); + string rootDirectory = Path.Combine(fileInfo.DirectoryName, Globals.RelativeRootPath); + Globals.RootDirectory = Util.SimplifyPath(rootDirectory); + } + + private static void ConfigureAutoCleanup() + { + Util.FilesAutoCleanupActive = true; + Util.FilesAutoCleanupDBPath = Path.Combine(Globals.TmpDirectory, "sharpmake"); + + if (!Directory.Exists(Util.FilesAutoCleanupDBPath)) + Directory.CreateDirectory(Util.FilesAutoCleanupDBPath); + } + + [Sharpmake.Main] + public static void SharpmakeMain(Sharpmake.Arguments arguments) + { + ConfigureRootDirectory(); + ConfigureAutoCleanup(); + + FastBuildSettings.FastBuildWait = true; + FastBuildSettings.FastBuildSummary = false; + FastBuildSettings.FastBuildNoSummaryOnError = true; + FastBuildSettings.FastBuildDistribution = false; + FastBuildSettings.FastBuildMonitor = true; + FastBuildSettings.FastBuildAllowDBMigration = true; + FastBuildSettings.SetPathToResourceCompilerInEnvironment = true; + + KitsRootPaths.SetKitsRoot10ToHighestInstalledVersion(DevEnv.vs2019); + + // for the purpose of this sample, we'll reuse the FastBuild executables that live in the sharpmake source repo + string sharpmakeFastBuildDir = Util.PathGetAbsolute(Globals.RootDirectory, @"..\..\..\tools\FastBuild"); + switch (Util.GetExecutingPlatform()) + { + case Platform.linux: + FastBuildSettings.FastBuildMakeCommand = Path.Combine(sharpmakeFastBuildDir, "Linux-x64", "fbuild"); + break; + case Platform.mac: + FastBuildSettings.FastBuildMakeCommand = Path.Combine(sharpmakeFastBuildDir, "OSX-x64", "FBuild"); + break; + case Platform.win64: + default: + FastBuildSettings.FastBuildMakeCommand = Path.Combine(sharpmakeFastBuildDir, "Windows-x64", "FBuild.exe"); + break; + } + + Bff.UnityResolver = new Bff.FragmentUnityResolver(); + + foreach (Type solutionType in Assembly.GetExecutingAssembly().GetTypes().Where(t => !t.IsAbstract && t.IsSubclassOf(typeof(CommonSolution)))) + arguments.Generate(solutionType); + } + } +} diff --git a/samples/HelloClangCl/Properties/AssemblyInfo.cs b/samples/HelloClangCl/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..96835cc29 --- /dev/null +++ b/samples/HelloClangCl/Properties/AssemblyInfo.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HelloClangCl.Properties")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Ubisoft")] +[assembly: AssemblyProduct("HelloClangCl.Properties")] +[assembly: AssemblyCopyright("Copyright \u00A9 Ubisoft 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("CC6018D5-0760-463E-92FB-849E7E904449")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/HelloClangCl/codebase/HelloClangCl.sharpmake.cs b/samples/HelloClangCl/codebase/HelloClangCl.sharpmake.cs new file mode 100644 index 000000000..2654d29d6 --- /dev/null +++ b/samples/HelloClangCl/codebase/HelloClangCl.sharpmake.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Sharpmake; + +namespace HelloClangCl +{ + [Sharpmake.Generate] + public class HelloClangClSolution : CommonSolution + { + public HelloClangClSolution() + { + AddTargets(CommonTarget.GetDefaultTargets()); + Name = "HelloClangCl"; + } + + public override void ConfigureAll(Configuration conf, CommonTarget target) + { + base.ConfigureAll(conf, target); + + conf.AddProject(target); + conf.AddProject(target); + conf.AddProject(target); + conf.AddProject(target); + } + } +} diff --git a/samples/HelloClangCl/codebase/dll1/dll1.sharpmake.cs b/samples/HelloClangCl/codebase/dll1/dll1.sharpmake.cs new file mode 100644 index 000000000..a59e07d21 --- /dev/null +++ b/samples/HelloClangCl/codebase/dll1/dll1.sharpmake.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Sharpmake; + +namespace HelloClangCl +{ + [Sharpmake.Generate] + public class Dll1Project : CommonProject + { + public Dll1Project() + { + AddTargets(CommonTarget.GetDefaultTargets()); + Name = "dll1"; + } + + public override void ConfigureAll(Configuration conf, CommonTarget target) + { + base.ConfigureAll(conf, target); + + conf.SolutionFolder = "SharedLibs"; + + conf.PrecompHeader = "precomp.h"; + conf.PrecompSource = "precomp.cpp"; + + conf.Output = Configuration.OutputType.Dll; + + conf.Defines.Add("UTIL_DLL_EXPORT"); + conf.ExportDefines.Add("UTIL_DLL_IMPORT"); + + conf.IncludePaths.Add(SourceRootPath); + + conf.AddPrivateDependency(target); + } + } +} diff --git a/samples/HelloClangCl/codebase/dll1/precomp.cpp b/samples/HelloClangCl/codebase/dll1/precomp.cpp new file mode 100644 index 000000000..15c6d7b04 --- /dev/null +++ b/samples/HelloClangCl/codebase/dll1/precomp.cpp @@ -0,0 +1,2 @@ +#include "precomp.h" + diff --git a/samples/HelloClangCl/codebase/dll1/precomp.h b/samples/HelloClangCl/codebase/dll1/precomp.h new file mode 100644 index 000000000..201c6bf40 --- /dev/null +++ b/samples/HelloClangCl/codebase/dll1/precomp.h @@ -0,0 +1,7 @@ +#pragma once + +#pragma warning(push) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) diff --git a/samples/HelloClangCl/codebase/dll1/util_dll.cpp b/samples/HelloClangCl/codebase/dll1/util_dll.cpp new file mode 100644 index 000000000..4c30ce103 --- /dev/null +++ b/samples/HelloClangCl/codebase/dll1/util_dll.cpp @@ -0,0 +1,39 @@ +#include "precomp.h" +#include "util_dll.h" + +#include "src/util_static_lib1.h" + +#pragma warning(push) +#pragma warning(disable: 4668) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) + +int UtilDll1::ComputeSum(const std::vector& someInts) +{ + int acc = 0; + for (int item : someInts) + acc += item; + +#if defined(_DEBUG) && _DEBUG + std::cout << "- Dll1 is built in Debug" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + +#if defined(NDEBUG) && NDEBUG + std::cout << "- Dll1 is built in Release" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + + acc += static_cast(static_lib1_utils::GetRandomPosition()); + + return acc; +} + diff --git a/samples/HelloClangCl/codebase/dll1/util_dll.h b/samples/HelloClangCl/codebase/dll1/util_dll.h new file mode 100644 index 000000000..ead7afc75 --- /dev/null +++ b/samples/HelloClangCl/codebase/dll1/util_dll.h @@ -0,0 +1,21 @@ +#pragma once + +#pragma warning(push) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) + +#if defined(UTIL_DLL_EXPORT) && defined(_MSC_VER) +# define UTIL_DLL __declspec(dllexport) +#elif defined(UTIL_DLL_IMPORT) && defined(_MSC_VER) +# define UTIL_DLL __declspec(dllimport) +#else +# define UTIL_DLL +#endif + +struct UtilDll1 +{ + UTIL_DLL int ComputeSum(const std::vector& someInts); +}; + diff --git a/samples/HelloClangCl/codebase/exe/exe.sharpmake.cs b/samples/HelloClangCl/codebase/exe/exe.sharpmake.cs new file mode 100644 index 000000000..11f702883 --- /dev/null +++ b/samples/HelloClangCl/codebase/exe/exe.sharpmake.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Sharpmake; + +namespace HelloClangCl +{ + [Sharpmake.Generate] + public class ExeProject : CommonProject + { + public ExeProject() + { + AddTargets(CommonTarget.GetDefaultTargets()); + Name = "exe"; + } + + public override void ConfigureAll(Configuration conf, CommonTarget target) + { + base.ConfigureAll(conf, target); + + conf.Output = Configuration.OutputType.Exe; + + conf.PrecompHeader = "stdafx.h"; + conf.PrecompSource = "stdafx.cpp"; + + conf.AddPrivateDependency(target); + conf.AddPrivateDependency(target); + + conf.Defines.Add("CREATION_DATE=\"March 2021\""); + } + } +} diff --git a/samples/HelloClangCl/codebase/exe/main.cpp b/samples/HelloClangCl/codebase/exe/main.cpp new file mode 100644 index 000000000..ff1eac8b1 --- /dev/null +++ b/samples/HelloClangCl/codebase/exe/main.cpp @@ -0,0 +1,37 @@ +#include "stdafx.h" +#include "util_dll.h" +#include "util_static_lib2.h" +#include "sub folder/useless_static_lib2.h" + +int main(int, char**) +{ + std::cout << "Hello ClangCl World, from " CREATION_DATE "!" << std::endl; + +#if defined(_DEBUG) && _DEBUG + std::cout << "- Exe is built in Debug" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + +#if defined(NDEBUG) && NDEBUG + std::cout << "- Exe is built in Release" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + + std::vector someArray(5, 6); + + // from dll1 + UtilDll1 utilityDll; + utilityDll.ComputeSum(someArray); + + // from static_lib2 + Util2 utilityStatic; + utilityStatic.DoSomethingUseful(); + StaticLib2::UselessMethod(); + return 0; +} diff --git a/samples/HelloClangCl/codebase/exe/stdafx.cpp b/samples/HelloClangCl/codebase/exe/stdafx.cpp new file mode 100644 index 000000000..fd4f341c7 --- /dev/null +++ b/samples/HelloClangCl/codebase/exe/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/samples/HelloClangCl/codebase/exe/stdafx.h b/samples/HelloClangCl/codebase/exe/stdafx.h new file mode 100644 index 000000000..a53f0481b --- /dev/null +++ b/samples/HelloClangCl/codebase/exe/stdafx.h @@ -0,0 +1,8 @@ +#pragma once + +#pragma warning(push) +#pragma warning(disable: 4668) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) diff --git a/samples/HelloClangCl/codebase/static lib2/static_lib2.sharpmake.cs b/samples/HelloClangCl/codebase/static lib2/static_lib2.sharpmake.cs new file mode 100644 index 000000000..ea4f3433e --- /dev/null +++ b/samples/HelloClangCl/codebase/static lib2/static_lib2.sharpmake.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Sharpmake; + +namespace HelloClangCl +{ + [Sharpmake.Generate] + public class StaticLib2Project : CommonProject + { + public StaticLib2Project() + { + AddTargets(CommonTarget.GetDefaultTargets()); + Name = "static lib2"; + } + + public override void ConfigureAll(Configuration conf, CommonTarget target) + { + base.ConfigureAll(conf, target); + + conf.SolutionFolder = "StaticLibs"; + + conf.IncludePaths.Add(SourceRootPath); + } + } +} diff --git a/samples/HelloClangCl/codebase/static lib2/sub folder/useless_static_lib2.cpp b/samples/HelloClangCl/codebase/static lib2/sub folder/useless_static_lib2.cpp new file mode 100644 index 000000000..5308d55d7 --- /dev/null +++ b/samples/HelloClangCl/codebase/static lib2/sub folder/useless_static_lib2.cpp @@ -0,0 +1,17 @@ +#include "useless_static_lib2.h" + +#pragma warning(push) +#pragma warning(disable: 4668) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) + +namespace StaticLib2 +{ + void UselessMethod() + { + std::cout << "- Useless in fact!" << std::endl; + } +} + diff --git a/samples/HelloClangCl/codebase/static lib2/sub folder/useless_static_lib2.h b/samples/HelloClangCl/codebase/static lib2/sub folder/useless_static_lib2.h new file mode 100644 index 000000000..ee6d3ef92 --- /dev/null +++ b/samples/HelloClangCl/codebase/static lib2/sub folder/useless_static_lib2.h @@ -0,0 +1,7 @@ +#pragma once + +namespace StaticLib2 +{ + void UselessMethod(); +} + diff --git a/samples/HelloClangCl/codebase/static lib2/util_static_lib2.cpp b/samples/HelloClangCl/codebase/static lib2/util_static_lib2.cpp new file mode 100644 index 000000000..7fe1753af --- /dev/null +++ b/samples/HelloClangCl/codebase/static lib2/util_static_lib2.cpp @@ -0,0 +1,40 @@ +#include "util_static_lib2.h" + +#pragma warning(push) +#pragma warning(disable: 4668) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) + +Util2::Util2() = default; + +Util2::~Util2() +{ +} + +void Util2::DoSomethingUseful() const +{ +#if defined(_DEBUG) && _DEBUG + std::cout << "- StaticLib2 is built in Debug" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + +#if defined(NDEBUG) && NDEBUG + std::cout << "- StaticLib2 is built in Release" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + + return DoSomethingInternal("Yeah right..."); +} + +void Util2::DoSomethingInternal(const char* anArgument) const +{ + std::cout << "Useful, right?\n- " << anArgument << std::endl; +} diff --git a/samples/HelloClangCl/codebase/static lib2/util_static_lib2.h b/samples/HelloClangCl/codebase/static lib2/util_static_lib2.h new file mode 100644 index 000000000..196128c58 --- /dev/null +++ b/samples/HelloClangCl/codebase/static lib2/util_static_lib2.h @@ -0,0 +1,15 @@ +#pragma once + +class Util2 +{ +public: + Util2(); + ~Util2(); + +public: + void DoSomethingUseful() const; + +private: + void DoSomethingInternal(const char* anArgument) const; +}; + diff --git a/samples/HelloClangCl/codebase/static_lib1/src/ensure_debug.cpp b/samples/HelloClangCl/codebase/static_lib1/src/ensure_debug.cpp new file mode 100644 index 000000000..a4c3dd5b6 --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/src/ensure_debug.cpp @@ -0,0 +1,11 @@ +#include "src/pch.h" + +#if !_DEBUG + #error Expected Debug define (_DEBUG) was not found +#endif + +#if defined(NDEBUG) && NDEBUG + #error Unexpected Release define (NDEBUG) was found +#endif + +#pragma message("Debug is built!") diff --git a/samples/HelloClangCl/codebase/static_lib1/src/ensure_release.cpp b/samples/HelloClangCl/codebase/static_lib1/src/ensure_release.cpp new file mode 100644 index 000000000..bf99db8c7 --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/src/ensure_release.cpp @@ -0,0 +1,11 @@ +#include "src/pch.h" + +#if defined(_DEBUG) && _DEBUG + #error Unexpected Debug define (_DEBUG) was found +#endif + +#if !NDEBUG + #error Expected Release define (NDEBUG) was not found +#endif + +#pragma message("Release is built!") diff --git a/samples/HelloClangCl/codebase/static_lib1/src/pch.cpp b/samples/HelloClangCl/codebase/static_lib1/src/pch.cpp new file mode 100644 index 000000000..e3cb5f78c --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/src/pch.cpp @@ -0,0 +1,2 @@ +#include "src/pch.h" + diff --git a/samples/HelloClangCl/codebase/static_lib1/src/pch.h b/samples/HelloClangCl/codebase/static_lib1/src/pch.h new file mode 100644 index 000000000..a53f0481b --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/src/pch.h @@ -0,0 +1,8 @@ +#pragma once + +#pragma warning(push) +#pragma warning(disable: 4668) +#pragma warning(disable: 4710) +#pragma warning(disable: 4711) +#include +#pragma warning(pop) diff --git a/samples/HelloClangCl/codebase/static_lib1/src/util_static_lib1.cpp b/samples/HelloClangCl/codebase/static_lib1/src/util_static_lib1.cpp new file mode 100644 index 000000000..9ec055461 --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/src/util_static_lib1.cpp @@ -0,0 +1,28 @@ +#include "src/pch.h" +#include "util_static_lib1.h" +#include + +namespace static_lib1_utils +{ + std::streampos GetRandomPosition() + { +#if defined(_DEBUG) && _DEBUG + std::cout << "- StaticLib1 is built in Debug" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + +#if defined(NDEBUG) && NDEBUG + std::cout << "- StaticLib1 is built in Release" +# if defined(USES_FASTBUILD) && USES_FASTBUILD + " with FastBuild" +# endif + "!" << std::endl; +#endif + + return 1; + } +} + diff --git a/samples/HelloClangCl/codebase/static_lib1/src/util_static_lib1.h b/samples/HelloClangCl/codebase/static_lib1/src/util_static_lib1.h new file mode 100644 index 000000000..0cec87480 --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/src/util_static_lib1.h @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace static_lib1_utils +{ + std::streampos GetRandomPosition(); +} diff --git a/samples/HelloClangCl/codebase/static_lib1/static_lib1.sharpmake.cs b/samples/HelloClangCl/codebase/static_lib1/static_lib1.sharpmake.cs new file mode 100644 index 000000000..a7c2eba82 --- /dev/null +++ b/samples/HelloClangCl/codebase/static_lib1/static_lib1.sharpmake.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2021 Ubisoft Entertainment +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Sharpmake; + +namespace HelloClangCl +{ + [Sharpmake.Generate] + public class StaticLib1Project : CommonProject + { + public StaticLib1Project() + { + AddTargets(CommonTarget.GetDefaultTargets()); + Name = "static_lib1"; + } + + public override void ConfigureAll(Configuration conf, CommonTarget target) + { + base.ConfigureAll(conf, target); + + conf.SolutionFolder = "StaticLibs"; + + // intentionally in a subfolder + conf.PrecompHeader = @"src\pch.h"; + conf.PrecompSource = @"src\pch.cpp"; + + conf.IncludePaths.Add(SourceRootPath); + + switch (target.Optimization) + { + case Optimization.Debug: + conf.SourceFilesBuildExclude.Add(@"src\ensure_release.cpp"); + break; + case Optimization.Release: + // use a different method to exclude ensure_debug.cpp + conf.SourceFilesBuildExcludeRegex.Add(Util.RegexPathCombine("src", @"ensure_d.*\.cpp$")); + break; + default: + throw new Error("Unexpected optimization " + target.Optimization); + } + } + } +} diff --git a/samples/HelloLinux/HelloLinux.CommonProject.sharpmake.cs b/samples/HelloLinux/HelloLinux.CommonProject.sharpmake.cs index 4d3ad1cac..c4c378123 100644 --- a/samples/HelloLinux/HelloLinux.CommonProject.sharpmake.cs +++ b/samples/HelloLinux/HelloLinux.CommonProject.sharpmake.cs @@ -64,6 +64,12 @@ public virtual void ConfigureAll(Configuration conf, CommonTarget target) //conf.TargetFileName += "x"; conf.Output = Configuration.OutputType.Lib; // defaults to creating static libs + + // Create a separate package directory before building. + string packageDir = $@"{RootPath}\package"; + conf.EventPreBuild.Add($"mkdir {packageDir}"); + // Copy the build artifacts to the package directory. + conf.EventPostBuild.Add($@"cp [conf.TargetPath]\[project.Name].* {packageDir}"); } //////////////////////////////////////////////////////////////////////// diff --git a/samples/Sharpmake.Samples.sharpmake.cs b/samples/Sharpmake.Samples.sharpmake.cs index 5bfb3d99b..897373bb7 100644 --- a/samples/Sharpmake.Samples.sharpmake.cs +++ b/samples/Sharpmake.Samples.sharpmake.cs @@ -159,6 +159,25 @@ public FastBuildSimpleExecutable() } } + [Generate] + public class HelloClangClProject : SampleProject + { + public HelloClangClProject() + { + Name = "HelloClangCl"; + SharpmakeMainFile = "HelloClangCl.Main.sharpmake.cs"; + + // This one is special, we have .sharpmake.cs files in the codebase + SourceFilesExcludeRegex.Remove(@"\\codebase\\"); + } + + public override void ConfigureAll(Configuration conf, Target target) + { + base.ConfigureAll(conf, target); + conf.AddPrivateDependency(target); + } + } + [Generate] public class HelloLinuxProject : SampleProject { diff --git a/tools/FastBuild/LICENSE.TXT b/tools/FastBuild/LICENSE.TXT index 286a09c3c..097781f77 100644 --- a/tools/FastBuild/LICENSE.TXT +++ b/tools/FastBuild/LICENSE.TXT @@ -1,4 +1,4 @@ -Copyright © 2012-2020 Franta Fulin +Copyright © 2012-2021 Franta Fulin This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -6,7 +6,7 @@ Permission is granted to anyone to use this software for any purpose, including 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. -2. If you use this software, in source or binary form, an acknowledgment in the product documentation or credits would be appreciated but is not required. Example: "This product uses FASTBuild © 2012-2020 Franta Fulin." +2. If you use this software, in source or binary form, an acknowledgment in the product documentation or credits would be appreciated but is not required. Example: "This product uses FASTBuild © 2012-2021 Franta Fulin." 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. diff --git a/tools/FastBuild/Linux-x64/fbuild b/tools/FastBuild/Linux-x64/fbuild old mode 100644 new mode 100755 index 23957c9c9..82a852954 Binary files a/tools/FastBuild/Linux-x64/fbuild and b/tools/FastBuild/Linux-x64/fbuild differ diff --git a/tools/FastBuild/OSX-x64/FBuild b/tools/FastBuild/OSX-x64/FBuild index c9508b011..2a3a7a45c 100755 Binary files a/tools/FastBuild/OSX-x64/FBuild and b/tools/FastBuild/OSX-x64/FBuild differ diff --git a/tools/FastBuild/Windows-x64/FBuild.exe b/tools/FastBuild/Windows-x64/FBuild.exe index 404a4c93f..17266103b 100644 Binary files a/tools/FastBuild/Windows-x64/FBuild.exe and b/tools/FastBuild/Windows-x64/FBuild.exe differ