/// <summary>
        /// Finds the configuration info for the name passed in. It will try to
        /// find a close match if it cannot find an exact macth.
        /// Return null if no match can be found.
        /// </summary>
        private ProjectConfigurationInfo_CPP getConfigurationInfo(string configurationName)
        {
            // Have we already worked out which configuration is needed for this name?
            if (m_mapNamesToConfigurations.ContainsKey(configurationName) == true)
            {
                return(m_mapNamesToConfigurations[configurationName]);
            }

            // We look for the closest match for the name passed in...
            ProjectConfigurationInfo_CPP result = null;
            int closestDistance = -1;

            foreach (ProjectConfigurationInfo_CPP configurationInfo in m_configurationInfos)
            {
                int distance = Utils.levenshteinDistance(configurationName, configurationInfo.Name);
                if (distance < closestDistance
                    ||
                    closestDistance == -1)
                {
                    result          = configurationInfo;
                    closestDistance = distance;
                }
            }
            m_mapNamesToConfigurations.Add(configurationName, result);
            return(result);
        }
        /// <summary>
        /// Updates include paths from config settings.
        /// </summary>
        private void updateIncludePaths(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            string projectRootFolder = configuration.ParentProjectInfo.RootFolderAbsolute;

            // We check if any include paths should be removed...
            List <string> includePaths = new List <string>(configuration.getIncludePaths());

            foreach (string includePath in includePaths)
            {
                string fullPath = Path.Combine(projectRootFolder, includePath);
                if (projectSettings.includePathShouldBeRemoved(fullPath) == true)
                {
                    configuration.removeIncludePath(includePath);
                }
            }

            // We add any new paths...
            List <string> pathsToAdd = projectSettings.getConfiguration(configuration.Name).getIncludePathsToAdd().ToList();

            foreach (string pathToAdd in pathsToAdd)
            {
                string relativePath = Utils.makeRelativePath(projectRootFolder, pathToAdd);
                configuration.addIncludePath(relativePath);
            }
        }
        /// <summary>
        /// Updates preprocessor definitions from config settings.
        /// </summary>
        private void updatePreprocessorDefinitions(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            // By default we replace WIN32 with GCC_BUILD...
            configuration.removePreprocessorDefinition("WIN32");
            configuration.addPreprocessorDefinition("GCC_BUILD");

            // We check if any definitions should be removed...
            List <string> definitions = new List <string>(configuration.getPreprocessorDefinitions());

            foreach (string definition in definitions)
            {
                if (projectSettings.preprocessorDefinitionShouldBeRemoved(definition) == true)
                {
                    configuration.removePreprocessorDefinition(definition);
                }
            }

            // We add any new definitions...
            List <string> definitionsToAdd = projectSettings.getConfiguration(configuration.Name).getPreprocessorDefinitionsToAdd();

            foreach (string definition in definitionsToAdd)
            {
                configuration.addPreprocessorDefinition(definition);
            }
        }
        /// <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>
        /// Updates library paths from config settings.
        /// </summary>
        private void updateLibraryPaths(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            ProjectInfo projectInfo       = configuration.ParentProjectInfo;
            string      projectRootFolder = projectInfo.RootFolderAbsolute;

            // We check if any library paths should be removed...
            List <string> libraryPaths = new List <string>(configuration.getLibraryPaths());

            foreach (string libraryPath in libraryPaths)
            {
                // We remove the library (and re-add it if we need to, but
                // with the name changed)...
                configuration.removeLibraryPath(libraryPath);

                // We find the full path, and add it if we are not
                // configured to remove it...
                string fullPath = Path.Combine(projectRootFolder, libraryPath);
                if (projectSettings.libraryPathShouldBeRemoved(fullPath) == false)
                {
                    string prefix  = MakeItSoConfig.Instance.getProjectConfig(projectInfo.Name).CPPFolderPrefix;
                    string gccPath = Utils.addPrefixToFolderPath(libraryPath, prefix);
                    configuration.addLibraryPath(gccPath);
                }
            }

            // We add any new paths...
            List <ProjectPath> pathsToAdd = projectSettings.getConfiguration(configuration.Name).getLibraryPathsToAdd();

            foreach (ProjectPath pathToAdd in pathsToAdd)
            {
                string relativePath;
                if (!pathToAdd.Absolute)
                {
                    relativePath = Utils.makeRelativePath(projectRootFolder, pathToAdd.Path);
                }
                else
                {
                    relativePath = pathToAdd.Path;
                }

                configuration.addLibraryPath(relativePath);
            }
        }
        /// <summary>
        /// Updates compiler flags from the config settings.
        /// </summary>
        private void updateCompilerFlags(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            // We check if any definitions should be removed...
            List<string> flags = new List<string>(configuration.getCompilerFlags());
            foreach (string flag in flags)
            {
                if (projectSettings.compilerFlagShouldBeRemoved(flag) == true)
                {
                    configuration.removeCompilerFlag(flag);
                }
            }

            // We add any new definitions...
            List<string> flagsToAdd = projectSettings.getConfiguration(configuration.Name).getCompilerFlagsToAdd().ToList();
            foreach (string flag in flagsToAdd)
            {
                configuration.addCompilerFlag(flag);
            }
        }
        /// <summary>
        /// Updates compiler flags from the config settings.
        /// </summary>
        private void updateCompilerFlags(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            // We check if any definitions should be removed...
            List <string> flags = new List <string>(configuration.getCompilerFlags());

            foreach (string flag in flags)
            {
                if (projectSettings.compilerFlagShouldBeRemoved(flag) == true)
                {
                    configuration.removeCompilerFlag(flag);
                }
            }

            // We add any new definitions...
            List <string> flagsToAdd = projectSettings.getConfiguration(configuration.Name).getCompilerFlagsToAdd();

            foreach (string flag in flagsToAdd)
            {
                configuration.addCompilerFlag(flag);
            }
        }
        /// <summary>
        /// Updates libraries from config settings.
        /// </summary>
        private void updateLibraries(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            // We check if any of the libraries in the configuration should be removed...
            HashSet <string> libraries = new HashSet <string>(configuration.getLibraryRawNames());

            foreach (string library in libraries)
            {
                if (projectSettings.libraryShouldBeRemoved(library) == true)
                {
                    configuration.removeLibraryRawName(library);
                }
            }

            // We add any that need adding...
            List <string> librariesToAdd = projectSettings.getConfiguration(configuration.Name).getLibrariesToAdd();

            foreach (string library in librariesToAdd)
            {
                string rawName = Utils.convertLinuxLibraryNameToRawName(library);
                configuration.addLibraryRawName(rawName);
            }
        }
Exemple #9
0
        /// <summary>
        /// We parse the librarian settings, ie link options for libraries.
        /// </summary>
        private void parseConfiguration_LibrarianSettings(VCConfiguration vcConfiguration, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // We get the librarian 'tool'...
            IVCCollection tools = Utils.call(() => (vcConfiguration.Tools as IVCCollection));
            VCLibrarianTool librarianTool = Utils.call(() => (tools.Item("VCLibrarianTool") as VCLibrarianTool));
            if (librarianTool == null)
            {
                // Not all projects have a librarian tool...
                return;
            }

            // We find if this library is set to link together other libraries it depends on...
            // (We are assuming that all configurations of the project have the same link-library-dependencies setting.)
            m_projectInfo.LinkLibraryDependencies = Utils.call(() => (librarianTool.LinkLibraryDependencies));

            parseLibrarianSettings_LibraryPath(vcConfiguration, librarianTool, configurationInfo);
            parseLibrarianSettings_Libraries(vcConfiguration, librarianTool, configurationInfo);
        }
Exemple #10
0
        /// <summary>
        /// Parses the configuration (e.g. Debug, Release) passed in.
        /// </summary>
        private void parseConfiguration(VCConfiguration vcConfiguration)
        {
            ProjectConfigurationInfo_CPP configurationInfo = new ProjectConfigurationInfo_CPP();
            configurationInfo.ParentProjectInfo = m_projectInfo;

            // The configuration name...
            configurationInfo.Name = Utils.call(() => (vcConfiguration.ConfigurationName));

            // The project type.
            // Note: we are assuming that all the configurations for the project build the
            //       same type of target.
            m_projectInfo.ProjectType = parseConfiguration_Type(vcConfiguration);

            // We get the intermediates and output folder, and the Target Name.
            configurationInfo.IntermediateFolder = parseConfiguration_Folder(vcConfiguration, () => (vcConfiguration.IntermediateDirectory));
            configurationInfo.OutputFolder = parseConfiguration_Folder(vcConfiguration, () => (vcConfiguration.OutputDirectory));
            configurationInfo.TargetName = parseConfiguration_TargetName(vcConfiguration);

            // We get compiler settings, such as the include path and
            // preprocessor definitions...
            parseConfiguration_CompilerSettings(vcConfiguration, configurationInfo);

            // We get linker settings, such as any libs to link and the library path...
            parseConfiguration_LinkerSettings(vcConfiguration, configurationInfo);

            // We parse librarian settings (how libraries are linked)...
            parseConfiguration_LibrarianSettings(vcConfiguration, configurationInfo);

            // We see if there are any pre- or post- build events set up for this
            // configuration. The only types of events we know how to deal with are
            // ones that invoke a .cmd file. For these we convert them to invoke
            // a .sh file with the same name.
            parseConfiguration_PreBuildEvent(vcConfiguration, configurationInfo);
            parseConfiguration_PostBuildEvent(vcConfiguration, configurationInfo);

            // We add the configuration to the collection of them for the project...
            m_projectInfo.addConfigurationInfo(configurationInfo);
        }
Exemple #11
0
        /// <summary>
        /// Finds compiler flags.
        /// </summary>
        private void parseCompilerSettings_CompilerFlags(VCConfiguration vcConfiguration, VCCLCompilerTool compilerTool, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // Warning level...
            warningLevelOption warningLevel = Utils.call(() => (compilerTool.WarningLevel));
            switch (warningLevel)
            {
                case warningLevelOption.warningLevel_0:
                    configurationInfo.addCompilerFlag("-w");
                    break;

                case warningLevelOption.warningLevel_4:
                    configurationInfo.addCompilerFlag("-Wall");
                    break;
            }

            // Warnings as errors...
            bool warningsAsErrors = Utils.call(() => (compilerTool.WarnAsError));
            if (warningsAsErrors == true)
            {
                configurationInfo.addCompilerFlag("-Werror");
            }

            // Optimization...
            optimizeOption optimization = Utils.call(() => (compilerTool.Optimization));
            switch (optimization)
            {
                case optimizeOption.optimizeDisabled:
                    configurationInfo.addCompilerFlag("-O0");
                    break;

                case optimizeOption.optimizeMinSpace:
                    configurationInfo.addCompilerFlag("-Os");
                    break;

                case optimizeOption.optimizeMaxSpeed:
                    configurationInfo.addCompilerFlag("-O2");
                    break;

                case optimizeOption.optimizeFull:
                    configurationInfo.addCompilerFlag("-O3");
                    break;
            }
        }
        /// <summary>
        /// Updates library paths from config settings.
        /// </summary>
        private void updateLibraryPaths(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            ProjectInfo projectInfo = configuration.ParentProjectInfo;
            string projectRootFolder = projectInfo.RootFolderAbsolute;

            // We check if any library paths should be removed...
            List<string> libraryPaths = new List<string>(configuration.getLibraryPaths());
            foreach (string libraryPath in libraryPaths)
            {
                // We remove the library (and re-add it if we need to, but
                // with the name changed)...
                configuration.removeLibraryPath(libraryPath);

                // We find the full path, and add it if we are not
                // configured to remove it...
                string fullPath = Path.Combine(projectRootFolder, libraryPath);
                if (projectSettings.libraryPathShouldBeRemoved(fullPath) == false)
                {
                    string prefix = MakeItSoConfig.Instance.getProjectConfig(projectInfo.Name).CPPFolderPrefix;
                    string gccPath = Utils.addPrefixToFolderPath(libraryPath, prefix);
                    configuration.addLibraryPath(gccPath);
                }
            }

            // We add any new paths...
            List<string> pathsToAdd = projectSettings.getConfiguration(configuration.Name).getLibraryPathsToAdd().ToList();
            foreach (string pathToAdd in pathsToAdd)
            {
                string relativePath = Utils.makeRelativePath(projectRootFolder, pathToAdd);
                configuration.addLibraryPath(relativePath);
            }
        }
 /// <summary>
 /// Returns the preprocessor-definitions variable name for the configuration passed in.
 /// For example "Debug_Preprocessor_Definitions".
 /// </summary>
 private string getPreprocessorDefinitionsVariableName(ProjectConfigurationInfo_CPP configuration)
 {
     return configuration.Name + "_Preprocessor_Definitions";
 }
 /// <summary>
 /// Adds a configuration to the project.
 /// </summary>
 public void addConfigurationInfo(ProjectConfigurationInfo_CPP configurationInfo)
 {
     m_configurationInfos.Add(configurationInfo);
 }
Exemple #15
0
        /// <summary>
        /// Parses the configuration (e.g. Debug, Release) passed in.
        /// </summary>
        private void parseConfiguration(VCConfiguration vcConfiguration)
        {
            ProjectConfigurationInfo_CPP configurationInfo = new ProjectConfigurationInfo_CPP();
            configurationInfo.ParentProjectInfo = m_projectInfo;

            IVCCollection sheets = Utils.call(() => (vcConfiguration.PropertySheets as IVCCollection));
            int numSheets = Utils.call(() => (sheets.Count));
            for (int i = 1; i <= numSheets; ++i)
            {
                VCPropertySheet sheet = Utils.call(() => (sheets.Item(i) as VCPropertySheet));

                // 1. The thing is that VCPropertySheet and VCConfiguration have more-or-less
                //    identical interfaces. So we should be able to merge them fairly easily.
                //
                // 2. We should try multiple layers of inheritance

                IVCCollection tools = Utils.call(() => (sheet.Tools as IVCCollection));
                VCCLCompilerTool compilerTool = Utils.call(() => (tools.Item("VCCLCompilerTool") as VCCLCompilerTool));

            }

            // The configuration name...
            configurationInfo.Name = Utils.call(() => (vcConfiguration.ConfigurationName));

            // The project type. 
            // Note: we are assuming that all the configurations for the project build the
            //       same type of target. 
            m_projectInfo.ProjectType = parseConfiguration_Type(vcConfiguration);

            // We get the intermediates folder and output folder...
            configurationInfo.IntermediateFolder = parseConfiguration_Folder(vcConfiguration, () => (vcConfiguration.IntermediateDirectory));
            configurationInfo.OutputFolder = parseConfiguration_Folder(vcConfiguration, () => (vcConfiguration.OutputDirectory));

            // We get compiler settings, such as the include path and 
            // preprocessor definitions...
            parseConfiguration_CompilerSettings(vcConfiguration, configurationInfo);

            // We get linker settings, such as any libs to link and the library path...
            parseConfiguration_LinkerSettings(vcConfiguration, configurationInfo);

            // We parse librarian settings (how libraries are linked)...
            parseConfiguration_LibrarianSettings(vcConfiguration, configurationInfo);

            // We see if there are any pre- or post- build events set up for this
            // configuration. The only types of events we know how to deal with are
            // ones that invoke a .cmd file. For these we convert them to invoke
            // a .sh file with the same name.
            parseConfiguration_PreBuildEvent(vcConfiguration, configurationInfo);
            parseConfiguration_PostBuildEvent(vcConfiguration, configurationInfo);

            // We add the configuration to the collection of them for the project...
            m_projectInfo.addConfigurationInfo(configurationInfo);
        }
Exemple #16
0
        /// <summary>
        /// Finds compiler settings, such as the include path, for the configuration
        /// passed in.
        /// </summary>
        private void parseConfiguration_CompilerSettings(VCConfiguration vcConfiguration, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // We get the compiler-settings 'tool'...
            IVCCollection tools = Utils.call(() => (vcConfiguration.Tools as IVCCollection));
            VCCLCompilerTool compilerTool = Utils.call(() => (tools.Item("VCCLCompilerTool") as VCCLCompilerTool));

            // And extract various details from it...
            parseCompilerSettings_IncludePath(vcConfiguration, compilerTool, configurationInfo);
            parseCompilerSettings_PreprocessorDefinitions(vcConfiguration, compilerTool, configurationInfo);
            parseCompilerSettings_CompilerFlags(vcConfiguration, compilerTool, configurationInfo);
        }
Exemple #17
0
 /// <summary>
 /// We parse the pre-build events.
 /// </summary>
 private void parseConfiguration_PreBuildEvent(VCConfiguration vcConfiguration, ProjectConfigurationInfo_CPP configurationInfo)
 {
     // We see if there is a pre-build event...
     IVCCollection tools = Utils.call(() => (vcConfiguration.Tools as IVCCollection));
     VCPreBuildEventTool preBuildEvent = Utils.call(() => (tools.Item("VCPreBuildEventTool") as VCPreBuildEventTool));
     if (preBuildEvent == null)
     {
         return;
     }
     string commandLine = Utils.call(() => (preBuildEvent.CommandLine));
     configurationInfo.PreBuildEvent = convertBuildEventCommandLine(commandLine);
 }
Exemple #18
0
        /// <summary>
        /// Finds the library path for the configuration passed in.
        /// </summary>
        private void parseLinkerSettings_LibraryPath(VCConfiguration vcConfiguration, VCLinkerTool linkerTool, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // We:
            // 1. Read the additional library paths (which are in a semi-colon-delimited string)
            // 2. Split it into separate paths
            // 3. Resolve any symbols
            // 4. Make sure all paths are relative to the project root folder

            // 1 & 2...
            string strAdditionalLibraryDirectories = Utils.call(() => (linkerTool.AdditionalLibraryDirectories));
            if (strAdditionalLibraryDirectories == null)
            {
                return;
            }

            List<string> additionalLibraryDirectories = Utils.split(strAdditionalLibraryDirectories, ';', ',');
            foreach (string additionalLibraryDirectory in additionalLibraryDirectories)
            {
                // The string may be quoted. We need to remove the quotes...
                string unquotedLibraryDirectory = additionalLibraryDirectory.Trim('"');
                if (unquotedLibraryDirectory == "")
                {
                    continue;
                }

                // 3 & 4...
                string resolvedPath = Utils.call(() => (vcConfiguration.Evaluate(unquotedLibraryDirectory)));
                if (resolvedPath != "")
                {
                    string relativePath = Utils.makeRelativePath(m_projectInfo.RootFolderAbsolute, resolvedPath);
                    configurationInfo.addLibraryPath(relativePath);
                }
            }
        }
 /// <summary>
 /// Returns the folder to use for intermediate files.
 /// </summary>
 private string getOutputFolder(ProjectConfigurationInfo_CPP configuration)
 {
     return Utils.addPrefixToFolderPath(configuration.OutputFolder, m_projectConfig.CPPFolderPrefix);
 }
 /// <summary>
 /// Returns the library-path variable name for the configuration passed in.
 /// For example "Debug_Library_Path".
 /// </summary>
 private string getLibraryPathVariableName(ProjectConfigurationInfo_CPP configuration)
 {
     return configuration.Name + "_Library_Path";
 }
        /// <summary>
        /// Sets up implicit linking for this project.
        /// </summary>
        public void setupImplicitLinking()
        {
            // Implicit linking can be a bit tricky, and works differently
            // depending on whether the project is an executable or a
            // library.

            // Executables
            // -----------
            // 1. We check if the project is set to link dependencies.
            //    If so, we:
            // 2. Find the libraries that the executable depends and link
            //    them in.
            // 3. If the libraries themselves depend on other libraries,
            //    we need to link them in as well. We recurse through the
            //    chain of dependencies, to find all the libraries that
            //    the executable depends on. (Subject to rule 4, below.)
            // 4. If any library is set to link its dependencies, we
            //    link it, but we do not link any of the libraries it
            //    depends on (as they are already linked into the
            //    library itself).

            // Libraries
            // ---------
            // 1. We check if the library is set to link dependencies.
            //    If so, we:
            // 2. Find the libraries that the project depends on.
            //    We find the list of object files that these libraries
            //    are made up from, and add them to the collection to
            //    create the main library from.
            // 3. We recurse through any libraries that the libraries
            //    from step 2 depend on. We add their files to this
            //    library as well.

            // We check if this project should implicitly link the projects
            // it depends on...
            if (LinkLibraryDependencies == false)
            {
                return;
            }

            // We want to link projects we depend on...
            switch (ProjectType)
            {
            case ProjectInfo.ProjectTypeEnum.CPP_EXECUTABLE:
            {
                // We find the libraries that this executable depends on...
                List <ImplicitLinkInfo> infos = new List <ImplicitLinkInfo>();

                // Commented as it generates wrong and not needed additional informations.
                // Is it really needed if project properties are correctly filled?
                //findImplicitlyLinkedLibraries(infos);

                // And add them to the library path...
                foreach (ImplicitLinkInfo info in infos)
                {
                    // We find the configuration for this info and add
                    // the library to it...
                    ProjectConfigurationInfo_CPP configuration = getConfigurationInfo(info.ConfigurationName);
                    if (configuration == null)
                    {
                        // We should only fail to find a configuration is the
                        // project has no configurations. So really, this should
                        // not happen...
                        Log.log(String.Format("Project {0} could not implicitly link {1}. Could not find the {2} configuration.", Name, info.LibraryRawName, info.ConfigurationName));
                        continue;
                    }

                    // We add the library and the library path...
                    configuration.addLibraryRawName(info.LibraryRawName);
                    string libraryPath = Utils.makeRelativePath(RootFolderAbsolute, info.OutputFolderAbsolute);
                    configuration.addLibraryPath(libraryPath);
                }
            }
            break;

            case ProjectInfo_CPP.ProjectTypeEnum.CPP_STATIC_LIBRARY:
            {
                // We find the collection of object files used by any
                // libraries this library depends on...
                List <ImplicitLinkInfo> infos = new List <ImplicitLinkInfo>();
                findImplicitlyLinkedObjectFiles(infos);

                // We add the files to the configurations...
                foreach (ImplicitLinkInfo info in infos)
                {
                    // We find the configuration for this info...
                    ProjectConfigurationInfo_CPP configuration = getConfigurationInfos().Find((cfg) => (cfg.Name == info.ConfigurationName));

                    // We add the collection of object files to the configuration...
                    string prefix = MakeItSoConfig.Instance.getProjectConfig(Name).CPPFolderPrefix;
                    string intermediateFolderAbsolute = Utils.addPrefixToFolderPath(info.IntermediateFolderAbsolute, prefix);
                    foreach (string objectFile in info.ObjectFileNames)
                    {
                        string absolutePath = intermediateFolderAbsolute + "/" + objectFile;
                        string relativePath = Utils.makeRelativePath(RootFolderAbsolute, absolutePath);
                        configuration.addImplicitlyLinkedObjectFile(relativePath);
                    }
                }
            }
            break;
            }
        }
 /// <summary>
 /// Gets the name for the pre-build event target for the configuration
 /// passed in.
 /// </summary>
 private string getPreBuildTargetName(ProjectConfigurationInfo_CPP configurationInfo)
 {
     return configurationInfo.Name + "_PreBuildEvent";
 }
        /// <summary>
        /// Creates a configuration target.
        /// </summary>
        private void createConfigurationTarget(ProjectConfigurationInfo_CPP configurationInfo)
        {
            // For example:
            //
            //   .PHONY: Debug
            //   Debug: debug/main.o debug/math.o debug/utility.o
            //       g++ debug/main.o debug/math.o debug/utility.o -o output/hello.exe

            // The target name...
            m_file.WriteLine("# Builds the {0} configuration...", configurationInfo.Name);
            m_file.WriteLine(".PHONY: {0}", configurationInfo.Name);

            // The targets that this target depends on...
            var dependencies = new List<string>();

            dependencies.Add("create_folders");

            // Is there a pre-build event for this configuration?
            if (configurationInfo.PreBuildEvent != "")
            {
                string preBuildTargetName = getPreBuildTargetName(configurationInfo);
                dependencies.Add(preBuildTargetName);
            }

            // We add any custom build targets as dependencies...
            foreach (CustomBuildRuleInfo_CPP ruleInfo in configurationInfo.getCustomBuildRuleInfos())
            {
                string ruleTargetName = getCustomRuleTargetName(configurationInfo, ruleInfo);
                dependencies.Add(ruleTargetName);
            }

            // The object files the target depends on...
            string intermediateFolder = getIntermediateFolder(configurationInfo);
            var objectFiles = new List<string>();
            foreach (string filename in m_projectInfo.getFiles())
            {
                string path = String.Format("{0}/{1}.o", intermediateFolder, Path.GetFileNameWithoutExtension(filename));
                objectFiles.Add(path);
                dependencies.Add(path);
            }

            // We write the dependencies...
            m_file.WriteLine("{0}: {1}", configurationInfo.Name, Utils.join(" ", dependencies));

            // We find variables needed for the link step...
            string outputFolder = getOutputFolder(configurationInfo);

            // The link step...
            switch (m_projectInfo.ProjectType)
            {
                // Creates a C++ executable...
                case ProjectInfo_CPP.ProjectTypeEnum.CPP_EXECUTABLE:
                    {
                        m_file.WriteLine("\t$(CPP_COMPILER) {0} $({1}) $({2}) -Wl,-rpath,./ -o {3}/{4}.exe",
                            Utils.join(" ", objectFiles),
                            getLibraryPathVariableName(configurationInfo),
                            getLibrariesVariableName(configurationInfo),
                            outputFolder,
                            m_projectInfo.Name);
                        break;
                    }

                // Creates a static library...
                case ProjectInfo_CPP.ProjectTypeEnum.CPP_STATIC_LIBRARY:
                    {
                        m_file.WriteLine("\tar rcs {0}/lib{1}.a {2} $({3})",
                            outputFolder,
                            m_projectInfo.Name,
                            Utils.join(" ", objectFiles),
                            getImplicitlyLinkedObjectsVariableName(configurationInfo));
                        break;
                    }

                // Creates a DLL (shared-objects) library...
                case ProjectInfo_CPP.ProjectTypeEnum.CPP_DLL:
                    {
                        string dllName, pic;
                        if (MakeItSoConfig.Instance.IsCygwinBuild == true)
                        {
                            dllName = String.Format("lib{0}.dll", m_projectInfo.Name);
                            pic = "";
                        }
                        else
                        {
                            dllName = String.Format("lib{0}.so", m_projectInfo.Name);
                            pic = "-fPIC";
                        }

                        m_file.WriteLine("\t$(CPP_COMPILER) {0} -shared -Wl,-soname,{1} -o {2}/{1} {3} $({4}) $({5}) $({6})",
                            pic,
                            dllName,
                            outputFolder,
                            Utils.join(" ", objectFiles),
                            getImplicitlyLinkedObjectsVariableName(configurationInfo),
                            getLibraryPathVariableName(configurationInfo),
                            getLibrariesVariableName(configurationInfo));
                        break;
                    }
            }

            // The post-build step, if there is one...
            if (configurationInfo.PostBuildEvent != "")
            {
                m_file.WriteLine("\t" + configurationInfo.PostBuildEvent);
            }

            m_file.WriteLine("");
        }
        /// <summary>
        /// Updates libraries from config settings.
        /// </summary>
        private void updateLibraries(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            // We check if any of the libraries in the configuration should be removed...
            HashSet<string> libraries = new HashSet<string>(configuration.getLibraryRawNames());
            foreach (string library in libraries)
            {
                if (projectSettings.libraryShouldBeRemoved(library) == true)
                {
                    configuration.removeLibraryRawName(library);
                }
            }

            // We add any that need adding...
            List<string> librariesToAdd = projectSettings.getConfiguration(configuration.Name).getLibrariesToAdd().ToList();
            foreach (string library in librariesToAdd)
            {
                string rawName = Utils.convertLinuxLibraryNameToRawName(library);
                configuration.addLibraryRawName(rawName);
            }
        }
        /// <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>
        /// Updates preprocessor definitions from config settings.
        /// </summary>
        private void updatePreprocessorDefinitions(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            // By default we replace WIN32 with GCC_BUILD...
            configuration.removePreprocessorDefinition("WIN32");
            configuration.addPreprocessorDefinition("GCC_BUILD");

            // We check if any definitions should be removed...
            List<string> definitions = new List<string>(configuration.getPreprocessorDefinitions());
            foreach (string definition in definitions)
            {
                if(projectSettings.preprocessorDefinitionShouldBeRemoved(definition) == true)
                {
                    configuration.removePreprocessorDefinition(definition);
                }
            }

            // We add any new definitions...
            List<string> definitionsToAdd = projectSettings.getConfiguration(configuration.Name).getPreprocessorDefinitionsToAdd().ToList();
            foreach (string definition in definitionsToAdd)
            {
                configuration.addPreprocessorDefinition(definition);
            }
        }
 /// <summary>
 /// We create targets to build any custom build rules associated with 
 /// this configuration.
 /// </summary>
 private void createCustomBuildRuleTargets(ProjectConfigurationInfo_CPP configuration)
 {
     foreach(CustomBuildRuleInfo_CPP ruleInfo in configuration.getCustomBuildRuleInfos())
     {
         createCustomBuildRuleTarget(configuration, ruleInfo);
     }
 }
        /// <summary>
        /// Updates include paths from config settings.
        /// </summary>
        private void updateIncludePaths(ProjectConfigurationInfo_CPP configuration)
        {
            MakeItSoConfig_Project projectSettings = MakeItSoConfig.Instance.getProjectConfig(configuration.ParentProjectInfo.Name);

            string projectRootFolder = configuration.ParentProjectInfo.RootFolderAbsolute;

            // We check if any include paths should be removed...
            List<string> includePaths = new List<string>(configuration.getIncludePaths());
            foreach (string includePath in includePaths)
            {
                string fullPath = Path.Combine(projectRootFolder, includePath);
                if (projectSettings.includePathShouldBeRemoved(fullPath) == true)
                {
                    configuration.removeIncludePath(includePath);
                }
            }

            // We add any new paths...
            List<string> pathsToAdd = projectSettings.getConfiguration(configuration.Name).getIncludePathsToAdd().ToList();
            foreach (string pathToAdd in pathsToAdd)
            {
                string relativePath = Utils.makeRelativePath(projectRootFolder, pathToAdd);
                configuration.addIncludePath(relativePath);
            }
        }
        /// <summary>
        /// Creates targets to compile the files for the configuration passed in.
        /// </summary>
        private void createFileTargets(ProjectConfigurationInfo_CPP configurationInfo)
        {
            // For example:
            //
            //   -include debug/main.d
            //   main.o: main.cpp
            //       g++ -c main.cpp [include-path] -o debug/main.o
            //       g++ -MM main.cpp [include-path] > debug/main.d

            // We find settings that aply to all files in the configuration...
            string intermediateFolder = getIntermediateFolder(configurationInfo);
            string includePath = String.Format("$({0})", getIncludePathVariableName(configurationInfo));
            string preprocessorDefinitions = String.Format("$({0})", getPreprocessorDefinitionsVariableName(configurationInfo));
            string compilerFlags = String.Format("$({0})", getCompilerFlagsVariableName(configurationInfo));

            // We write a section of the makefile to compile each file...
            foreach (string filename in m_projectInfo.getFiles())
            {
                // We work out the filename, the object filename and the
                // dependencies filename...
                string path = String.Format("{0}/{1}", intermediateFolder, Path.GetFileName(filename));
                string objectPath = Path.ChangeExtension(path, ".o");
                string dependenciesPath = Path.ChangeExtension(path, ".d");

                // We decide which compiler to use...
                string compiler = "$(CPP_COMPILER)";
                if (Path.GetExtension(filename).ToLower() == ".c")
                {
                    compiler = "$(C_COMPILER)";
                }

                // We create the target...
                m_file.WriteLine("# Compiles file {0} for the {1} configuration...", filename, configurationInfo.Name);
                m_file.WriteLine("-include {0}", dependenciesPath);
                m_file.WriteLine("{0}: {1}", objectPath, filename);
                m_file.WriteLine("\t{0} {1} {2} -c {3} {4} -o {5}", compiler, preprocessorDefinitions, compilerFlags, filename, includePath, objectPath);
                m_file.WriteLine("\t{0} {1} {2} -MM {3} {4} > {5}", compiler, preprocessorDefinitions, compilerFlags, filename, includePath, dependenciesPath);
                m_file.WriteLine("");
            }
        }
Exemple #30
0
        /// <summary>
        /// Finds the collection of preprocessor definitions for the configuration passed in.
        /// </summary>
        private void parseCompilerSettings_PreprocessorDefinitions(VCConfiguration vcConfiguration, VCCLCompilerTool compilerTool, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // We read the delimited string of preprocessor definitions, and
            // split them...
            string strPreprocessorDefinitions = Utils.call(() => (compilerTool.PreprocessorDefinitions));
            if (strPreprocessorDefinitions == null)
            {
                return;
            }
            List<string> preprocessorDefinitions = Utils.split(strPreprocessorDefinitions, ';');

            // We add the definitions to the parsed configuration (removing ones that
            // aren't relevant to a linux build)...
            foreach (string definition in preprocessorDefinitions)
            {
                configurationInfo.addPreprocessorDefinition(definition);
            }
        }
        /// <summary>
        /// Creates a target for the pre-build event, if there is one.
        /// </summary>
        private void createPreBuildEventTarget(ProjectConfigurationInfo_CPP configurationInfo)
        {
            if (configurationInfo.PreBuildEvent == "")
            {
                return;
            }

            m_file.WriteLine("# Pre-build step...");
            string targetName = getPreBuildTargetName(configurationInfo);
            m_file.WriteLine(".PHONY: " + targetName);
            m_file.WriteLine(targetName + ":");
            m_file.WriteLine("\t" + configurationInfo.PreBuildEvent);

            m_file.WriteLine("");
        }
Exemple #32
0
        /// <summary>
        /// Finds compiler settings, such as the include path, for the configuration
        /// passed in.
        /// </summary>
        private void parseConfiguration_CompilerSettings(VCConfiguration vcConfiguration, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // We get the compiler-settings 'tool'...
            IVCCollection tools = Utils.call(() => (vcConfiguration.Tools as IVCCollection));
            VCCLCompilerTool compilerTool = Utils.call(() => (tools.Item("VCCLCompilerTool") as VCCLCompilerTool));

            // And extract various details from it...
            parseCompilerSettings_IncludePath(vcConfiguration, compilerTool, configurationInfo);
            parseCompilerSettings_PreprocessorDefinitions(vcConfiguration, compilerTool, configurationInfo);
            parseCompilerSettings_CompilerFlags(vcConfiguration, compilerTool, configurationInfo);

            IVCCollection sheets = Utils.call(() => (vcConfiguration.PropertySheets as IVCCollection));
            int numSheets = Utils.call(() => (sheets.Count));
            for (int i = 1; i <= numSheets; ++i)
            {
                VCPropertySheet sheet = Utils.call(() => (sheets.Item(i) as VCPropertySheet));

                if (!sheet.IsSystemPropertySheet)
                {
                    // 1. The thing is that VCPropertySheet and VCConfiguration have more-or-less
                    //    identical interfaces. So we should be able to merge them fairly easily.
                    //
                    // 2. We should try multiple layers of inheritance

                    IVCCollection toolsInSheet = Utils.call(() => (sheet.Tools as IVCCollection));
                    VCCLCompilerTool compilerToolInSheet = Utils.call(() => (toolsInSheet.Item("VCCLCompilerTool") as VCCLCompilerTool));

                    // And extract various details from it...
                    if (compilerToolInSheet != null)
                    {
                        parseCompilerSettings_IncludePath(vcConfiguration, compilerToolInSheet, configurationInfo);
                        parseCompilerSettings_PreprocessorDefinitions(vcConfiguration, compilerToolInSheet, configurationInfo);
                        //parseCompilerSettings_CompilerFlags(vcConfiguration, compilerToolInSheet, configurationInfo);
                    }
                }
            }
        }
 /// <summary>
 /// Returns the compiler-flags variable name for the configuration passed in.
 /// For example "Debug_Compiler_Flags".
 /// </summary>
 private string getCompilerFlagsVariableName(ProjectConfigurationInfo_CPP configuration)
 {
     return configuration.Name + "_Compiler_Flags";
 }
Exemple #34
0
        /// <summary>
        /// Finds the linker settings, such as the collection of libraries to link,
        /// for the configuration passed in.
        /// </summary>
        private void parseConfiguration_LinkerSettings(VCConfiguration vcConfiguration, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // We get the linker-settings 'tool'...
            IVCCollection tools = Utils.call(() => (vcConfiguration.Tools as IVCCollection));
            VCLinkerTool linkerTool = Utils.call(() => (tools.Item("VCLinkerTool") as VCLinkerTool));
            if (linkerTool == null)
            {
                // Not all projects have a linker tools...
                return;
            }

            // And extract various details from it...
            parseLinkerSettings_LibraryPath(vcConfiguration, linkerTool, configurationInfo);
            parseLinkerSettings_Libraries(vcConfiguration, linkerTool, configurationInfo);
            parseLinkerSettings_Misc(vcConfiguration, linkerTool, configurationInfo);

            IVCCollection sheets = Utils.call(() => (vcConfiguration.PropertySheets as IVCCollection));
            int numSheets = Utils.call(() => (sheets.Count));
            for (int i = 1; i <= numSheets; ++i)
            {
                VCPropertySheet sheet = Utils.call(() => (sheets.Item(i) as VCPropertySheet));

                if (!sheet.IsSystemPropertySheet)
                {
                    // 1. The thing is that VCPropertySheet and VCConfiguration have more-or-less
                    //    identical interfaces. So we should be able to merge them fairly easily.
                    //
                    // 2. We should try multiple layers of inheritance

                    IVCCollection toolsInSheet = Utils.call(() => (sheet.Tools as IVCCollection));
                    VCLinkerTool linkerToolInSheet = Utils.call(() => (toolsInSheet.Item("VCLinkerTool") as VCLinkerTool));

                    // And extract various details from it...
                    if (linkerToolInSheet != null)
                    {
                        parseLinkerSettings_LibraryPath(vcConfiguration, linkerToolInSheet, configurationInfo);
                        parseLinkerSettings_Libraries(vcConfiguration, linkerToolInSheet, configurationInfo);
                    }
                }
            }
        }
 /// <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);
 }
Exemple #36
0
        /// <summary>
        /// Finds the collection of additional libraries to link into this project.
        /// </summary>
        private void parseLinkerSettings_Libraries(VCConfiguration vcConfiguration, VCLinkerTool linkerTool, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // The collection of libraries is stored in a space-delimited string...
            string strAdditionalLibraries = Utils.call(() => (linkerTool.AdditionalDependencies));
            if (strAdditionalLibraries == null)
            {
                return;
            }

            List<string> additionalLibraries = Utils.split(strAdditionalLibraries, ' ');
            foreach (string additionalLibrary in additionalLibraries)
            {
                // We add the library to the project...
                string rawName = Path.GetFileNameWithoutExtension(additionalLibrary);
                configurationInfo.addLibraryRawName(rawName);
            }
        }
 /// <summary>
 /// Returns the implictly-linked-objects variable name for the configuration passed in.
 /// For example "Debug_Implicitly_Linked_Objects".
 /// </summary>
 private string getImplicitlyLinkedObjectsVariableName(ProjectConfigurationInfo_CPP configuration)
 {
     return configuration.Name + "_Implicitly_Linked_Objects";
 }
Exemple #38
0
        /// <summary>
        /// Reads miscellaneous linker settings.
        /// </summary>
        private void parseLinkerSettings_Misc(VCConfiguration vcConfiguration, VCLinkerTool linkerTool, ProjectConfigurationInfo_CPP configurationInfo)
        {
            // Whether we implicitly link in libraries we depend on.
            // (We are assuming that all configurations of the project have the
            // same link-library-dependencies setting.)
            m_projectInfo.LinkLibraryDependencies = Utils.call(() => (linkerTool.LinkLibraryDependencies));

            // Generate debug info...
            bool debugInfo = Utils.call(() => (linkerTool.GenerateDebugInformation));
            if (debugInfo == true
                &&
                configurationInfo.getPreprocessorDefinitions().Contains("NDEBUG") == false)
            {
                configurationInfo.addCompilerFlag("-g");
            }
        }
 /// <summary>
 /// Returns the include-path variable name for the configuration passed in.
 /// For example "Debug_Include_Path".
 /// </summary>
 private string getIncludePathVariableName(ProjectConfigurationInfo_CPP configuration)
 {
     return configuration.Name + "_Include_Path";
 }