// Makes a Vcxproj rule from a BFFOnly rule. protected MocSourceAndTargetFile(MocSourceAndTargetFile reference) { Filter = ProjectFilter.ExcludeBFF; Executable = reference.Executable; // Input is the intermediate file. KeyInput = reference.IntermediateFile; // We also depend on the actual input file. AdditionalInputs.Add(reference.KeyInput); Output = reference.Output; Description = reference.Description; SourceFile = reference.SourceFile; IntermediateFile = reference.IntermediateFile; IsCPPFile = reference.IsCPPFile; IncludePaths.AddRange(reference.IncludePaths); ForceIncludes.AddRange(reference.ForceIncludes); CombinedDefines = reference.CombinedDefines; }
// Call this from Project::ExcludeOutputFiles() to find the list of files we need to moc. // This is after resolving files, but before filtering them, and before they get mapped to // configurations, so this is a good spot to add additional files. public void GenerateListOfFilesToMoc(Project project, string QTExecFolder) { string mocExe = QTExecFolder + "moc.exe"; string rccExe = QTExecFolder + "rcc.exe"; string uicExe = QTExecFolder + "uic.exe"; // Filter all the files by the filters we've already specified, so we don't moc a file that's excluded from the solution. RegexOptions filterOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase; List <Regex> filters = project.SourceFilesExcludeRegex.Select(filter => new Regex(filter, filterOptions)).ToList(); filters.AddRange(ExcludeMocRegex.Select(filter => new Regex(filter, filterOptions))); var preFilteredFiles = project.ResolvedSourceFiles.Where(file => !filters.Any(filter => filter.IsMatch(file)) && !project.Configurations.Any(conf => FileIsPrecompiledHeader(file, conf))).ToList(); // Async load all the source files and look for Q_OBJECT that we want to keep. var answerSetTask = Task.WhenAll(preFilteredFiles.Select(async file => new { file = file, runMoc = await FileContainsQObject(file) })); // Compile a list of qrc and ui files. Strings qrcFiles = new Strings(preFilteredFiles.Where(file => file.EndsWith(".qrc", StringComparison.InvariantCultureIgnoreCase))); Strings uiFiles = new Strings(preFilteredFiles.Where(file => file.EndsWith(".ui", StringComparison.InvariantCultureIgnoreCase))); // Wait for the moc files. answerSetTask.Wait(); var filterPass = answerSetTask.Result; // These are the files we want to moc. Strings FilteredResolvedSourceFiles = new Strings(filterPass.Where(result => result.runMoc).Select(result => result.file)); // Compile a list of files where we don't want to compile the moc output. List <Regex> filesToExclude = ExcludeMocFromCompileRegex.Select(filter => new Regex(filter, filterOptions)).ToList(); foreach (ProjConfiguration conf in project.Configurations) { // Setup exclusions. string QTMocOutputBase = Path.GetDirectoryName(conf.IntermediatePath); string targetName = conf.Target.Name; string outputFolder = QTMocOutputBase + @"\qt\" + targetName.ToLowerInvariant() + @"\"; // We make the current output folder included directly so you can use the same #include directive to get the correct cpp file. conf.IncludePrivatePaths.Add(outputFolder); // Also include the project file folder, since the moc tool generates includes from this location. conf.IncludePrivatePaths.Add(conf.ProjectPath); // We need to exclude the generation files folder from the build on all targets except our own. string rootFolderForRegex = Util.GetCapitalizedPath(conf.ProjectPath); string outputRegex = Util.PathGetRelative(rootFolderForRegex, outputFolder); outputRegex = outputRegex.Replace("..\\", "").Replace("\\", "\\\\") + @"\\"; foreach (ProjConfiguration confToExclude in project.Configurations) { if (confToExclude == conf || confToExclude.ProjectFullFileNameWithExtension != conf.ProjectFullFileNameWithExtension) { continue; } confToExclude.SourceFilesBuildExcludeRegex.Add(outputRegex); } // Build a list of all files to moc in this configuration. var mocTargets = new List <MocSourceAndTargetFile>(); foreach (string file in FilteredResolvedSourceFiles) { var target = new MocSourceAndTargetFile(targetName, mocExe, outputFolder, outputFolder, file); if (filesToExclude.Any(filter => filter.IsMatch(file))) { target.TargetFileNotCompiled = true; } mocTargets.Add(target); if (target.IsCPPFile) { mocTargets.Add(new MocVcxprojBuildStep(target)); } } if (mocTargets.Count > 0) { MocTargetsPerConfiguration.Add(conf, mocTargets); } if (qrcFiles.Count > 0) { RccTargetsPerConfiguration.Add(conf, qrcFiles.Select(file => new RccSourceAndTargetFile(targetName, rccExe, outputFolder, file)).ToList()); } if (uiFiles.Count > 0) { UicTargetsPerConfiguration.Add(conf, uiFiles.Select(file => new UicSourceAndTargetFile(targetName, uicExe, outputFolder, file)).ToList()); } } // Add all the new source files to the project file. foreach (var values in MocTargetsPerConfiguration) { foreach (var target in values.Value) { // We only need to include outputs that have build steps. For source files, that's the intermediate file, for // header files, that's the target file, if it wasn't excluded. values.Key.CustomFileBuildSteps.Add(target); if (target.IsCPPFile) { project.ResolvedSourceFiles.Add(target.IntermediateFile); } else if (!target.TargetFileNotCompiled) { project.ResolvedSourceFiles.Add(target.Output); } } } foreach (var values in RccTargetsPerConfiguration) { foreach (var target in values.Value) { values.Key.CustomFileBuildSteps.Add(target); project.ResolvedSourceFiles.Add(target.Output); } } foreach (var values in UicTargetsPerConfiguration) { foreach (var target in values.Value) { values.Key.CustomFileBuildSteps.Add(target); // uic files generate header files - we don't need to run a build step on them, so don't include them in the vcxproj listing. //project.ResolvedSourceFiles.Add(target.Output); } } }
public MocVcxprojBuildStep(MocSourceAndTargetFile reference) : base(reference) { }