/// <summary> /// Adds the custom build rule info (for one file) to the configuration /// whose name is passed in. /// </summary> public void addCustomBuildRuleInfo(CustomBuildRuleInfo_CPP ruleInfo, string configurationName) { ProjectConfigurationInfo_CPP configurationInfo = getConfigurationInfo(configurationName); if (configurationInfo != null) { configurationInfo.addCustomBuildRuleInfo(ruleInfo); } }
/// <summary> /// Parses one configuration for a custom build rule. /// </summary> private void parseCustomBuildRule_Configuration(VCFileConfiguration configuration, string relativePath) { // We find the custom build rule for this configuration (if there is one)... VCCustomBuildRule rule = Utils.call(() => (configuration.Tool as VCCustomBuildRule)); if (rule == null) { return; } // We will store info about this rule in a CustomBuildRuleInfo_CPP object... CustomBuildRuleInfo_CPP ruleInfo = new CustomBuildRuleInfo_CPP(); ruleInfo.RelativePathToFile = relativePath; // There is a custom build rule, so we parse it... ruleInfo.RuleName = Utils.call(() => (rule.Name)); string commandLine = Utils.call(() => (rule.CommandLine)); string expandedCommandLine = Utils.call(() => (configuration.Evaluate(commandLine))); // We find the collection of output files generated by the rule... string outputs = Utils.call(() => (rule.Outputs)); string expandedOutputs = Utils.call(() => (configuration.Evaluate(outputs))); // The command-line may contain references to custom properties for // the rule. These will be in square brackets,like [property]. We find // these and replace the property markers in the command-line... Dictionary<string, string> properties = getCustomBuildRuleProperties(rule); foreach (KeyValuePair<string, string> property in properties) { // We replace values in the command line, and in the output files... string tokenToReplace = "[" + property.Key + "]"; expandedCommandLine = expandedCommandLine.Replace(tokenToReplace, property.Value); expandedOutputs = expandedOutputs.Replace(tokenToReplace, property.Value); } // We split the command-line to find the executable and the parameters... List<string> splitCommandLine = Utils.split(expandedCommandLine, ' '); // The executable... if (splitCommandLine.Count >= 1) { string ruleExecutable = splitCommandLine[0]; string relativePathToExecutable = Utils.makeRelativePath(m_projectInfo.RootFolderAbsolute, ruleExecutable); ruleInfo.RelativePathToExecutable = relativePathToExecutable; } // The parameters... for (int j = 1; j < splitCommandLine.Count; ++j) { string parameter = splitCommandLine[j]; // Many parameters will be path names. We cnvert these // to be relative to the project root (and in Linux format). // Non-path parameters should be unaffected... parameter = Utils.makeRelativePath(m_projectInfo.RootFolderAbsolute, parameter); ruleInfo.addParameter(parameter); } // We store the info in the configuration... m_projectInfo.addCustomBuildRuleInfo(ruleInfo, configuration.Name); }
/// <summary> /// Gets the target name for the configuration and rule passed in. /// </summary> private string getCustomRuleTargetName(ProjectConfigurationInfo_CPP configurationInfo, CustomBuildRuleInfo_CPP ruleInfo) { // The target-name has this form: // [configuration]_CustomBuildRule_[rule-name]_[file-name] // For example: // Release_CustomBuildRule_Splitter_TextUtils.code string fileName = Path.GetFileName(ruleInfo.RelativePathToFile); return String.Format("{0}_CustomBuildRule_{1}_{2}", configurationInfo.Name, ruleInfo.RuleName, fileName); }
/// <summary> /// Creates a target for one custom build rule. /// </summary> private void createCustomBuildRuleTarget(ProjectConfigurationInfo_CPP configuration, CustomBuildRuleInfo_CPP ruleInfo) { // The rule might be built by one of the other projects in this solution. // If so, we need to change the folder name to the adjusted output folder // name we generate. (This means that we need to know if the project that // generates it is a C++ or C# project.) string executablePath = Path.Combine(configuration.ParentProjectInfo.RootFolderAbsolute, ruleInfo.RelativePathToExecutable); ProjectInfo.ProjectTypeEnum projectType = m_projectInfo.ParentSolution.isOutputObject(executablePath); string folderPrefix = ""; switch(projectType) { case ProjectInfo.ProjectTypeEnum.CPP_EXECUTABLE: folderPrefix = m_projectConfig.CPPFolderPrefix; break; case ProjectInfo.ProjectTypeEnum.CSHARP_EXECUTABLE: folderPrefix = m_projectConfig.CSharpFolderPrefix; break; } // We add the target to the makefile... m_file.WriteLine("# Custom build rule for " + ruleInfo.RelativePathToFile); string targetName = getCustomRuleTargetName(configuration, ruleInfo); m_file.WriteLine(".PHONY: " + targetName); m_file.WriteLine(targetName + ":"); m_file.WriteLine("\t" + ruleInfo.getCommandLine(folderPrefix)); m_file.WriteLine(""); }
/// <summary> /// Adds info about a custom build rule (for one file) to this /// configuration. /// </summary> public void addCustomBuildRuleInfo(CustomBuildRuleInfo_CPP ruleInfo) { m_customBuildRuleInfos.Add(ruleInfo); }