Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        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);
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        /// <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);
                }
            }
        }
Exemple #12
0
        /// <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);
        }
Exemple #13
0
        /// <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);
        }
Exemple #14
0
        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);
        }
Exemple #15
0
        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);
        }
Exemple #16
0
        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);
        }