/// <summary> /// Returns the configuration from the referenced-project with the name that best /// matches the name passed in. /// Returns null if no configurations are found . /// </summary> private ProjectConfigurationInfo_CSharp findEquivalentConfiguration(string configurationName, ProjectInfo_CSharp referencedProject) { ProjectConfigurationInfo_CSharp result = null; int nearestDistance = -1; // To find the best match, we look at the 'levenshtein distance' between the // configuration names from the project and the name we are looking for. The // one with the smallest distance is the best match. // // The idea here is that we may not be matching exactly, but we still want // to find a good match. For example, our configuration may be called 'Debug' // and the best match may be called 'Debug Any CPU'. // // This is a bit 'fuzzy' but it should be reasonably good. If there is an // exac match, it will choose it. foreach (ProjectConfigurationInfo_CSharp configurationInfo in referencedProject.getConfigurationInfos()) { int distance = Utils.levenshteinDistance(configurationName, configurationInfo.Name); if (distance < nearestDistance || nearestDistance == -1) { // This configuration is the best match so far... result = configurationInfo; nearestDistance = distance; } } return(result); }
/// <summary> /// Gets the collection of files to copy to the output folder. /// </summary><remarks> /// These files include: /// - Files from the current project with the CopyToOutputFolder flag set. /// - Referenced assemblies with the CopyLocal flag set. /// - Files and references from other projects that we have references to. /// </remarks> public List <FileInfo> getFilesToCopyToOutputFolder() { // The collection of files from this project / configuration... List <FileInfo> results = m_filesToCopyToOutputFolder.ToList(); // We add the list of files from other projects that // we have references to... foreach (ReferenceInfo referenceInfo in m_referenceInfos) { if (referenceInfo.ReferenceType != ReferenceInfo.ReferenceTypeEnum.PROJECT_REFERENCE) { continue; } // We've got a project-reference, so we find the files // that it needs to copy... ProjectConfigurationInfo_CSharp referencedConfiguration = referenceInfo.ConfigurationInfo; List <FileInfo> filesFromReferencedConfiguration = referencedConfiguration.getFilesToCopyToOutputFolder(); // We add them to the list for this configuration, first converting // the paths to be relative to our project's root folder... foreach (FileInfo fileInfo in filesFromReferencedConfiguration) { FileInfo infoWithRelativePath = fileInfo.clone(); infoWithRelativePath.RelativePath = Utils.makeRelativePath(ParentProjectInfo.RootFolderAbsolute, fileInfo.AbsolutePath); results.Add(infoWithRelativePath); } } return(results); }
/// <summary> /// Sets up a 'project reference' to the project passed in. /// (See heading comment notes, and comments in setupReferences() above.) /// </summary> private void setupProjectReference(ReferenceInfo referenceInfo, ProjectInfo_CSharp referencedProject) { // For each configuration in this project, we find the equivalent // configuration in the referenced-project, and set up references // to its output folder... foreach (ProjectConfigurationInfo_CSharp configurationInfo in m_configurationInfos) { // We find the equivalent configuration from the referenced project... ProjectConfigurationInfo_CSharp referencedConfiguration = findEquivalentConfiguration(configurationInfo.Name, referencedProject); if (referencedConfiguration == null) { // The project has no equivalent configuration. (It probably // doesn't have any configurations at all.) continue; } // We find the absolute and relative path to the output of this // configuration... string absolutePath = referencedProject.RootFolderAbsolute + "/" + referencedConfiguration.OutputFolder + "/" + referencedProject.OutputFileName; absolutePath = Path.GetFullPath(absolutePath); string relativePath = Utils.makeRelativePath(m_rootFolderAbsolute, absolutePath); // We store the reference-info for each configuration... ReferenceInfo info = new ReferenceInfo(); info.CopyLocal = referenceInfo.CopyLocal; info.AbsolutePath = absolutePath; info.RelativePath = relativePath; info.ReferenceType = ReferenceInfo.ReferenceTypeEnum.PROJECT_REFERENCE; info.ConfigurationInfo = referencedConfiguration; configurationInfo.addReference(info); } }
/// <summary> /// Adds a cofiguration to the collection for this project. /// </summary> public void addConfigurationInfo(ProjectConfigurationInfo_CSharp configurationInfo) { m_configurationInfos.Add(configurationInfo); }
/// <summary> /// Parses on configuration. /// </summary> private void parseConfiguration(EnvDTE.Configuration dteConfiguration) { // We create a new configuration-info object and fill it in... ProjectConfigurationInfo_CSharp configurationInfo = new ProjectConfigurationInfo_CSharp(); configurationInfo.ParentProjectInfo = m_projectInfo; configurationInfo.Name = Utils.call(() => dteConfiguration.ConfigurationName); // We parse the configuration's properties, and set configuration // seetings from them... EnvDTE.Properties dteProperties = Utils.call(() => (dteConfiguration.Properties)); Dictionary<string, object> properties = getProperties(dteProperties); // Whether to optimize... configurationInfo.Optimize = getBoolProperty(properties, "Optimize"); // The output path and intermediate path... configurationInfo.OutputFolder = getStringProperty(properties, "OutputPath"); configurationInfo.IntermediateFolder = getStringProperty(properties, "IntermediatePath"); // Whether to treat warnings as errors... configurationInfo.ThreatWarningsAsErrors = getBoolProperty(properties, "TreatWarningsAsErrors"); // Defined constants (DEBUG, TRACE etc)... string definedConstants = getStringProperty(properties, "DefineConstants"); foreach (string definedConstant in Utils.split(definedConstants, ';')) { configurationInfo.addDefinedConstant(definedConstant); } // Whether to add debug symbols to the output... configurationInfo.Debug = getBoolProperty(properties, "DebugSymbols"); // Comma separated list of warnings to ignore... string warningsToIgnore = getStringProperty(properties, "NoWarn"); foreach (string warningToIgnore in Utils.split(warningsToIgnore, ',')) { configurationInfo.addWarningToIgnore(warningToIgnore); } // DebugInfo, e.g. "full"... configurationInfo.DebugInfo = getStringProperty(properties, "DebugInfo"); // File alignment... configurationInfo.FileAlignment = getIntProperty(properties, "FileAlignment"); // Warning level... configurationInfo.WarningLevel = getIntProperty(properties, "WarningLevel"); // We add the configuration-info to the project-info... m_projectInfo.addConfigurationInfo(configurationInfo); }
/// <summary> /// Returns the variable name for this data for this configuration. /// </summary> private string getReferencesVariableName(ProjectConfigurationInfo_CSharp configurationInfo) { return configurationInfo.Name + "_REFERENCES"; }
/// <summary> /// Returns the variable name for this data for this configuration. /// </summary> private string getOutputFolderVariableName(ProjectConfigurationInfo_CSharp configurationInfo) { return configurationInfo.Name + "_OUTPUT_FOLDER"; }
/// <summary> /// Returns the output folder for the configuration passed in. /// </summary> private string getOutputFolder(ProjectConfigurationInfo_CSharp configurationInfo) { string prefix = MakeItSoConfig.Instance.getProjectConfig(m_projectInfo.Name).CSharpFolderPrefix; return Utils.addPrefixToFolderPath(configurationInfo.OutputFolder, prefix); }
/// <summary> /// Returns the variable name for this data for this configuration. /// </summary> private string getFlagsVariableName(ProjectConfigurationInfo_CSharp configurationInfo) { return configurationInfo.Name + "_FLAGS"; }
/// <summary> /// Creates compiler flags for the configuration passed in. /// </summary> private void createConfigurationFlagsVariable(ProjectConfigurationInfo_CSharp configurationInfo) { string variableName = getFlagsVariableName(configurationInfo); string flags = ""; // Optimize... if (configurationInfo.Optimize == true) { flags += "-optimize+ "; } else { flags += "-optimize- "; } // Treat warnings as errors... if (configurationInfo.ThreatWarningsAsErrors == true) { flags += "-warnaserror+ "; } // Defined constants... foreach (string definedConstant in configurationInfo.getDefinedConstants()) { flags += ("-define:" + definedConstant + " "); } // Debug build... if (configurationInfo.Debug == true) { flags += "-debug+ "; } // Type of debug info... if (configurationInfo.DebugInfo != "") { flags += ("-debug:" + configurationInfo.DebugInfo + " "); } // Warnings to ignore... List<string> warningsToIgnore = configurationInfo.getWarningsToIgnore(); if (warningsToIgnore.Count > 0) { flags += "-nowarn:"; foreach (string warningToIgnore in warningsToIgnore) { flags += (warningToIgnore + ","); } flags = flags.TrimEnd(',') + " "; } // File alignment... flags += ("-filealign:" + configurationInfo.FileAlignment + " "); // Warning level... flags += ("-warn:" + configurationInfo.WarningLevel + " "); // We add the mono .net packages (if we are not in a cygwin build)... if (MakeItSoConfig.Instance.IsCygwinBuild == false) { flags += "-pkg:dotnet "; } // We add the flags to the makefile... m_file.WriteLine(variableName + " = " + flags); }