public void BuildResourceCompilerArguments_Simple() { var targetRootDirectory = new Path("C:/target/"); var arguments = new SharedCompileArguments() { ResourceFile = new ResourceCompileArguments() { SourceFile = new Path("Resources.rc"), TargetFile = new Path("Resources.mock.res"), }, }; var actualArguments = ArgumentBuilder.BuildResourceCompilerArguments( targetRootDirectory, arguments); var expectedArguments = new List <string>() { "/nologo", "/D_UNICODE", "/DUNICODE", "/l\"0x0409\"", "/Fo\"C:/target/Resources.mock.res\"", "./Resources.rc", }; Assert.Equal(expectedArguments, actualArguments); }
public void BuildSharedCompilerArguments_SingleArgument_LanguageStandard_CPP20() { var arguments = new SharedCompileArguments() { Standard = LanguageStandard.CPP20, }; var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/W4", "/std:c++latest", "/Od", "/X", "/RTC1", "/EHsc", "/MT", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
public void BuildSharedCompilerArguments_SingleArgument_GenerateDebugInformation() { var arguments = new SharedCompileArguments() { Standard = LanguageStandard.CPP17, Optimize = OptimizationLevel.None, GenerateSourceDebugInfo = true, }; var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/Z7", "/W4", "/std:c++17", "/Od", "/X", "/RTC1", "/EHsc", "/MTd", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
public void BuildSharedCompilerArguments_DefaultParameters() { var arguments = new SharedCompileArguments(); var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/W4", "/std:c++11", "/Od", "/X", "/RTC1", "/EHsc", "/MT", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
public void BuildSharedCompilerArguments_SingleArgument_OptimizationLevel( OptimizationLevel level, string expectedFlag) { var arguments = new SharedCompileArguments() { Standard = LanguageStandard.CPP17, Optimize = level, }; var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/W4", "/std:c++17", expectedFlag, "/X", "/RTC1", "/EHsc", "/MT", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
public void Compile_Simple() { var uut = new Compiler( new Path("C:/bin/mock.cl.exe"), new Path("C:/bin/mock.link.exe"), new Path("C:/bin/mock.lib.exe"), new Path("C:/bin/mock.rc.exe")); var arguments = new SharedCompileArguments() { SourceRootDirectory = new Path("C:/source/"), TargetRootDirectory = new Path("C:/target/"), ObjectDirectory = new Path("ObjectDir/"), }; var translationUnitArguments = new TranslationUnitCompileArguments() { SourceFile = new Path("File.cpp"), TargetFile = new Path("obj/File.obj"), }; arguments.ImplementationUnits = new List <TranslationUnitCompileArguments>() { translationUnitArguments, }; var result = uut.CreateCompileOperations(arguments); // Verify result var expected = new List <BuildOperation>() { new BuildOperation( "WriteFile [./ObjectDir/SharedCompileArguments.rsp]", new Path("C:/target/"), new Path("./writefile.exe"), "\"./ObjectDir/SharedCompileArguments.rsp\" \"/nologo /FC /permissive- /Zc:__cplusplus /Zc:externConstexpr /Zc:inline /Zc:throwingNew /W4 /std:c++11 /Od /X /RTC1 /EHsc /MT /bigobj /c\"", new List <Path>(), new List <Path>() { new Path("./ObjectDir/SharedCompileArguments.rsp"), }), new BuildOperation( "./File.cpp", new Path("C:/source/"), new Path("C:/bin/mock.cl.exe"), "@C:/target/ObjectDir/SharedCompileArguments.rsp ./File.cpp /Fo\"C:/target/obj/File.obj\"", new List <Path>() { new Path("File.cpp"), new Path("C:/target/ObjectDir/SharedCompileArguments.rsp"), }, new List <Path>() { new Path("C:/target/obj/File.obj"), }), }; Assert.Equal(expected, result); }
public static IList <string> BuildResourceCompilerArguments( Path targetRootDirectory, SharedCompileArguments arguments) { if (arguments.ResourceFile == null) { throw new ArgumentNullException(nameof(arguments)); } // Build the arguments for a standard translation unit var commandArguments = new List <string>(); // Disable the logo AddFlag(commandArguments, ArgumentFlag_NoLogo); // TODO: Defines? AddFlagValue(commandArguments, Compiler_ArgumentParameter_PreprocessorDefine, "_UNICODE"); AddFlagValue(commandArguments, Compiler_ArgumentParameter_PreprocessorDefine, "UNICODE"); // Specify default language using language identifier AddFlagValueWithQuotes(commandArguments, "l", "0x0409"); // Set the include paths foreach (var directory in arguments.IncludeDirectories) { AddFlagValueWithQuotes(commandArguments, Compiler_ArgumentParameter_Include, directory.ToString()); } // Add the target file as outputs var absoluteTargetFile = targetRootDirectory + arguments.ResourceFile.TargetFile; AddFlagValueWithQuotes( commandArguments, Compiler_ArgumentParameter_ObjectFile, absoluteTargetFile.ToString()); // Add the source file as input commandArguments.Add(arguments.ResourceFile.SourceFile.ToString()); return(commandArguments); }
public void BuildSharedCompilerArguments_SingleArgument_Modules() { var arguments = new SharedCompileArguments() { IncludeModules = new List <Path>() { new Path("Module.pcm"), new Path("Std.pcm"), }, }; var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/W4", "/std:c++11", "/Od", "/X", "/RTC1", "/EHsc", "/MT", "/reference", "\"./Module.pcm\"", "/reference", "\"./Std.pcm\"", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
public void BuildSharedCompilerArguments_SingleArgument_PreprocessorDefinitions() { var arguments = new SharedCompileArguments() { PreprocessorDefinitions = new List <string>() { "DEBUG", "VERSION=1" }, }; var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/W4", "/std:c++11", "/Od", "/DDEBUG", "/DVERSION=1", "/X", "/RTC1", "/EHsc", "/MT", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
public void BuildSharedCompilerArguments_SingleArgument_IncludePaths() { var arguments = new SharedCompileArguments() { IncludeDirectories = new List <Path>() { new Path("C:/Files/SDK/"), new Path("my files/") }, }; var actualArguments = ArgumentBuilder.BuildSharedCompilerArguments( arguments); var expectedArguments = new List <string>() { "/nologo", "/FC", "/permissive-", "/Zc:__cplusplus", "/Zc:externConstexpr", "/Zc:inline", "/Zc:throwingNew", "/W4", "/std:c++11", "/Od", "/I\"C:/Files/SDK/\"", "/I\"./my files/\"", "/X", "/RTC1", "/EHsc", "/MT", "/bigobj", "/c", }; Assert.Equal(expectedArguments, actualArguments); }
/// <summary> /// Compile the module and source files /// </summary> private void CoreCompile( IBuildState buildState, BuildArguments arguments, BuildResult result) { // Ensure there are actually files to build if (arguments.ModuleInterfacePartitionSourceFiles.Count != 0 || !arguments.ModuleInterfaceSourceFile.IsEmpty || arguments.SourceFiles.Count != 0) { // Setup the shared properties var compileArguments = new SharedCompileArguments() { Standard = arguments.LanguageStandard, Optimize = Convert(arguments.OptimizationLevel), SourceRootDirectory = arguments.SourceRootDirectory, TargetRootDirectory = arguments.TargetRootDirectory, ObjectDirectory = arguments.ObjectDirectory, IncludeDirectories = arguments.IncludeDirectories, IncludeModules = arguments.ModuleDependencies, PreprocessorDefinitions = arguments.PreprocessorDefinitions, GenerateSourceDebugInfo = arguments.GenerateSourceDebugInfo, EnableWarningsAsErrors = arguments.EnableWarningsAsErrors, DisabledWarnings = arguments.DisabledWarnings, EnabledWarnings = arguments.EnabledWarnings, CustomProperties = arguments.CustomProperties, }; // Compile the resource file if present if (!arguments.ResourceFile.IsEmpty) { buildState.LogTrace(TraceLevel.Information, "Generate Resource File Compile: " + arguments.ResourceFile.ToString()); var compiledResourceFile = arguments.ObjectDirectory + new Path(arguments.ResourceFile.GetFileName()); compiledResourceFile.SetFileExtension(_compiler.ResourceFileExtension); var compileResourceFileArguments = new ResourceCompileArguments() { SourceFile = arguments.ResourceFile, TargetFile = compiledResourceFile, }; // Add the resource file arguments to the shared build definition compileArguments.ResourceFile = compileResourceFileArguments; } // Build up the entire Interface Dependency Closure for each file var partitionInterfaceDependencyLookup = new Dictionary <Path, IReadOnlyList <Path> >(); foreach (var file in arguments.ModuleInterfacePartitionSourceFiles) { partitionInterfaceDependencyLookup.Add(file.File, file.Imports); } // Compile the individual module interface partition translation units var compileInterfacePartitionUnits = new List <InterfaceUnitCompileArguments>(); var allPartitionInterfaces = new List <Path>(); foreach (var file in arguments.ModuleInterfacePartitionSourceFiles) { buildState.LogTrace(TraceLevel.Information, "Generate Module Interface Partition Compile Operation: " + file.File.ToString()); var objectModuleInterfaceFile = arguments.ObjectDirectory + new Path(file.File.GetFileName()); objectModuleInterfaceFile.SetFileExtension(_compiler.ModuleFileExtension); var interfaceDependencyClosure = new HashSet <Path>(); BuildClosure(interfaceDependencyClosure, file.File, partitionInterfaceDependencyLookup); if (interfaceDependencyClosure.Contains(file.File)) { throw new InvalidOperationException($"Circular partition references in: {file.File}"); } var partitionImports = new List <Path>(); foreach (var import in interfaceDependencyClosure) { var importInterface = arguments.ObjectDirectory + new Path(import.GetFileName()); importInterface.SetFileExtension(_compiler.ModuleFileExtension); partitionImports.Add(arguments.TargetRootDirectory + importInterface); } var compileFileArguments = new InterfaceUnitCompileArguments() { SourceFile = file.File, TargetFile = arguments.ObjectDirectory + new Path(file.File.GetFileName()), IncludeModules = partitionImports, ModuleInterfaceTarget = objectModuleInterfaceFile, }; compileFileArguments.TargetFile.SetFileExtension(_compiler.ObjectFileExtension); compileInterfacePartitionUnits.Add(compileFileArguments); allPartitionInterfaces.Add(arguments.TargetRootDirectory + objectModuleInterfaceFile); } // Add all partition unit interface files as module dependencies since MSVC does not // combine the interfaces into the final interface unit foreach (var module in allPartitionInterfaces) { result.ModuleDependencies.Add(module); } compileArguments.InterfacePartitionUnits = compileInterfacePartitionUnits; // Compile the module interface unit if present if (!arguments.ModuleInterfaceSourceFile.IsEmpty) { buildState.LogTrace(TraceLevel.Information, "Generate Module Interface Unit Compile: " + arguments.ModuleInterfaceSourceFile.ToString()); var objectModuleInterfaceFile = arguments.ObjectDirectory + new Path(arguments.ModuleInterfaceSourceFile.GetFileName()); objectModuleInterfaceFile.SetFileExtension(_compiler.ModuleFileExtension); var binaryOutputModuleInterfaceFile = arguments.BinaryDirectory + new Path(arguments.TargetName + "." + _compiler.ModuleFileExtension); var compileModuleFileArguments = new InterfaceUnitCompileArguments() { SourceFile = arguments.ModuleInterfaceSourceFile, TargetFile = arguments.ObjectDirectory + new Path(arguments.ModuleInterfaceSourceFile.GetFileName()), IncludeModules = allPartitionInterfaces, ModuleInterfaceTarget = objectModuleInterfaceFile, }; compileModuleFileArguments.TargetFile.SetFileExtension(_compiler.ObjectFileExtension); // Add the interface unit arguments to the shared build definition compileArguments.InterfaceUnit = compileModuleFileArguments; // Copy the binary module interface to the binary directory after compiling var copyInterfaceOperation = SharedOperations.CreateCopyFileOperation( arguments.TargetRootDirectory, objectModuleInterfaceFile, binaryOutputModuleInterfaceFile); result.BuildOperations.Add(copyInterfaceOperation); // Add output module interface to the parent set of modules // This will allow the module implementation units access as well as downstream // dependencies to the public interface. result.ModuleDependencies.Add( binaryOutputModuleInterfaceFile.HasRoot ? binaryOutputModuleInterfaceFile : arguments.TargetRootDirectory + binaryOutputModuleInterfaceFile); } // Compile the individual translation units var compileImplementationUnits = new List <TranslationUnitCompileArguments>(compileArguments.ImplementationUnits); foreach (var file in arguments.SourceFiles) { buildState.LogTrace(TraceLevel.Information, "Generate Compile Operation: " + file.ToString()); var compileFileArguments = new TranslationUnitCompileArguments(); compileFileArguments.SourceFile = file; compileFileArguments.TargetFile = arguments.ObjectDirectory + new Path(file.GetFileName()); compileFileArguments.TargetFile.SetFileExtension(_compiler.ObjectFileExtension); compileImplementationUnits.Add(compileFileArguments); } compileArguments.ImplementationUnits = compileImplementationUnits; // Compile all source files as a single call var compileOperations = _compiler.CreateCompileOperations(compileArguments); foreach (var operation in compileOperations) { result.BuildOperations.Add(operation); } } }
/// <summary> /// Compile /// </summary> public IList <BuildOperation> CreateCompileOperations(SharedCompileArguments arguments) { _compileRequests.Add(arguments); var result = new List <BuildOperation>(); foreach (var fileArguments in arguments.InterfacePartitionUnits) { result.Add( new BuildOperation( $"MockCompilePartition: {_compileRequests.Count}", new Path("MockWorkingDirectory"), new Path("MockCompiler.exe"), "Arguments", new List <Path>() { fileArguments.SourceFile, }, new List <Path>() { fileArguments.TargetFile, fileArguments.ModuleInterfaceTarget, })); } if (!ReferenceEquals(arguments.InterfaceUnit, null)) { result.Add( new BuildOperation( $"MockCompileModule: {_compileRequests.Count}", new Path("MockWorkingDirectory"), new Path("MockCompiler.exe"), "Arguments", new List <Path>() { arguments.InterfaceUnit.SourceFile, }, new List <Path>() { arguments.InterfaceUnit.TargetFile, arguments.InterfaceUnit.ModuleInterfaceTarget, })); } foreach (var fileArguments in arguments.ImplementationUnits) { result.Add( new BuildOperation( $"MockCompile: {_compileRequests.Count}", new Path("MockWorkingDirectory"), new Path("MockCompiler.exe"), "Arguments", new List <Path>() { fileArguments.SourceFile, }, new List <Path>() { fileArguments.TargetFile, })); } return(result); }
/// <summary> /// Compile /// </summary> public IList <BuildOperation> CreateCompileOperations( SharedCompileArguments arguments) { var operations = new List <BuildOperation>(); // Write the shared arguments to the response file var responseFile = arguments.ObjectDirectory + new Path("SharedCompileArguments.rsp"); var sharedCommandArguments = ArgumentBuilder.BuildSharedCompilerArguments(arguments); var writeSharedArgumentsOperation = SharedOperations.CreateWriteFileOperation( arguments.TargetRootDirectory, responseFile, CombineArguments(sharedCommandArguments)); operations.Add(writeSharedArgumentsOperation); // Initialize a shared input set var sharedInputFiles = new List <Path>(); sharedInputFiles.AddRange(arguments.IncludeModules); var absoluteResponseFile = arguments.TargetRootDirectory + responseFile; // Generate the resource build operation if present if (arguments.ResourceFile is not null) { var resourceFileArguments = arguments.ResourceFile; // Build up the input/output sets var inputFiles = sharedInputFiles.ToList(); inputFiles.Add(resourceFileArguments.SourceFile); // TODO: The temp files require read access, need a way to tell build operation inputFiles.Add(arguments.TargetRootDirectory + new Path("fake_file")); var outputFiles = new List <Path>() { arguments.TargetRootDirectory + resourceFileArguments.TargetFile, }; // Build the unique arguments for this resource file var commandArguments = ArgumentBuilder.BuildResourceCompilerArguments( arguments.TargetRootDirectory, arguments); // Generate the operation var buildOperation = new BuildOperation( resourceFileArguments.SourceFile.ToString(), arguments.SourceRootDirectory, _rcExecutable, CombineArguments(commandArguments), inputFiles, outputFiles); operations.Add(buildOperation); } var internalModules = new List <Path>(); foreach (var partitionUnitArguments in arguments.InterfacePartitionUnits) { // Build up the input/output sets var inputFiles = sharedInputFiles.ToList(); inputFiles.Add(partitionUnitArguments.SourceFile); inputFiles.Add(absoluteResponseFile); inputFiles.AddRange(partitionUnitArguments.IncludeModules); var outputFiles = new List <Path>() { arguments.TargetRootDirectory + partitionUnitArguments.TargetFile, arguments.TargetRootDirectory + partitionUnitArguments.ModuleInterfaceTarget, }; // Build the unique arguments for this translation unit var commandArguments = ArgumentBuilder.BuildPartitionUnitCompilerArguments( arguments.TargetRootDirectory, partitionUnitArguments, absoluteResponseFile); // Generate the operation var buildOperation = new BuildOperation( partitionUnitArguments.SourceFile.ToString(), arguments.SourceRootDirectory, _compilerExecutable, CombineArguments(commandArguments), inputFiles.ToArray(), outputFiles); operations.Add(buildOperation); // Add our module interface back in for the downstream compilers internalModules.Add(arguments.TargetRootDirectory + partitionUnitArguments.ModuleInterfaceTarget); } // Generate the interface build operation if present if (arguments.InterfaceUnit is not null) { var interfaceUnitArguments = arguments.InterfaceUnit; // Build up the input/output sets var inputFiles = sharedInputFiles.ToList(); inputFiles.Add(interfaceUnitArguments.SourceFile); inputFiles.Add(absoluteResponseFile); inputFiles.AddRange(interfaceUnitArguments.IncludeModules); var outputFiles = new List <Path>() { arguments.TargetRootDirectory + interfaceUnitArguments.TargetFile, arguments.TargetRootDirectory + interfaceUnitArguments.ModuleInterfaceTarget, }; // Build the unique arguments for this translation unit var commandArguments = ArgumentBuilder.BuildInterfaceUnitCompilerArguments( arguments.TargetRootDirectory, interfaceUnitArguments, absoluteResponseFile); // Generate the operation var buildOperation = new BuildOperation( interfaceUnitArguments.SourceFile.ToString(), arguments.SourceRootDirectory, _compilerExecutable, CombineArguments(commandArguments), inputFiles, outputFiles); operations.Add(buildOperation); // Add our module interface back in for the downstream compilers internalModules.Add(arguments.TargetRootDirectory + interfaceUnitArguments.ModuleInterfaceTarget); } foreach (var implementationUnitArguments in arguments.ImplementationUnits) { // Build up the input/output sets var inputFiles = sharedInputFiles.ToList(); inputFiles.Add(implementationUnitArguments.SourceFile); inputFiles.Add(absoluteResponseFile); inputFiles.AddRange(implementationUnitArguments.IncludeModules); inputFiles.AddRange(internalModules); var outputFiles = new List <Path>() { arguments.TargetRootDirectory + implementationUnitArguments.TargetFile, }; // Build the unique arguments for this translation unit var commandArguments = ArgumentBuilder.BuildTranslationUnitCompilerArguments( arguments.TargetRootDirectory, implementationUnitArguments, absoluteResponseFile, internalModules); // Generate the operation var buildOperation = new BuildOperation( implementationUnitArguments.SourceFile.ToString(), arguments.SourceRootDirectory, _compilerExecutable, CombineArguments(commandArguments), inputFiles.ToArray(), outputFiles); operations.Add(buildOperation); } return(operations); }
public void Compile_Module_Partition() { var uut = new Compiler( new Path("C:/bin/mock.cl.exe"), new Path("C:/bin/mock.link.exe"), new Path("C:/bin/mock.lib.exe"), new Path("C:/bin/mock.rc.exe")); var arguments = new SharedCompileArguments() { SourceRootDirectory = new Path("C:/source/"), TargetRootDirectory = new Path("C:/target/"), ObjectDirectory = new Path("ObjectDir/"), IncludeDirectories = new List <Path>() { new Path("Includes"), }, IncludeModules = new List <Path>() { new Path("Module.pcm"), }, PreprocessorDefinitions = new List <string>() { "DEBUG", }, InterfacePartitionUnits = new List <InterfaceUnitCompileArguments>() { new InterfaceUnitCompileArguments() { SourceFile = new Path("File.cpp"), TargetFile = new Path("obj/File.obj"), ModuleInterfaceTarget = new Path("obj/File.pcm"), IncludeModules = new List <Path>() { new Path("obj/Other.pcm"), }, }, }, }; var result = uut.CreateCompileOperations(arguments); // Verify result var expected = new List <BuildOperation>() { new BuildOperation( "WriteFile [./ObjectDir/SharedCompileArguments.rsp]", new Path("C:/target/"), new Path("./writefile.exe"), "\"./ObjectDir/SharedCompileArguments.rsp\" \"/nologo /FC /permissive- /Zc:__cplusplus /Zc:externConstexpr /Zc:inline /Zc:throwingNew /W4 /std:c++11 /Od /I\"./Includes\" /DDEBUG /X /RTC1 /EHsc /MT /reference \"./Module.pcm\" /bigobj /c\"", new List <Path>(), new List <Path>() { new Path("./ObjectDir/SharedCompileArguments.rsp"), }), new BuildOperation( "./File.cpp", new Path("C:/source/"), new Path("C:/bin/mock.cl.exe"), "@C:/target/ObjectDir/SharedCompileArguments.rsp /reference \"./obj/Other.pcm\" ./File.cpp /Fo\"C:/target/obj/File.obj\" /interface /ifcOutput \"C:/target/obj/File.pcm\"", new List <Path>() { new Path("Module.pcm"), new Path("File.cpp"), new Path("C:/target/ObjectDir/SharedCompileArguments.rsp"), new Path("obj/Other.pcm"), }, new List <Path>() { new Path("C:/target/obj/File.obj"), new Path("C:/target/obj/File.pcm"), }), }; Assert.Equal(expected, result); }
public void Compile_Resource() { var uut = new Compiler( new Path("C:/bin/mock.cl.exe"), new Path("C:/bin/mock.link.exe"), new Path("C:/bin/mock.lib.exe"), new Path("C:/bin/mock.rc.exe")); var arguments = new SharedCompileArguments() { SourceRootDirectory = new Path("C:/source/"), TargetRootDirectory = new Path("C:/target/"), ObjectDirectory = new Path("ObjectDir/"), IncludeDirectories = new List <Path>() { new Path("Includes"), }, IncludeModules = new List <Path>() { new Path("Module.pcm"), }, PreprocessorDefinitions = new List <string>() { "DEBUG" }, ResourceFile = new ResourceCompileArguments() { SourceFile = new Path("Resources.rc"), TargetFile = new Path("obj/Resources.res"), }, }; var result = uut.CreateCompileOperations(arguments); // Verify result var expected = new List <BuildOperation>() { new BuildOperation( "WriteFile [./ObjectDir/SharedCompileArguments.rsp]", new Path("C:/target/"), new Path("./writefile.exe"), "\"./ObjectDir/SharedCompileArguments.rsp\" \"/nologo /FC /permissive- /Zc:__cplusplus /Zc:externConstexpr /Zc:inline /Zc:throwingNew /W4 /std:c++11 /Od /I\"./Includes\" /DDEBUG /X /RTC1 /EHsc /MT /reference \"./Module.pcm\" /bigobj /c\"", new List <Path>(), new List <Path>() { new Path("./ObjectDir/SharedCompileArguments.rsp"), }), new BuildOperation( "./Resources.rc", new Path("C:/source/"), new Path("C:/bin/mock.rc.exe"), "/nologo /D_UNICODE /DUNICODE /l\"0x0409\" /I\"./Includes\" /Fo\"C:/target/obj/Resources.res\" ./Resources.rc", new List <Path>() { new Path("Module.pcm"), new Path("Resources.rc"), new Path("C:/target/fake_file"), }, new List <Path>() { new Path("C:/target/obj/Resources.res"), }), }; Assert.Equal(expected, result); }
public static IList <string> BuildSharedCompilerArguments( SharedCompileArguments arguments) { // Calculate object output file var commandArguments = new List <string>(); // Disable the logo AddFlag(commandArguments, ArgumentFlag_NoLogo); // Enable full paths for errors AddFlag(commandArguments, "FC"); // Enable standards-conforming compiler behavior // https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=vs-2019 // Note: Enables /Zc:referenceBinding, /Zc:strictStrings, and /Zc:rvalueCast // And after 15.3 /Zc:ternary AddFlag(commandArguments, "permissive-"); // Enable the __cplusplus macro to report the supported standard // https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2019 bool disableCPlusPlusMacroConformance = arguments.CustomProperties.Contains("DisableCPlusPlusMacroConformance"); if (!disableCPlusPlusMacroConformance) { AddParameter(commandArguments, "Zc", "__cplusplus"); } // Enable external linkage for constexpr variables // https://docs.microsoft.com/en-us/cpp/build/reference/zc-externconstexpr?view=vs-2019 AddParameter(commandArguments, "Zc", "externConstexpr"); // Remove unreferenced function or data if it is COMDAT or has internal linkage only // https://docs.microsoft.com/en-us/cpp/build/reference/zc-inline-remove-unreferenced-comdat?view=vs-2019 AddParameter(commandArguments, "Zc", "inline"); // Assume operator new throws on failure // https://docs.microsoft.com/en-us/cpp/build/reference/zc-throwingnew-assume-operator-new-throws?view=vs-2019 AddParameter(commandArguments, "Zc", "throwingNew"); // Generate source debug information if (arguments.GenerateSourceDebugInfo) { AddFlag(commandArguments, Compiler_ArgumentFlag_GenerateDebugInformation); } // Disabled individual warnings if (arguments.EnableWarningsAsErrors) { AddFlag(commandArguments, "WX"); } AddFlag(commandArguments, "W4"); // Disable any requested warnings foreach (var warning in arguments.DisabledWarnings) { AddFlagValue(commandArguments, "wd", warning); } // Enable any requested warnings foreach (var warning in arguments.EnabledWarnings) { AddFlagValue(commandArguments, "w", warning); } // Set the language standard switch (arguments.Standard) { case LanguageStandard.CPP11: AddParameter(commandArguments, Compiler_ArgumentParameter_Standard, "c++11"); break; case LanguageStandard.CPP14: AddParameter(commandArguments, Compiler_ArgumentParameter_Standard, "c++14"); break; case LanguageStandard.CPP17: AddParameter(commandArguments, Compiler_ArgumentParameter_Standard, "c++17"); break; case LanguageStandard.CPP20: AddParameter(commandArguments, Compiler_ArgumentParameter_Standard, "c++latest"); break; default: throw new InvalidOperationException("Unknown language standard."); } // Set the optimization level switch (arguments.Optimize) { case OptimizationLevel.None: AddFlag(commandArguments, Compiler_ArgumentFlag_Optimization_Disable); break; case OptimizationLevel.Speed: AddFlag(commandArguments, Compiler_ArgumentFlag_Optimization_Speed); break; case OptimizationLevel.Size: AddFlag(commandArguments, Compiler_ArgumentFlag_Optimization_Size); break; default: throw new InvalidOperationException("Unknown optimization level."); } // Set the include paths foreach (var directory in arguments.IncludeDirectories) { AddFlagValueWithQuotes(commandArguments, Compiler_ArgumentParameter_Include, directory.ToString()); } // Set the preprocessor definitions foreach (var definition in arguments.PreprocessorDefinitions) { AddFlagValue(commandArguments, Compiler_ArgumentParameter_PreprocessorDefine, definition); } // Ignore Standard Include Paths to prevent pulling in accidental headers AddFlag(commandArguments, Compiler_ArgumentFlag_IgnoreStandardIncludePaths); // Enable basic runtime checks AddFlag(commandArguments, Compiler_ArgumentFlag_RuntimeChecks); // Enable c++ exceptions AddFlag(commandArguments, "EHsc"); // Enable multithreaded runtime static linked if (arguments.GenerateSourceDebugInfo) { AddFlag(commandArguments, Compiler_ArgumentFlag_Runtime_MultithreadedStatic_Debug); } else { AddFlag(commandArguments, Compiler_ArgumentFlag_Runtime_MultithreadedStatic_Release); } // Add the module references as input foreach (var moduleFile in arguments.IncludeModules) { AddFlag(commandArguments, "reference"); AddValueWithQuotes(commandArguments, moduleFile.ToString()); } // TODO: For now we allow exports to be large AddFlag(commandArguments, "bigobj"); // Only run preprocessor, compile and assemble AddFlag(commandArguments, Compiler_ArgumentFlag_CompileOnly); return(commandArguments); }