/// <summary>
        /// Constructor
        /// </summary>
        private MakefileBuilder_Project_CPP(ProjectInfo_CPP project, ProjectInfo_CUDA projectInfoCuda)
        {
            m_projectInfo     = project;
            m_projectInfoCuda = projectInfoCuda;

            try
            {
                // We create the file '[project-name].makefile', and set it to
                // use unix-style line endings...
                string path = String.Format("{0}/{1}.makefile", m_projectInfo.RootFolderAbsolute, m_projectInfo.Name);
                m_file         = new StreamWriter(path, false);
                m_file.NewLine = MakeItSoConfig.Instance.NewLine;

                // We create variables...
                createCompilerVariables();
                createIncludePathVariables();
                createLibraryPathVariables();
                createLibrariesVariables();
                createPreprocessorDefinitionsVariables();
                createImplicitlyLinkedObjectsVariables();
                createCompilerFlagsVariables();

                MakefileBuilder_Project_CUDA.createCudaLocationAndCompiler(m_file, m_projectInfoCuda);
                MakefileBuilder_Project_CUDA.createCudaIncludesAndLibaryPath(m_file, m_projectInfo, m_projectInfoCuda);

                // We create an 'all configurations' root target...
                createAllConfigurationsTarget();

                // We create one target for each configuration...
                createConfigurationTargets();

                // We create a target to create the intermediate and output folders...
                createCreateFoldersTarget();

                // Creates the target that cleans intermediate files...
                createCleanTarget();
            }
            finally
            {
                if (m_file != null)
                {
                    m_file.Close();
                    m_file.Dispose();
                }
            }
        }
        /// <summary>
        /// Creates a target for each configuration.
        /// </summary>
        private void createConfigurationTargets()
        {
            foreach (ProjectConfigurationInfo_CPP configurationInfo in m_projectInfo.getConfigurationInfos())
            {
                // We create the configuration target...
                createConfigurationTarget(configurationInfo);

                // We create the pre-build event target (if there is a pre-build event)...
                createPreBuildEventTarget(configurationInfo);

                // We create targets for any custom build rules...
                createCustomBuildRuleTargets(configurationInfo);

                // We compile all files for this target...
                createFileTargets(configurationInfo);

                MakefileBuilder_Project_CUDA.createCudaLinker(m_file, m_projectInfo, configurationInfo, m_projectInfoCuda);
                MakefileBuilder_Project_CUDA.createFileTargets(m_file, m_projectInfo, configurationInfo, m_projectInfoCuda);
            }
        }
        /// <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...
            string dependencies = "create_folders ";

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

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

            var projectSettings = MakeItSoConfig.Instance.getProjectConfig(m_projectInfo.Name);

            // The object files the target depends on...
            string intermediateFolder = getIntermediateFolder(configurationInfo);
            string objectFiles        = "";

            foreach (string filename in m_projectInfo.getFiles())
            {
                if (!projectSettings.filesOrDirectoriesShouldBeRemoved(filename))
                {
                    string path = String.Format("{0}/{1}", intermediateFolder, filename);
                    if (filename.StartsWith(".."))
                    {
                        var tmp = filename.Replace("../", "");
                        path = String.Format("{0}/{1}", intermediateFolder, tmp);
                    }
                    string objectPath = Path.ChangeExtension(path, ".o");
                    objectFiles  += (objectPath + " ");
                    dependencies += (objectPath + " ");
                }
            }

            // To Link with gpu code.
            if (m_projectInfo.ProjectType != ProjectInfo_CPP.ProjectTypeEnum.CPP_EXECUTABLE)
            {
                // NOTE
                // https://stackoverflow.com/questions/26893588/creating-a-static-cuda-library-to-be-linked-with-a-c-program
                // dlinkするときは元になったobjファイルも含めること.
                // そうしないと、hostコードが含まれなくなる.

                objectFiles  += MakefileBuilder_Project_CUDA.getObjectFiles(intermediateFolder, m_projectInfoCuda);
                dependencies += MakefileBuilder_Project_CUDA.getObjectFiles(intermediateFolder, m_projectInfoCuda);
            }

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

            // We find variables needed for the link step...
            string outputFolder = getOutputFolder(configurationInfo);
            string implicitlyLinkedObjectFiles = String.Format("$({0})", getImplicitlyLinkedObjectsVariableName(configurationInfo));

            // The link step...
#if false
            switch (m_projectInfo.ProjectType)
            {
            // Creates a C++ executable...
            case ProjectInfo_CPP.ProjectTypeEnum.CPP_EXECUTABLE:
                string libraryPath = getLibraryPathVariableName(configurationInfo);
                string libraries   = getLibrariesVariableName(configurationInfo);
                m_file.WriteLine("\tg++ {0} $({1}) $({2}) -Wl,-rpath,./ -o {3}/{4}.exe", objectFiles, libraryPath, libraries, outputFolder, m_projectInfo.Name);
                break;


            // Creates a static library...
            case ProjectInfo_CPP.ProjectTypeEnum.CPP_STATIC_LIBRARY:
                // We use the Target Name as the output file name if it exists
                if (configurationInfo.TargetName != "")
                {
                    m_file.WriteLine("\tar rcs {0}/lib{1}.a {2} {3}", outputFolder, configurationInfo.TargetName, objectFiles, implicitlyLinkedObjectFiles);
                }
                else
                {
                    m_file.WriteLine("\tar rcs {0}/lib{1}.a {2} {3}", outputFolder, m_projectInfo.Name, objectFiles, implicitlyLinkedObjectFiles);
                }
                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("\tg++ {0} -shared -Wl,-soname,{1} -o {2}/{1} {3} {4}", pic, dllName, outputFolder, objectFiles, implicitlyLinkedObjectFiles);
                break;
            }
#else
            switch (m_projectInfo.ProjectType)
            {
            // Creates a C++ executable...
            case ProjectInfo_CPP.ProjectTypeEnum.CPP_EXECUTABLE:
                string libraryPath = getLibraryPathVariableName(configurationInfo);
                string libraries   = getLibrariesVariableName(configurationInfo);
                string exeName     = getBuildExportName(configurationInfo);
                m_file.WriteLine("\tg++ {0} $({1}) $({2}) -Wl,-rpath,./ -o {3}/{4}", objectFiles, libraryPath, libraries, outputFolder, exeName);
                break;


            // Creates a static library...
            case ProjectInfo_CPP.ProjectTypeEnum.CPP_STATIC_LIBRARY:
                // We use the Target Name as the output file name if it exists
                var libName = getBuildExportName(configurationInfo);
                m_file.WriteLine("\tar rcs {0}/{1} {2} {3}", outputFolder, libName, objectFiles, implicitlyLinkedObjectFiles);
                break;

            // Creates a DLL (shared-objects) library...
            case ProjectInfo_CPP.ProjectTypeEnum.CPP_DLL:
                string dllName = getBuildExportName(configurationInfo);
                string pic;
                if (MakeItSoConfig.Instance.IsCygwinBuild == true)
                {
                    pic = "";
                }
                else
                {
                    pic = "-fPIC";
                }

                m_file.WriteLine("\tg++ {0} -shared -Wl,-soname,{1} -o {2}/{1} {3} {4}", pic, dllName, outputFolder, objectFiles, implicitlyLinkedObjectFiles);
                break;
            }
#endif

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

            m_file.WriteLine("");
        }