Example #1
0
        private IEnumerable <IDictionary <string, string> > GetProjectEntries(Builder builder, Project project, Project.Configuration config)
        {
            var context        = new CompileCommandGenerationContext(builder, project, config);
            var resolverParams = new[] {
                new VariableAssignment("project", context.Project),
                new VariableAssignment("target", context.Configuration.Target),
                new VariableAssignment("conf", context.Configuration)
            };

            context.EnvironmentVariableResolver = PlatformRegistry.Get <IPlatformDescriptor>(config.Platform).GetPlatformEnvironmentResolver(resolverParams);

            var factory = new CompileCommandFactory(context);

            var database = project.GetSourceFilesForConfigurations(new[] { config })
                           .Except(config.ResolvedSourceFilesBuildExclude)
                           .Where(f => project.SourceFilesCPPExtensions.Contains(Path.GetExtension(f)))
                           .Select(factory.CreateCompileCommand);

            foreach (var cc in database)
            {
                CompileCommandGenerated?.Invoke(context, cc);
                yield return(new Dictionary <string, string>
                {
                    { "directory", cc.Directory },
                    { "command", cc.Command },
                    { "file", cc.File },
                });
            }
        }
Example #2
0
        public CompileCommandFactory(CompileCommandGenerationContext context)
        {
            var isClang     = context.Configuration.Platform.IsUsingClang();
            var isMicrosoft = context.Configuration.Platform.IsMicrosoft();

            _compiler         = isClang ? "clang.exe" : "clang-cl.exe";
            _config           = context.Configuration;
            _outputExtension  = isMicrosoft ? ".obj" : ".o";
            _outputDirectory  = _config.IntermediatePath;
            _projectDirectory = context.ProjectDirectoryCapitalized;
            _flags            = isClang ? s_clangFlags : s_vcFlags;

            s_optionGenerator.GenerateOptions(context, ProjectOptionGenerationLevel.Compiler);
            var argsList = new List <string>();

            argsList.Add(isClang ? "-c" : "/c");

            // Precomp arguments flags are actually written by the bff generator (see bff.template.cs)
            // Therefore, the CommandLineOptions entries only contain the pch name and file.
            if (_config.PrecompSource != null)
            {
                _precompFile = Path.Combine(_projectDirectory, context.Options[PrecompFileKey]);

                string name;
                if (_flags.ContainsKey(CompilerFlags.PrecompPath))
                {
                    argsList.Add(string.Format(_flags[CompilerFlags.PrecompPath], _precompFile));
                    name = context.Options[PrecompNameKey];
                }
                else
                {
                    name = _precompFile;
                }

                _createPrecompArgument = string.Format(_flags[CompilerFlags.CreatePrecomp], name);
                _usePrecompArgument    = string.Format(_flags[CompilerFlags.UsePrecomp], name);
            }

            // AdditionalCompilerOptions are referenced from Options in the bff template.
            context.CommandLineOptions.Add(AdditionalOptionsKey, context.Options[AdditionalOptionsKey]);

            FillIncludeDirectoriesOptions(context);

            var validOptions = context.CommandLineOptions
                               .Where(IsValidOption)
                               .ToDictionary(kvp => kvp.Key, FlattenMultilineArgument);

            if (isMicrosoft)
            {
                // Required to avoid errors in VC headers.
                var flag  = isClang ? "-D" : "/D";
                var value = validOptions.ContainsKey("ExceptionHandling") ? 1 : 0;
                argsList.Add($"{flag}_HAS_EXCEPTIONS={value}");
            }

            argsList.AddRange(validOptions.Values);

            _arguments = string.Join(" ", argsList);
        }
Example #3
0
        internal static string CmdLineConvertIncludePathsFunc(CompileCommandGenerationContext context, string include, string prefix)
        {
            // if the include is below the global root, we compute the relative path,
            // otherwise it's probably a system include for which we keep the full path
            string resolvedInclude = context.EnvironmentVariableResolver.Resolve(include);

            if (resolvedInclude.StartsWith(context.Project.RootPath, StringComparison.OrdinalIgnoreCase))
            {
                resolvedInclude = Util.PathGetRelative(context.ProjectDirectory, resolvedInclude, true);
            }
            return($@"{prefix}""{resolvedInclude}""");
        }
Example #4
0
        private void SelectPreprocessorDefinitions(CompileCommandGenerationContext context, string platformDefineSwitch)
        {
            var defines = new Strings();

            defines.AddRange(context.Options.ExplicitDefines);
            defines.AddRange(context.Configuration.Defines);

            foreach (string define in defines.SortedValues)
            {
                if (!string.IsNullOrWhiteSpace(define))
                {
                    _arguments.Add(string.Format(@"{0}{1}{2}{1}", platformDefineSwitch, Util.DoubleQuotes, define.Replace(Util.DoubleQuotes, Util.EscapedDoubleQuotes)));
                }
            }
        }
Example #5
0
        private void FillIncludeDirectoriesOptions(CompileCommandGenerationContext context)
        {
            // TODO: really not ideal, refactor and move the properties we need from it someplace else
            var platformVcxproj = PlatformRegistry.Query <IPlatformVcxproj>(context.Configuration.Platform);

            var includePaths         = new OrderableStrings(platformVcxproj.GetIncludePaths(context));
            var resourceIncludePaths = new OrderableStrings(platformVcxproj.GetResourceIncludePaths(context));

            context.CommandLineOptions["AdditionalIncludeDirectories"]         = FileGeneratorUtilities.RemoveLineTag;
            context.CommandLineOptions["AdditionalResourceIncludeDirectories"] = FileGeneratorUtilities.RemoveLineTag;
            context.CommandLineOptions["AdditionalUsingDirectories"]           = FileGeneratorUtilities.RemoveLineTag;

            var platformDescriptor = PlatformRegistry.Get <IPlatformDescriptor>(context.Configuration.Platform);

            string defaultCmdLineIncludePrefix = _flags[CompilerFlags.IncludePath];

            // Fill include dirs
            var dirs = new List <string>();

            var platformIncludePaths         = platformVcxproj.GetPlatformIncludePathsWithPrefix(context);
            var platformIncludePathsPrefixed = platformIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p.Path, p.CmdLinePrefix)).ToList();

            dirs.AddRange(platformIncludePathsPrefixed);

            // TODO: move back up, just below the creation of the dirs list
            dirs.AddRange(includePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p, defaultCmdLineIncludePrefix)));

            if (dirs.Any())
            {
                context.CommandLineOptions["AdditionalIncludeDirectories"] = string.Join(" ", dirs);
                _arguments.AddRange(dirs);
            }

            // Fill resource include dirs
            var resourceDirs = new List <string>();

            resourceDirs.AddRange(resourceIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p, defaultCmdLineIncludePrefix)));

            if (Options.GetObject <Options.Vc.General.PlatformToolset>(context.Configuration).IsLLVMToolchain() &&
                Options.GetObject <Options.Vc.LLVM.UseClangCl>(context.Configuration) == Options.Vc.LLVM.UseClangCl.Enable)
            {
                // with LLVM as toolchain, we are still using the default resource compiler, so we need the default include prefix
                // TODO: this is not great, ideally we would need the prefix to be per "compiler", and a platform can have many
                var platformIncludePathsDefaultPrefix = platformIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p.Path, defaultCmdLineIncludePrefix));
                resourceDirs.AddRange(platformIncludePathsDefaultPrefix);
            }
            else
            {
                resourceDirs.AddRange(platformIncludePathsPrefixed);
            }

            if (resourceDirs.Any())
            {
                context.CommandLineOptions["AdditionalResourceIncludeDirectories"] = string.Join(" ", resourceDirs);
                _arguments.AddRange(resourceDirs);
            }

            // Fill using dirs
            Strings additionalUsingDirectories = Options.GetStrings <Options.Vc.Compiler.AdditionalUsingDirectories>(context.Configuration);

            additionalUsingDirectories.AddRange(context.Configuration.AdditionalUsingDirectories);
            additionalUsingDirectories.AddRange(platformVcxproj.GetCxUsingPath(context));
            if (additionalUsingDirectories.Any())
            {
                var cmdAdditionalUsingDirectories = additionalUsingDirectories.Select(p => CmdLineConvertIncludePathsFunc(context, p, "/AI"));
                context.CommandLineOptions["AdditionalUsingDirectories"] = string.Join(" ", cmdAdditionalUsingDirectories);
                _arguments.AddRange(cmdAdditionalUsingDirectories);
            }
        }