make_msvcX_install_[config] patch by Brezenbak
[reactos.git] / reactos / tools / rbuild / backend / msvc / msvc.cpp
index b4188a6..dfadc5e 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2005 Trevor McCort\r
  * Copyright (C) 2005 Casper S. Hornstrup\r
  * Copyright (C) 2005 Steven Edwards\r
+ * Copyright (C) 2005 Royce Mitchell\r
  *\r
  * This program is free software; you can redistribute it and/or modify\r
  * it under the terms of the GNU General Public License as published by\r
 #include <iostream>\r
 #include <fstream>\r
 #include <string>\r
+#include <vector>\r
 \r
 #include "msvc.h"\r
 #include "../mingw/mingw.h"\r
 \r
-using namespace std;\r
-\r
-char get_key(char *valid,char *prompt); //FIXME\r
-bool spawn_new(const string& cmd); //FIXME\r
-void gen_guid();\r
+using std::string;\r
+using std::vector;\r
+using std::ifstream;\r
 \r
 static class MSVCFactory : public Backend::Factory\r
 {\r
@@ -56,61 +56,48 @@ MSVCBackend::MSVCBackend(Project &project,
 \r
 void MSVCBackend::Process()\r
 {\r
-       //bool exec = false;\r
-       //const char rbuild_mingw[] = "output-i386\\tools\\rbuild\\rbuild.exe mingw"; \r
-\r
-       string filename = ProjectNode.name + ".dsw";\r
+       if ( configuration.CleanAsYouGo ) {\r
+               _clean_project_files();\r
+               return;\r
+       }\r
+       if ( configuration.InstallFiles ) {\r
+               _install_files( _get_vc_dir(),  configuration.VSConfigurationType );\r
+               return;\r
+       }\r
+       string filename_sln ( ProjectNode.name );\r
+       //string filename_rules = "gccasm.rules";\r
        \r
-       cout << "Creating MSVC project: " << filename << endl;\r
+       if ( configuration.VSProjectVersion == "6.00" )\r
+               filename_sln += ".dsw";\r
+       else {\r
+               filename_sln += ".sln";\r
+\r
+               //m_rulesFile = fopen ( filename_rules.c_str(), "wb" );\r
+               //if ( m_rulesFile )\r
+               //{\r
+               //      _generate_rules_file ( m_rulesFile );\r
+               //}\r
+               //fclose ( m_rulesFile );\r
+       }\r
 \r
+       printf ( "Creating MSVC workspace: %s\n", filename_sln.c_str() );\r
+       \r
        ProcessModules();\r
+       m_slnFile = fopen ( filename_sln.c_str(), "wb" );\r
 \r
-       m_dswFile = fopen ( filename.c_str(), "w" );\r
-\r
-       if ( !m_dswFile )\r
+       if ( !m_slnFile )\r
        {\r
-               cout << "Could not open file." << endl;\r
+               printf ( "Could not create file '%s'.\n", filename_sln.c_str() );\r
                return;\r
        }\r
-       _generate_wine_dsw ( m_dswFile );\r
-#if 0\r
-       m_devFile << "Microsoft Visual Studio Solution File, Format Version 9.00" << endl;\r
-       m_devFile << "# Visual C++ Express 2005" << endl;\r
-\r
-       m_devFile << "# FIXME Project listings here" << endl;\r
-       m_devFile << "EndProject" << endl;\r
-       m_devFile << "Global" << endl;\r
-       m_devFile << "  GlobalSection(SolutionConfigurationPlatforms) = preSolution" << endl;\r
-       m_devFile << "          Debug|Win32 = Debug|Win32" << endl;\r
-       m_devFile << "          Release|Win32 = Release|Win32" << endl;\r
-       m_devFile << "  EndGlobalSection" << endl;\r
-       m_devFile << "  GlobalSection(ProjectConfigurationPlatforms) = postSolution" << endl;\r
-       m_devFile << "  #FIXME Project Listings Here" << endl;\r
-       m_devFile << "  EndGlobalSection" << endl;\r
-       m_devFile << "  GlobalSection(SolutionProperties) = preSolution" << endl;\r
-       m_devFile << "          HideSolutionNode = FALSE" << endl;\r
-       m_devFile << "  EndGlobalSection" << endl;\r
-       m_devFile << "EndGlobal" << endl;\r
-\r
-       m_devFile << endl << endl;\r
-#endif\r
-       fclose ( m_dswFile );\r
 \r
-       gen_guid();\r
+       if ( configuration.VSProjectVersion == "6.00" )\r
+               _generate_wine_dsw ( m_slnFile );\r
+       else\r
+               _generate_sln ( m_slnFile );\r
 \r
-       // The MSVC build still needs the mingw backend.\r
-       //ProcessModules();\r
-\r
-       cout << "Done." << endl << endl;\r
-\r
-       /*cout << "Don't expect the MSVC backend to work yet. "<< endl << endl;\r
-\r
-       if(get_key("yn","Would you like to configure for a Mingw build as well? (y/n)") == 'y')\r
-       {\r
-               exec = spawn_new(rbuild_mingw);\r
-                       if (!exec)\r
-                               printf("\nError invoking rbuild\n");\r
-       }*/\r
+       fclose ( m_slnFile );\r
+       printf ( "Done.\n" );\r
 }\r
 \r
 void MSVCBackend::ProcessModules()\r
@@ -119,12 +106,20 @@ void MSVCBackend::ProcessModules()
        {\r
                Module &module = *ProjectNode.modules[i];\r
 \r
-               for(size_t k = 0; k < module.non_if_data.files.size(); k++)\r
+               module.guid = _gen_guid();\r
+\r
+               if (configuration.VSProjectVersion == "6.00")\r
+                       this->_generate_dsp ( module );\r
+               else\r
+                       this->_generate_vcproj ( module );\r
+\r
+\r
+               /*for(size_t k = 0; k < module.non_if_data.files.size(); k++)\r
                {\r
                        File &file = *module.non_if_data.files[k];\r
                        \r
                        ProcessFile(file.name);\r
-               }\r
+               }*/\r
        }\r
 }\r
 \r
@@ -221,39 +216,203 @@ void MSVCBackend::OutputFolders()
 #endif\r
 }\r
 \r
+std::string\r
+MSVCBackend::OptFileName ( const Module& module ) const\r
+{\r
+       return DosSeparator(\r
+               ReplaceExtension ( module.GetPath(), "_" + _get_vc_dir() + "_auto.opt" )\r
+               );\r
+}\r
+\r
+std::string\r
+MSVCBackend::SuoFileName ( const Module& module ) const\r
+{\r
+       return DosSeparator(\r
+               ReplaceExtension ( module.GetPath(), "_" + _get_vc_dir() + "_auto.suo" )\r
+               );\r
+}\r
 \r
-char get_key(char *valid,char *prompt)\r
+std::string\r
+MSVCBackend::DswFileName ( const Module& module ) const\r
 {\r
-    int ch,okay;\r
-\r
-    while (1) {\r
-       if (prompt) printf("%s ",prompt);\r
-       fflush(stdout);\r
-       while (ch = getchar(), ch == ' ' || ch == '\t');\r
-       if (ch == EOF) exit(1);\r
-       if (!strchr(valid,okay = ch)) okay = 0;\r
-       while (ch = getchar(), ch != '\n' && ch != EOF);\r
-       if (ch == EOF) exit(1);\r
-       if (okay) return okay;\r
-       printf("Invalid input.\n");\r
-    }\r
+       return DosSeparator(\r
+               ReplaceExtension ( module.GetPath(), "_auto.dsw" )\r
+               );\r
+}\r
+\r
+std::string\r
+MSVCBackend::SlnFileName ( const Module& module ) const\r
+{\r
+       return DosSeparator(\r
+               ReplaceExtension ( module.GetPath(), "_" + _get_vc_dir() + "_auto.sln" )\r
+               );\r
 }\r
 \r
-bool spawn_new( const string& cmd )\r
+std::string\r
+MSVCBackend::NcbFileName ( const Module& module ) const\r
 {\r
-       string command = ssprintf (\r
-               "%s",\r
-               cmd.c_str (),\r
-               NUL,\r
-               NUL );\r
-       int exitcode = system ( command.c_str () );\r
-       return (exitcode == 0);\r
+       return DosSeparator(\r
+               ReplaceExtension ( module.GetPath(), "_" + _get_vc_dir() + "_auto.ncb" )\r
+               );\r
 }\r
 \r
 std::string\r
 MSVCBackend::DspFileName ( const Module& module ) const\r
 {\r
        return DosSeparator(\r
-               ReplaceExtension ( module.GetPath(), ".dsp" )\r
+               ReplaceExtension ( module.GetPath(), "_auto.dsp" )\r
                );\r
 }\r
+\r
+std::string\r
+MSVCBackend::VcprojFileName ( const Module& module ) const\r
+{\r
+       return DosSeparator(\r
+                       ReplaceExtension ( module.GetPath(), "_" + _get_vc_dir() + "_auto.vcproj" )\r
+                       );\r
+}\r
+\r
+std::string MSVCBackend::_get_vc_dir ( void ) const\r
+{\r
+       if ( configuration.VSProjectVersion == "6.00" )\r
+               return "vc6";\r
+       else if ( configuration.VSProjectVersion == "7.00" )\r
+               return "vc70";\r
+       else if ( configuration.VSProjectVersion == "7.10" )\r
+               return "vc71";\r
+       else /* must be VS2005 */\r
+               return "vc8";\r
+\r
+\r
+}\r
+\r
+void \r
+MSVCBackend::_get_object_files ( const Module& module, vector<string>& out) const\r
+{\r
+       string basepath = module.GetBasePath ();\r
+       string vcdir = _get_vc_dir ();\r
+       size_t i;\r
+       string intenv = Environment::GetIntermediatePath () + "\\" + basepath + "\\" + vcdir + "\\";\r
+       string outenv = Environment::GetOutputPath () + "\\" + basepath + "\\" + vcdir + "\\";\r
+       string dbg = vcdir.substr ( 0, 3 );\r
+\r
+       vector<string> cfgs;\r
+       cfgs.push_back ( intenv + "Debug" );\r
+       cfgs.push_back ( intenv + "Release" );\r
+       cfgs.push_back ( intenv + "Speed" );\r
+       cfgs.push_back ( outenv + "Debug" );\r
+       cfgs.push_back ( outenv + "Release" );\r
+       cfgs.push_back ( outenv + "Speed" );\r
+\r
+\r
+       vector<const IfableData*> ifs_list;\r
+       ifs_list.push_back ( &module.project.non_if_data );\r
+       ifs_list.push_back ( &module.non_if_data );\r
+       while ( ifs_list.size () )\r
+       {\r
+               const IfableData& data = *ifs_list.back();\r
+               ifs_list.pop_back();\r
+               const vector<File*>& files = data.files;\r
+               for ( i = 0; i < files.size (); i++ )\r
+               {\r
+                       string file = files[i]->name;\r
+                       string::size_type pos = file.find_last_of ("\\");\r
+                       if ( pos != string::npos )\r
+                               file.erase ( 0, pos+1 );\r
+                       if ( !stricmp ( Right(file,3).c_str(), ".rc" ) )\r
+                               file = ReplaceExtension ( file, ".res" );\r
+                       else\r
+                               file = ReplaceExtension ( file, ".obj" );\r
+                       for ( size_t j = 0; j < cfgs.size () / 2; j++ )\r
+                               out.push_back ( cfgs[j] + "\\" + file );\r
+               }\r
+\r
+       }\r
+       //common files in intermediate dir\r
+       for ( i = 0; i < cfgs.size () / 2; i++)\r
+       {\r
+               out.push_back ( cfgs[i] + "\\" + "BuildLog.htm" );\r
+               out.push_back ( cfgs[i] + "\\" + dbg + "0.pdb" );\r
+               out.push_back ( cfgs[i] + "\\" + dbg + "0.idb" );\r
+               out.push_back ( cfgs[i] + "\\" + module.name + ".pch" );\r
+       }\r
+       //files in the output dir\r
+       for ( i = cfgs.size () / 2; i < cfgs.size (); i++ )\r
+       {\r
+               out.push_back ( cfgs[i] + "\\" + module.GetTargetName () );\r
+               out.push_back ( cfgs[i] + "\\" + module.name + ".pdb" );\r
+               out.push_back ( cfgs[i] + "\\" + module.name + ".lib" );\r
+               out.push_back ( cfgs[i] + "\\" + module.name + ".exp" );\r
+               out.push_back ( cfgs[i] + "\\" + module.name + ".ilk" );\r
+               out.push_back ( cfgs[i] + "\\" + "(InputName).obj" ); //MSVC2003 build bug \r
+       }\r
+}\r
+\r
+void\r
+MSVCBackend::_clean_project_files ( void )\r
+{\r
+       for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )\r
+       {\r
+               Module& module = *ProjectNode.modules[i];\r
+               vector<string> out;\r
+               printf("Cleaning project %s %s %s\n", module.name.c_str (), module.GetBasePath ().c_str (), NcbFileName ( module ).c_str () );\r
+               \r
+               string basepath = module.GetBasePath ();\r
+               remove ( NcbFileName ( module ).c_str () );\r
+               remove ( DspFileName ( module ).c_str () );\r
+               remove ( DswFileName ( module ).c_str () );\r
+               remove ( OptFileName ( module ).c_str () );\r
+               remove ( SlnFileName ( module ).c_str () );\r
+               remove ( SuoFileName ( module ).c_str () );\r
+               remove ( VcprojFileName ( module ).c_str () );  \r
+\r
+               _get_object_files ( module, out );\r
+               for ( size_t j = 0; j < out.size (); j++)\r
+                       remove ( out[j].c_str () );\r
+       }\r
+       string filename_sln = ProjectNode.name + ".sln";\r
+       string filename_dsw = ProjectNode.name + ".dsw";\r
+\r
+       remove ( filename_sln.c_str () );\r
+       remove ( filename_dsw.c_str () );\r
+}\r
+\r
+bool\r
+MSVCBackend::_copy_file ( const std::string& inputname, const std::string& targetname ) const\r
+{\r
+  FILE * input = fopen ( inputname.c_str (), "rb" );\r
+       if ( !input )\r
+               return false;\r
+\r
+  FILE * output = fopen ( targetname.c_str (), "wb+" );\r
+  if ( !output )\r
+  {\r
+       fclose ( input );\r
+       return false;\r
+  }\r
+\r
+  char buffer[256];\r
+  int num_read;\r
+  while ( (num_read = fread( buffer, sizeof(char), 256, input) ) || !feof( input ) )\r
+               fwrite( buffer, sizeof(char), num_read, output );\r
+\r
+  fclose ( input );\r
+  fclose ( output );\r
+  return true;\r
+}\r
+\r
+void\r
+MSVCBackend::_install_files (const std::string& vcdir, const::string& config)\r
+{\r
+       for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )\r
+       {\r
+               Module& module = *ProjectNode.modules[i];\r
+               if ( module.installBase == "" || module.installName == "" )\r
+                       continue;\r
+\r
+               string inputname = Environment::GetOutputPath () + "\\" + module.GetBasePath () + "\\" + vcdir + "\\" + config + "\\" + module.GetTargetName ();\r
+               string installdir = Environment::GetInstallPath () + "\\" + module.installBase + "\\" + module.installName;\r
+               if ( _copy_file( inputname, installdir ) )\r
+                       printf ("Installed File :'%s'\n",installdir.c_str () );\r
+       }\r
+}\r