diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b56f9d047..4b3951110 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -5,7 +5,6 @@ cmake.cxx cmakewizard.cxx cmMakeDepend.cxx cmMakefile.cxx -cmMakefileGenerator.cxx cmRegularExpression.cxx cmSourceFile.cxx cmSystemTools.cxx @@ -17,6 +16,10 @@ cmCustomCommand.cxx cmCacheManager.cxx cmSourceGroup.cxx cmListFileCache.cxx +cmGlobalGenerator.cxx +cmGlobalUnixMakefileGenerator.cxx +cmLocalGenerator.cxx +cmLocalUnixMakefileGenerator.cxx cmake.h cmakewizard.h cmMakeDepend.h @@ -33,6 +36,10 @@ cmCustomCommand.h cmCacheManager.h cmSourceGroup.h cmListFileCache.h +cmGlobalGenerator.h +cmGlobalUnixMakefileGenerator.h +cmLocalGenerator.h +cmLocalUnixMakefileGenerator.h ) # configure the .h file @@ -50,18 +57,22 @@ ADD_DEFINITIONS(-DCMAKE_BUILD_WITH_CMAKE) IF (WIN32) IF(NOT UNIX) SET(SRCS ${SRCS} - cmDSWWriter.cxx - cmDSPWriter.cxx - cmMSProjectGenerator.cxx - cmBorlandMakefileGenerator.cxx - cmNMakeMakefileGenerator.cxx - cmMSDotNETGenerator.cxx - cmDSWWriter.h - cmDSPWriter.h - cmMSProjectGenerator.h - cmBorlandMakefileGenerator.h - cmNMakeMakefileGenerator.h - cmMSDotNETGenerator.h + cmGlobalBorlandMakefileGenerator.cxx + cmLocalBorlandMakefileGenerator.cxx + cmGlobalNMakeMakefileGenerator.cxx + cmLocalNMakeMakefileGenerator.cxx + cmGlobalVisualStudio6Generator.cxx + cmLocalVisualStudio6Generator.cxx + cmGlobalVisualStudio7Generator.cxx + cmLocalVisualStudio7Generator.cxx + cmGlobalBorlandMakefileGenerator.h + cmLocalBorlandMakefileGenerator.h + cmGlobalNMakeMakefileGenerator.h + cmLocalNMakeMakefileGenerator.h + cmGlobalVisualStudio6Generator.h + cmLocalVisualStudio6Generator.h + cmGlobalVisualStudio7Generator.h + cmLocalVisualStudio7Generator.h ) IF( NOT BORLAND ) LINK_LIBRARIES( rpcrt4.lib ) @@ -70,8 +81,6 @@ IF (WIN32) ENDIF(NOT UNIX) ENDIF (WIN32) -SET(SRCS ${SRCS} cmUnixMakefileGenerator.cxx cmUnixMakefileGenerator.h) - # create a library used by the command line and the GUI ADD_LIBRARY(CMakeLib ${SRCS}) @@ -111,9 +120,6 @@ CONFIGURE_FILE( ADD_EXECUTABLE(cmaketest cmaketest.cxx) TARGET_LINK_LIBRARIES(cmaketest CMakeLib) -#ADD_LIBRARY(TEST_PLUGIN SHARED cmSimpleCommandPlugin.c) -#TARGET_LINK_LIBRARIES(TEST_PLUGIN CMakeLib) - IF(BUILD_TESTING) ADD_TEST(DumpDocumentation ${CMake_BINARY_DIR}/Source/DumpDocumentation ${CMake_BINARY_DIR}/CMakeDoc.html) diff --git a/Source/MFCDialog/CMakeSetupDialog.cpp b/Source/MFCDialog/CMakeSetupDialog.cpp index 4ddca5444..fe5448705 100644 --- a/Source/MFCDialog/CMakeSetupDialog.cpp +++ b/Source/MFCDialog/CMakeSetupDialog.cpp @@ -12,7 +12,7 @@ #include "CMakeCommandLineInfo.h" #include "../cmCacheManager.h" #include "../cmake.h" -#include "../cmMakefileGenerator.h" +#include "../cmGlobalGenerator.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE @@ -52,7 +52,7 @@ class CAboutDlg : public CDialog public: CAboutDlg(); -// Dialog Data + // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA @@ -146,7 +146,7 @@ CMakeSetupDialog::CMakeSetupDialog(const CMakeCommandLineInfo& cmdInfo, m_oldCX = -1; m_deltaXRemainder = 0; - m_CMakeInstance = 0; + m_CMakeInstance = new cmake; } void CMakeSetupDialog::DoDataExchange(CDataExchange* pDX) @@ -184,15 +184,15 @@ BEGIN_MESSAGE_MAP(CMakeSetupDialog, CDialog) ON_CBN_SELCHANGE(IDC_WhereBuild, OnSelendokWhereBuild) ON_CBN_EDITCHANGE(IDC_WhereSource, OnChangeWhereSource) ON_CBN_SELENDOK(IDC_WhereSource, OnSelendokWhereSource) - ON_WM_SIZE() + ON_WM_SIZE() ON_WM_GETMINMAXINFO() - ON_BN_CLICKED(IDC_OK, OnOk) - ON_CBN_EDITCHANGE(IDC_Generator, OnEditchangeGenerator) - ON_BN_CLICKED(IDC_HELP_BUTTON, OnHelpButton) + ON_BN_CLICKED(IDC_OK, OnOk) + ON_CBN_EDITCHANGE(IDC_Generator, OnEditchangeGenerator) + ON_BN_CLICKED(IDC_HELP_BUTTON, OnHelpButton) ON_BN_CLICKED(IDCANCEL, OnCancel) - ON_BN_CLICKED(IDC_AdvancedValues, OnAdvancedValues) - ON_BN_DOUBLECLICKED(IDC_AdvancedValues, OnDoubleclickedAdvancedValues) - //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_AdvancedValues, OnAdvancedValues) + ON_BN_DOUBLECLICKED(IDC_AdvancedValues, OnDoubleclickedAdvancedValues) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// @@ -245,7 +245,6 @@ BOOL CMakeSetupDialog::OnInitDialog() SetIcon(m_hIcon, FALSE); // Set small icon // Load source and build dirs from registry this->LoadFromRegistry(); - this->m_CMakeInstance = new cmake; std::vector names; this->m_CMakeInstance->GetRegisteredGenerators(names); for(std::vector::iterator i = names.begin(); @@ -266,8 +265,8 @@ BOOL CMakeSetupDialog::OnInitDialog() // Set the version number char tmp[1024]; - sprintf(tmp,"Version %d.%d - %s", cmMakefile::GetMajorVersion(), - cmMakefile::GetMinorVersion(), cmMakefile::GetReleaseVersion()); + sprintf(tmp,"Version %d.%d - %s", cmake::GetMajorVersion(), + cmake::GetMinorVersion(), cmake::GetReleaseVersion()); SetDlgItemText(IDC_CMAKE_VERSION, tmp); this->UpdateData(FALSE); return TRUE; // return TRUE unless you set the focus to a control @@ -560,38 +559,37 @@ void CMakeSetupDialog::RunCMake(bool generateProjectFiles) this->UpdateData(); // always save the current gui values to disk this->SaveCacheFromGUI(); - // free the old cmake and create a new one here - if (this->m_CMakeInstance) - { - delete this->m_CMakeInstance; - this->m_CMakeInstance = 0; - } - this->m_CMakeInstance = new cmake; // Make sure we are working from the cache on disk this->LoadCacheFromDiskToGUI(); m_OKButton.EnableWindow(false); - // create the arguments for the cmake object - std::vector args; - args.push_back((const char*)m_PathToExecutable); - std::string arg; - arg = "-H"; - arg += m_WhereSource; - args.push_back(arg); - arg = "-B"; - arg += m_WhereBuild; - args.push_back(arg); - arg = "-G"; - arg += m_GeneratorChoiceString; - args.push_back(arg); - // run the generate process - if(this->m_CMakeInstance->Generate(args, generateProjectFiles) != 0) + + // setup the cmake instance + if (generateProjectFiles) { - cmSystemTools::Error( - "Error in generation process, project files may be invalid"); + if(m_CMakeInstance->Generate() != 0) + { + cmSystemTools::Error( + "Error in generation process, project files may be invalid"); + } } - // update the GUI with any new values in the caused by the - // generation process - this->LoadCacheFromDiskToGUI(); + else + { + m_CMakeInstance->SetHomeDirectory(m_WhereSource); + m_CMakeInstance->SetStartDirectory(m_WhereSource); + m_CMakeInstance->SetHomeOutputDirectory(m_WhereBuild); + m_CMakeInstance->SetStartOutputDirectory(m_WhereBuild); + m_CMakeInstance->SetGlobalGenerator( + m_CMakeInstance->CreateGlobalGenerator(m_GeneratorChoiceString)); + if(m_CMakeInstance->Configure(m_PathToExecutable) != 0) + { + cmSystemTools::Error( + "Error in configuration process, project files may be invalid"); + } + // update the GUI with any new values in the caused by the + // generation process + this->LoadCacheFromDiskToGUI(); + } + // save source and build paths to registry this->SaveToRegistry(); // path is up-to-date now @@ -647,6 +645,11 @@ void CMakeSetupDialog::OnChangeWhereBuild() std::string path = this->m_WhereBuild; cmSystemTools::ConvertToUnixSlashes(path); + + // adjust the cmake instance + m_CMakeInstance->SetHomeOutputDirectory(m_WhereBuild); + m_CMakeInstance->SetStartOutputDirectory(m_WhereBuild); + std::string cache_file = path; cache_file += "/CMakeCache.txt"; diff --git a/Source/MFCDialog/CMakeSetupDialog.h b/Source/MFCDialog/CMakeSetupDialog.h index 21ff68d5c..67ff286b1 100644 --- a/Source/MFCDialog/CMakeSetupDialog.h +++ b/Source/MFCDialog/CMakeSetupDialog.h @@ -55,7 +55,7 @@ protected: const char *aadefault); void ShowAdvancedValues(); void RemoveAdvancedValues(); -// Dialog Data + // Dialog Data //{{AFX_DATA(CMakeSetupDialog) enum { IDD = IDD_CMakeSetupDialog_DIALOG }; CButton m_HelpButton; diff --git a/Source/Makefile.in b/Source/Makefile.in index 9d1a6de4b..d44e29f3a 100644 --- a/Source/Makefile.in +++ b/Source/Makefile.in @@ -19,12 +19,14 @@ cmakewizard.o \ cmakemain.o \ cmMakeDepend.o \ cmMakefile.o \ -cmMakefileGenerator.o \ +cmGlobalGenerator.o \ +cmLocalGenerator.o \ cmRegularExpression.o \ cmSourceFile.o \ cmSystemTools.o \ cmDirectory.o \ -cmUnixMakefileGenerator.o \ +cmGlobalUnixMakefileGenerator.o \ +cmLocalUnixMakefileGenerator.o \ cmCommands.o \ cmTarget.o \ cmCustomCommand.o \ @@ -39,13 +41,15 @@ cmake.o : $(DEPENDS) cmakemain.o : $(DEPENDS) cmMakeDepend.o : $(DEPENDS) cmMakefile.o : $(DEPENDS) -cmMakefileGenerator.o : $(DEPENDS) +cmGlobalGenerator.o : $(DEPENDS) +cmLocalGenerator.o : $(DEPENDS) cmAuxSourceDirectoryCommand.o : $(DEPENDS) cmRegularExpression.o : $(DEPENDS) cmSourceFile.o : $(DEPENDS) cmDirectory.o : $(DEPENDS) cmCustomCommand.o : $(DEPENDS) -cmUnixMakefileGenerator.o : $(DEPENDS) +cmGlobalUnixMakefileGenerator.o : $(DEPENDS) +cmLocalUnixMakefileGenerator.o : $(DEPENDS) cmCommands.o : $(DEPENDS) $(srcdir)/*Command*.cxx cmTarget.o : $(DEPENDS) cmCacheManager.o : $(DEPENDS) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 19f4f9a2a..14239a74b 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -52,6 +52,9 @@ void cmGlobalGenerator::ClearEnabledLanguages() void cmGlobalGenerator::Configure() { + // reset theLanguages + m_LanguagesEnabled = false; + // Delete any existing cmLocalGenerators int i; for (i = 0; i < m_LocalGenerators.size(); ++i) @@ -65,8 +68,8 @@ void cmGlobalGenerator::Configure() m_LocalGenerators.push_back(lg); // set the Start directories - lg->GetMakefile()->SetStartDirectory(m_CMakeInstance->GetHomeDirectory()); - lg->GetMakefile()->SetStartOutputDirectory(m_CMakeInstance->GetHomeOutputDirectory()); + lg->GetMakefile()->SetStartDirectory(m_CMakeInstance->GetStartDirectory()); + lg->GetMakefile()->SetStartOutputDirectory(m_CMakeInstance->GetStartOutputDirectory()); lg->GetMakefile()->MakeStartDirectoriesCurrent(); // now do it @@ -124,8 +127,8 @@ void cmGlobalGenerator::LocalGenerate() cmLocalGenerator *lg = this->CreateLocalGenerator(); // set the Start directories - lg->GetMakefile()->SetStartDirectory(m_CMakeInstance->GetHomeDirectory()); - lg->GetMakefile()->SetStartOutputDirectory(m_CMakeInstance->GetHomeOutputDirectory()); + lg->GetMakefile()->SetStartDirectory(m_CMakeInstance->GetStartDirectory()); + lg->GetMakefile()->SetStartOutputDirectory(m_CMakeInstance->GetStartOutputDirectory()); lg->GetMakefile()->MakeStartDirectoriesCurrent(); // now do trhe configure diff --git a/Source/cmGlobalUnixMakefileGenerator.cxx b/Source/cmGlobalUnixMakefileGenerator.cxx index 0f2a370d2..d3dd4e97d 100644 --- a/Source/cmGlobalUnixMakefileGenerator.cxx +++ b/Source/cmGlobalUnixMakefileGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGlobalUnixMakefileGenerator.h" #include "cmLocalUnixMakefileGenerator.h" #include "cmMakefile.h" +#include "cmake.h" void cmGlobalUnixMakefileGenerator::EnableLanguage(const char* lang, cmMakefile *mf) @@ -25,58 +26,68 @@ void cmGlobalUnixMakefileGenerator::EnableLanguage(const char* lang, { m_LanguagesEnabled = true; - // see man putenv for explaination of this stupid code.... - static char envCXX[5000]; - static char envCC[5000]; - if(mf->GetDefinition("CMAKE_CXX_COMPILER")) + // only do for global runs + if (!m_CMakeInstance->GetLocal()) { - std::string env = "CXX=${CMAKE_CXX_COMPILER}"; - mf->ExpandVariablesInString(env); - strncpy(envCXX, env.c_str(), 4999); - envCXX[4999] = 0; - putenv(envCXX); - } - if(mf->GetDefinition("CMAKE_C_COMPILER")) - { - std::string env = "CC=${CMAKE_C_COMPILER}"; - mf->ExpandVariablesInString(env); - strncpy(envCC, env.c_str(), 4999); - envCC[4999] = 0; - putenv(envCC); - } - std::string output; - std::string root - = cmSystemTools::ConvertToOutputPath(mf->GetDefinition("CMAKE_ROOT")); - // if no lang specified use CXX - if(!lang ) - { - lang = "CXX"; - } - // if CXX or C, then enable C - if((!this->GetLanguageEnabled(lang) && lang[0] == 'C')) - { - std::string cmd = root; - cmd += "/Templates/cconfigure"; - cmSystemTools::RunCommand(cmd.c_str(), output, - cmSystemTools::ConvertToOutputPath(mf->GetHomeOutputDirectory()).c_str()); - std::string fpath = mf->GetHomeOutputDirectory(); - fpath += "/CCMakeSystemConfig.cmake"; - mf->ReadListFile(NULL,fpath.c_str()); - this->SetLanguageEnabled("C"); - } - // if CXX - if(!this->GetLanguageEnabled(lang) || strcmp(lang, "CXX") == 0) - { - std::string cmd = root; - cmd += "/Templates/cxxconfigure"; - cmSystemTools::RunCommand(cmd.c_str(), output, - cmSystemTools::ConvertToOutputPath(mf->GetHomeOutputDirectory()).c_str()); - std::string fpath = mf->GetHomeOutputDirectory(); - fpath += "/CXXCMakeSystemConfig.cmake"; - mf->ReadListFile(NULL,fpath.c_str()); - this->SetLanguageEnabled("CXX"); + // see man putenv for explaination of this stupid code.... + static char envCXX[5000]; + static char envCC[5000]; + if(mf->GetDefinition("CMAKE_CXX_COMPILER")) + { + std::string env = "CXX=${CMAKE_CXX_COMPILER}"; + mf->ExpandVariablesInString(env); + strncpy(envCXX, env.c_str(), 4999); + envCXX[4999] = 0; + putenv(envCXX); + } + if(mf->GetDefinition("CMAKE_C_COMPILER")) + { + std::string env = "CC=${CMAKE_C_COMPILER}"; + mf->ExpandVariablesInString(env); + strncpy(envCC, env.c_str(), 4999); + envCC[4999] = 0; + putenv(envCC); + } + std::string output; + std::string root + = cmSystemTools::ConvertToOutputPath(mf->GetDefinition("CMAKE_ROOT")); + // if no lang specified use CXX + if(!lang ) + { + lang = "CXX"; + } + // if CXX or C, then enable C + if((!this->GetLanguageEnabled(lang) && lang[0] == 'C')) + { + std::string cmd = root; + cmd += "/Templates/cconfigure"; + cmSystemTools::RunCommand(cmd.c_str(), output, + cmSystemTools::ConvertToOutputPath(mf->GetHomeOutputDirectory()).c_str()); + std::string fpath = mf->GetHomeOutputDirectory(); + fpath += "/CCMakeSystemConfig.cmake"; + mf->ReadListFile(NULL,fpath.c_str()); + this->SetLanguageEnabled("C"); + } + // if CXX + if(!this->GetLanguageEnabled(lang) || strcmp(lang, "CXX") == 0) + { + std::string cmd = root; + cmd += "/Templates/cxxconfigure"; + cmSystemTools::RunCommand(cmd.c_str(), output, + cmSystemTools::ConvertToOutputPath(mf->GetHomeOutputDirectory()).c_str()); + std::string fpath = mf->GetHomeOutputDirectory(); + fpath += "/CXXCMakeSystemConfig.cmake"; + mf->ReadListFile(NULL,fpath.c_str()); + this->SetLanguageEnabled("CXX"); + } } } + + if (!m_CMakeInstance->GetLocal()) + { + // if we are from the top, always define this + mf->AddDefinition("RUN_CONFIGURE", true); + } } ///! Create a local generator appropriate to this Global Generator diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 76cf511f6..2d4876e90 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/Source/cmLocalUnixMakefileGenerator.cxx @@ -97,7 +97,9 @@ void cmLocalUnixMakefileGenerator::Generate(bool fromTheTop) this->ProcessDepends(md); } // output the makefile fragment - this->OutputMakefile("Makefile", !fromTheTop); + std::string dest = m_Makefile->GetStartOutputDirectory(); + dest += "/Makefile"; + this->OutputMakefile(dest.c_str(), !fromTheTop); } void cmLocalUnixMakefileGenerator::ProcessDepends(const cmMakeDepend &md) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ba036c29e..14ad15c4b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -20,7 +20,8 @@ #include "cmSourceFile.h" #include "cmDirectory.h" #include "cmSystemTools.h" -#include "cmMakefileGenerator.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" #include "cmCommands.h" #include "cmCacheManager.h" #include "cmFunctionBlocker.h" @@ -48,8 +49,7 @@ cmMakefile::cmMakefile() m_HeaderFileExtensions.push_back( "in" ); m_DefineFlags = " "; - m_MakefileGenerator = 0; - m_CacheManager = 0; + m_LocalGenerator = 0; this->AddSourceGroup("", "^.*$"); this->AddSourceGroup("Source Files", "\\.(cpp|C|c|cxx|rc|def|r|odl|idl|hpj|bat)$"); this->AddSourceGroup("Header Files", "\\.(h|hh|hpp|hxx|hm|inl)$"); @@ -59,20 +59,20 @@ cmMakefile::cmMakefile() unsigned int cmMakefile::GetCacheMajorVersion() { - if(!this->m_CacheManager->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION")) + if(!this->GetCacheManager()->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION")) { return 0; } - return atoi(this->m_CacheManager->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION")); + return atoi(this->GetCacheManager()->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION")); } unsigned int cmMakefile::GetCacheMinorVersion() { - if(!this->m_CacheManager->GetCacheValue("Cmake_Cache_MINOR_VERSION")) + if(!this->GetCacheManager()->GetCacheValue("Cmake_Cache_MINOR_VERSION")) { return 0; } - return atoi(this->m_CacheManager->GetCacheValue("CMAKE_CACHE_MINOR_VERSION")); + return atoi(this->GetCacheManager()->GetCacheValue("CMAKE_CACHE_MINOR_VERSION")); } @@ -132,7 +132,6 @@ cmMakefile::~cmMakefile() m_FunctionBlockers.remove(*pos); delete b; } - delete m_MakefileGenerator; } void cmMakefile::PrintStringVector(const char* s, const std::vector& v) const @@ -384,15 +383,9 @@ void cmMakefile::AddCommand(cmCommand* wg) } // Set the make file -void cmMakefile::SetMakefileGenerator(cmMakefileGenerator* mf) +void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg) { - if(mf == m_MakefileGenerator) - { - return; - } - delete m_MakefileGenerator; - m_MakefileGenerator = mf; - mf->SetMakefile(this); + m_LocalGenerator = lg; } void cmMakefile::FinalPass() @@ -430,8 +423,6 @@ void cmMakefile::GenerateMakefile() } l->second.AnalyzeLibDependencies(*this); } - // now do the generation - m_MakefileGenerator->GenerateMakefile(); } @@ -462,10 +453,10 @@ void cmMakefile::AddCustomCommand(const char* source, m_Targets[target].GetCustomCommands().push_back(cc); std::string cacheCommand = command; this->ExpandVariablesInString(cacheCommand); - if(this->m_CacheManager->GetCacheValue(cacheCommand.c_str())) + if(this->GetCacheManager()->GetCacheValue(cacheCommand.c_str())) { m_Targets[target].AddUtility( - this->m_CacheManager->GetCacheValue(cacheCommand.c_str())); + this->GetCacheManager()->GetCacheValue(cacheCommand.c_str())); } } } @@ -596,7 +587,7 @@ void cmMakefile::AddCacheDefinition(const char* name, const char* value, const char* doc, cmCacheManager::CacheEntryType type) { - this->m_CacheManager->AddCacheEntry(name, value, doc, type); + this->GetCacheManager()->AddCacheEntry(name, value, doc, type); this->AddDefinition(name, value); } @@ -618,7 +609,7 @@ void cmMakefile::AddDefinition(const char* name, bool value) void cmMakefile::AddCacheDefinition(const char* name, bool value, const char* doc) { - this->m_CacheManager->AddCacheEntry(name, value, doc); + this->GetCacheManager()->AddCacheEntry(name, value, doc); this->AddDefinition(name, value); } @@ -671,7 +662,7 @@ void cmMakefile::AddLibrary(const char* lname, int shared, // hence useless. std::string depname = lname; depname += "_LIB_DEPENDS"; - this->m_CacheManager-> + this->GetCacheManager()-> AddCacheEntry(depname.c_str(), "", "Dependencies for target", cmCacheManager::STATIC); @@ -684,7 +675,7 @@ void cmMakefile::AddLibrary(const char* lname, int shared, // Add an entry into the cache std::string libPath = lname; libPath += "_CMAKE_PATH"; - this->m_CacheManager-> + this->GetCacheManager()-> AddCacheEntry(libPath.c_str(), this->GetCurrentOutputDirectory(), "Path to a library", cmCacheManager::INTERNAL); @@ -695,26 +686,26 @@ void cmMakefile::AddLibrary(const char* lname, int shared, switch (shared) { case 0: - this->m_CacheManager->AddCacheEntry(ltname.c_str(),"STATIC", + this->GetCacheManager()->AddCacheEntry(ltname.c_str(),"STATIC", "Whether a library is static, shared or module.", cmCacheManager::INTERNAL); break; case 1: - this->m_CacheManager-> + this->GetCacheManager()-> AddCacheEntry(ltname.c_str(), "SHARED", "Whether a library is static, shared or module.", cmCacheManager::INTERNAL); break; case 2: - this->m_CacheManager-> + this->GetCacheManager()-> AddCacheEntry(ltname.c_str(), "MODULE", "Whether a library is static, shared or module.", cmCacheManager::INTERNAL); break; default: - this->m_CacheManager-> + this->GetCacheManager()-> AddCacheEntry(ltname.c_str(), "STATIC", "Whether a library is static, shared or module.", @@ -751,7 +742,7 @@ void cmMakefile::AddExecutable(const char *exeName, // Add an entry into the cache std::string exePath = exeName; exePath += "_CMAKE_PATH"; - this->m_CacheManager-> + this->GetCacheManager()-> AddCacheEntry(exePath.c_str(), this->GetCurrentOutputDirectory(), "Path to an executable", cmCacheManager::INTERNAL); @@ -904,7 +895,7 @@ const char* cmMakefile::GetDefinition(const char* name) const { return (*pos).second.c_str(); } - return this->m_CacheManager->GetCacheValue(name); + return this->GetCacheManager()->GetCacheValue(name); } int cmMakefile::DumpDocumentationToFile(std::ostream& f) @@ -1126,59 +1117,6 @@ void cmMakefile::RemoveVariablesInString(std::string& source, } } -// recursive function to create a vector of cmMakefile objects -// This is done by reading the sub directory CMakeLists.txt files, -// then calling this function with the new cmMakefile object -void -cmMakefile::FindSubDirectoryCMakeListsFiles(std::vector& makefiles) -{ - // loop over all the sub directories of this makefile - const std::vector& subdirs = this->GetSubDirectories(); - for(std::vector::const_iterator i = subdirs.begin(); - i != subdirs.end(); ++i) - { - std::string subdir = *i; - // Create a path to the list file in the sub directory - std::string listFile = this->GetCurrentDirectory(); - listFile += "/"; - listFile += subdir; - listFile += "/CMakeLists.txt"; - // if there is a CMakeLists.txt file read it - if(!cmSystemTools::FileExists(listFile.c_str())) - { - cmSystemTools::Error("CMakeLists.txt file missing from sub directory:", - listFile.c_str()); - } - else - { - cmMakefile* mf = new cmMakefile; - mf->SetMakefileGenerator(m_MakefileGenerator->CreateObject()); - mf->SetCacheManager(this->m_CacheManager); - makefiles.push_back(mf); - // initialize new makefile - mf->SetHomeOutputDirectory(this->GetHomeOutputDirectory()); - mf->SetHomeDirectory(this->GetHomeDirectory()); - // add the subdir to the start output directory - std::string outdir = this->GetStartOutputDirectory(); - outdir += "/"; - outdir += subdir; - mf->SetStartOutputDirectory(outdir.c_str()); - // add the subdir to the start source directory - std::string currentDir = this->GetStartDirectory(); - currentDir += "/"; - currentDir += subdir; - mf->SetStartDirectory(currentDir.c_str()); - // Parse the CMakeLists.txt file - currentDir += "/CMakeLists.txt"; - mf->MakeStartDirectoriesCurrent(); - mf->ReadListFile(currentDir.c_str()); - // recurse into nextDir - mf->FindSubDirectoryCMakeListsFiles(makefiles); - } - } -} - - /** * Add the default definitions to the makefile. These values must not * be dependent on anything that isn't known when this cmMakefile instance @@ -1399,7 +1337,7 @@ cmSourceFile* cmMakefile::AddSource(cmSourceFile const&sf) void cmMakefile::EnableLanguage(const char* lang) { - m_MakefileGenerator->EnableLanguage(lang); + m_LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this); } void cmMakefile::ExpandSourceListArguments( @@ -1437,7 +1375,7 @@ void cmMakefile::ExpandSourceListArguments( int cmMakefile::TryCompile(const char *srcdir, const char *bindir, const char *projectName) { - if (!m_MakefileGenerator) + if (!m_LocalGenerator) { cmSystemTools::Error("Internal CMake error, Attempt to call Try Compile without the generator being set"); return 1; @@ -1454,43 +1392,58 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir, std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::ChangeDirectory(bindir); - std::vector args; - // make sure the same generator is used // use this program as the cmake to be run, it should not // be run that way but the cmake object requires a vailid path std::string cmakeCommand = this->GetDefinition("CMAKE_COMMAND"); - args.push_back(cmakeCommand.c_str()); - args.push_back(srcdir); - - std::string generator = "-G"; - generator += this->GetDefinition("CMAKE_GENERATOR"); - args.push_back(generator); - cmake cm; - if (cm.Generate(args) != 0) + cmGlobalGenerator *gg = + cm.CreateGlobalGenerator(this->GetDefinition("CMAKE_GENERATOR")); + if (!gg) { cmSystemTools::Error( - "Internal CMake error, TryCompile execution of cmake failed"); + "Internal CMake error, TryCompile bad GlobalGenerator"); + // return to the original directory + cmSystemTools::ChangeDirectory(cwd.c_str()); + return 1; + } + + // do a configure + cm.SetHomeDirectory(srcdir); + cm.SetHomeOutputDirectory(bindir); + cm.SetStartDirectory(srcdir); + cm.SetStartOutputDirectory(bindir); + + if (cm.Configure(cmakeCommand.c_str()) != 0) + { + cmSystemTools::Error( + "Internal CMake error, TryCompile configure of cmake failed"); // return to the original directory cmSystemTools::ChangeDirectory(cwd.c_str()); return 1; } - cmake cm2; - if (cm2.Generate(args) != 0) + if (cm.Generate() != 0) { cmSystemTools::Error( - "Internal CMake error, TryCompile execution of cmake failed"); + "Internal CMake error, TryCompile generation of cmake failed"); // return to the original directory cmSystemTools::ChangeDirectory(cwd.c_str()); return 1; } // finally call the generator to actually build the resulting project - m_MakefileGenerator->TryCompile(srcdir,bindir,projectName); - cmSystemTools::ChangeDirectory(cwd.c_str()); + gg->TryCompile(srcdir,bindir,projectName); + cmSystemTools::ChangeDirectory(cwd.c_str()); return 0; } +cmCacheManager *cmMakefile::GetCacheManager() const +{ + if (m_LocalGenerator) + { + return m_LocalGenerator->GetGlobalGenerator()->GetCMakeInstance()->GetCacheManager(); + } + return 0; +} diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 4b3bbe3b4..1deee8ef7 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -27,7 +27,7 @@ class cmFunctionBlocker; class cmCommand; -class cmMakefileGenerator; +class cmLocalGenerator; class cmMakeDepend; /** \class cmMakefile @@ -96,11 +96,11 @@ public: * dependent, although the interface is through a generic * superclass. */ - void SetMakefileGenerator(cmMakefileGenerator*); + void SetLocalGenerator(cmLocalGenerator*); ///! Get the current makefile generator. - cmMakefileGenerator* GetMakefileGenerator() - { return m_MakefileGenerator;} + cmLocalGenerator* GetLocalGenerator() + { return m_LocalGenerator;} /** * Produce the output makefile. @@ -485,15 +485,6 @@ public: */ void ExpandVariables(); - /** Recursivly read and create a cmMakefile object for - * all CMakeLists.txt files in the GetSubDirectories list. - * Once the file is found, it ReadListFile is called on - * the cmMakefile created for it. CreateObject is called on - * the prototype to create a cmMakefileGenerator for each cmMakefile that - * is created. - */ - void FindSubDirectoryCMakeListsFiles(std::vector& makefiles); - /** * find what source group this source is in */ @@ -519,14 +510,9 @@ public: * Set/Get the name of the parent directories CMakeLists file * given a current CMakeLists file name */ - void SetCacheManager(cmCacheManager *cm) { - this->m_CacheManager = cm; } - cmCacheManager *GetCacheManager() { - return m_CacheManager; } + cmCacheManager *GetCacheManager() const; protected: - cmCacheManager *m_CacheManager; - // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -573,7 +559,7 @@ protected: DefinitionMap m_Definitions; RegisteredCommandsMap m_Commands; std::vector m_UsedCommands; - cmMakefileGenerator* m_MakefileGenerator; + cmLocalGenerator* m_LocalGenerator; bool IsFunctionBlocked(const char *name, std::vector const& args); private: diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1772835a8..2b9864a59 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -17,39 +17,34 @@ #include "cmake.h" #include "time.h" #include "cmCacheManager.h" +#include "cmMakefile.h" +#include "cmLocalGenerator.h" // include the generator #if defined(_WIN32) && !defined(__CYGWIN__) -#include "cmMSProjectGenerator.h" -#include "cmMSDotNETGenerator.h" -#include "cmBorlandMakefileGenerator.h" -#include "cmNMakeMakefileGenerator.h" +#include "cmGlobalVisualStudio6Generator.h" +#include "cmGlobalVisualStudio7Generator.h" +#include "cmGlobalBorlandMakefileGenerator.h" +#include "cmGlobalNMakeMakefileGenerator.h" #else -#include "cmUnixMakefileGenerator.h" +#include "cmGlobalUnixMakefileGenerator.h" #endif cmake::cmake() { m_Verbose = false; -#if defined(_WIN32) && !defined(__CYGWIN__) - this->RegisterGenerator(new cmMSProjectGenerator); - this->RegisterGenerator(new cmMSDotNETGenerator); - this->RegisterGenerator(new cmNMakeMakefileGenerator); - this->RegisterGenerator(new cmBorlandMakefileGenerator); -#else - this->RegisterGenerator(new cmUnixMakefileGenerator); -#endif + m_CacheManager = new cmCacheManager; + m_GlobalGenerator = 0; } cmake::~cmake() { - for(std::map::iterator i - = m_RegisteredGenerators.begin(); - i != m_RegisteredGenerators.end(); ++i) + delete m_CacheManager; + if (m_GlobalGenerator) { - delete i->second; + delete m_GlobalGenerator; + m_GlobalGenerator = 0; } - m_RegisteredGenerators = std::map(); } @@ -79,8 +74,7 @@ void cmake::Usage(const char* program) } // Parse the args -void cmake::SetCacheArgs(cmMakefile& builder, - const std::vector& args) +void cmake::SetCacheArgs(const std::vector& args) { for(unsigned int i=1; i < args.size(); ++i) { @@ -92,9 +86,7 @@ void cmake::SetCacheArgs(cmMakefile& builder, cmCacheManager::CacheEntryType type; if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type)) { - this->m_CacheManager.AddCacheEntry( - var.c_str(), - value.c_str(), + this->m_CacheManager->AddCacheEntry(var.c_str(), value.c_str(), "No help, variable specified on the command line.", type); } @@ -108,17 +100,46 @@ void cmake::SetCacheArgs(cmMakefile& builder, { std::string path = arg.substr(2); std::cerr << "loading initial cache file " << path.c_str() << "\n"; - if(!builder.ReadListFile(path.c_str())) - { - std::cerr << "Error in reading cmake initial cache file:" - << path.c_str() << "\n"; - } + this->ReadListFile(path.c_str()); } } } +void cmake::ReadListFile(const char *path) +{ + // if a generator was not yet created, temporarily create one + cmGlobalGenerator *gg = this->GetGlobalGenerator(); + bool created; + + // if a generator was not specified use a generic one + if (!gg) + { + gg = new cmGlobalGenerator; + gg->SetCMakeInstance(this); + created = true; + } + + // read in the list file to fill the cache + if(path) + { + cmLocalGenerator *lg = gg->CreateLocalGenerator(); + lg->SetGlobalGenerator(gg); + if (!lg->GetMakefile()->ReadListFile(path)) + { + std::cerr << "Error in reading cmake initial cache file:" + << path << "\n"; + } + } + + // free generic one if generated + if (created) + { + delete gg; + } +} + // Parse the args -void cmake::SetArgs(cmMakefile& builder, const std::vector& args) +void cmake::SetArgs(const std::vector& args) { m_Local = false; bool directoriesSet = false; @@ -126,22 +147,22 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector& args) if (args.size() <= 2) { directoriesSet = true; - builder.SetHomeOutputDirectory + this->SetHomeOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetStartOutputDirectory + this->SetStartOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); if (args.size() == 2) { - builder.SetHomeDirectory + this->SetHomeDirectory (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str()); - builder.SetStartDirectory + this->SetStartDirectory (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str()); } else { - builder.SetHomeDirectory + this->SetHomeDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetStartDirectory + this->SetStartDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); } } @@ -153,26 +174,26 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector& args) { directoriesSet = true; std::string path = arg.substr(2); - builder.SetHomeDirectory(path.c_str()); + this->SetHomeDirectory(path.c_str()); } else if(arg.find("-S",0) == 0) { directoriesSet = true; m_Local = true; std::string path = arg.substr(2); - builder.SetStartDirectory(path.c_str()); + this->SetStartDirectory(path.c_str()); } else if(arg.find("-O",0) == 0) { directoriesSet = true; std::string path = arg.substr(2); - builder.SetStartOutputDirectory(path.c_str()); + this->SetStartOutputDirectory(path.c_str()); } else if(arg.find("-B",0) == 0) { directoriesSet = true; std::string path = arg.substr(2); - builder.SetHomeOutputDirectory(path.c_str()); + this->SetHomeOutputDirectory(path.c_str()); } else if(arg.find("-V",0) == 0) { @@ -189,8 +210,8 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector& args) else if(arg.find("-G",0) == 0) { std::string value = arg.substr(2); - cmMakefileGenerator* gen = - this->CreateGenerator(value.c_str()); + cmGlobalGenerator* gen = + this->CreateGlobalGenerator(value.c_str()); if(!gen) { cmSystemTools::Error("Could not create named generator ", @@ -198,47 +219,47 @@ void cmake::SetArgs(cmMakefile& builder, const std::vector& args) } else { - builder.SetMakefileGenerator(gen); + this->SetGlobalGenerator(gen); } } // no option assume it is the path to the source else { directoriesSet = true; - builder.SetHomeOutputDirectory + this->SetHomeOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetStartOutputDirectory + this->SetStartOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetHomeDirectory + this->SetHomeDirectory (cmSystemTools::CollapseFullPath(arg.c_str()).c_str()); - builder.SetStartDirectory + this->SetStartDirectory (cmSystemTools::CollapseFullPath(arg.c_str()).c_str()); } } if(!directoriesSet) { - builder.SetHomeOutputDirectory + this->SetHomeOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetStartOutputDirectory + this->SetStartOutputDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetHomeDirectory + this->SetHomeDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - builder.SetStartDirectory + this->SetStartDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); } if (!m_Local) { - builder.SetStartDirectory(builder.GetHomeDirectory()); - builder.SetStartOutputDirectory(builder.GetHomeOutputDirectory()); + this->SetStartDirectory(this->GetHomeDirectory()); + this->SetStartOutputDirectory(this->GetHomeOutputDirectory()); } } // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache -int cmake::AddCMakePaths(const std::vector& args) +int cmake::AddCMakePaths(const char *arg0) { // Find our own executable. std::vector failures; - std::string cMakeSelf = args[0]; + std::string cMakeSelf = arg0; cmSystemTools::ConvertToUnixSlashes(cMakeSelf); failures.push_back(cMakeSelf); cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str()); @@ -268,7 +289,7 @@ int cmake::AddCMakePaths(const std::vector& args) failures.push_back(cMakeSelf); cmStringStream msg; msg << "CMAKE can not find the command line program cmake.\n"; - msg << " argv[0] = \"" << args[0].c_str() << "\"\n"; + msg << " argv[0] = \"" << arg0 << "\"\n"; msg << " Attempted paths:\n"; std::vector::iterator i; for(i=failures.begin(); i != failures.end(); ++i) @@ -279,7 +300,7 @@ int cmake::AddCMakePaths(const std::vector& args) return 0; } // Save the value in the cache - this->m_CacheManager.AddCacheEntry + this->m_CacheManager->AddCacheEntry ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.", cmCacheManager::INTERNAL); @@ -293,7 +314,7 @@ int cmake::AddCMakePaths(const std::vector& args) } if(cmSystemTools::FileExists(editCacheCommand.c_str())) { - this->m_CacheManager.AddCacheEntry + this->m_CacheManager->AddCacheEntry ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), "Path to cache edit program executable.", cmCacheManager::INTERNAL); } @@ -363,7 +384,7 @@ int cmake::AddCMakePaths(const std::vector& args) modules.c_str()); return 0; } - this->m_CacheManager.AddCacheEntry + this->m_CacheManager->AddCacheEntry ("CMAKE_ROOT", cMakeRoot.c_str(), "Path to CMake installation.", cmCacheManager::INTERNAL); return 1; @@ -371,182 +392,6 @@ int cmake::AddCMakePaths(const std::vector& args) -int cmake::Generate(const std::vector& args, bool buildMakefiles) -{ - if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt")) - { - this->Usage(args[0].c_str()); - return -1; - } - // look for obvious request for help - for(unsigned int i=1; i < args.size(); ++i) - { - std::string arg = args[i]; - if(arg.find("-help",0) != std::string::npos || - arg.find("--help",0) != std::string::npos || - arg.find("/?",0) != std::string::npos || - arg.find("-usage",0) != std::string::npos) - { - this->Usage(args[0].c_str()); - return -1; - } - } - // Create a makefile - cmMakefile mf; - mf.SetCacheManager(&this->m_CacheManager); - - // extract the directory arguments, could create a Generator - this->SetArgs(mf, args); - // Read and parse the input makefile - mf.MakeStartDirectoriesCurrent(); - this->m_CacheManager.LoadCache(&mf); - if(mf.GetDefinition("CMAKE_HOME_DIRECTORY")) - { - std::string cacheStart = mf.GetDefinition("CMAKE_HOME_DIRECTORY"); - cacheStart += "/CMakeLists.txt"; - std::string currentStart = mf.GetHomeDirectory(); - currentStart += "/CMakeLists.txt"; - if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str())) - { - std::string message = "Error: source : "; - message += currentStart; - message += "\nDoes not match source used to generate cache: "; - message += cacheStart; - message += "\nRe-run cmake with a different source directory."; - cmSystemTools::Error(message.c_str()); - return -2; - } - } - mf.AddCacheDefinition("CMAKE_HOME_DIRECTORY", mf.GetHomeDirectory(), - "Start directory with the top level CMakeLists.txt file for this project", - cmCacheManager::INTERNAL); - - // extract command line arguments that might add cache entries - this->SetCacheArgs(mf, args); - - // no generator specified on the command line - if(!mf.GetMakefileGenerator()) - { - cmMakefileGenerator* gen; - const char* genName = mf.GetDefinition("CMAKE_GENERATOR"); - if(genName) - { - gen = this->CreateGenerator(genName); - } - else - { -#if defined(__BORLANDC__) - gen = new cmBorlandMakefileGenerator; -#elif defined(_WIN32) && !defined(__CYGWIN__) - gen = new cmMSProjectGenerator; -#else - gen = new cmUnixMakefileGenerator; -#endif - } - if(!gen) - { - cmSystemTools::Error("Could not create generator"); - return -1; - } - mf.SetMakefileGenerator(gen); - // add the - } - cmMakefileGenerator* gen = mf.GetMakefileGenerator(); - gen->SetLocal(m_Local); - const char* genName = mf.GetDefinition("CMAKE_GENERATOR"); - if(genName) - { - if(strcmp(gen->GetName(), genName) != 0) - { - std::string message = "Error: generator : "; - message += gen->GetName(); - message += "\nDoes not match the generator used previously: "; - message += genName; - message += - "\nEither remove the CMakeCache.txt file or choose a different" - " binary directory."; - cmSystemTools::Error(message.c_str()); - return -2; - } - } - if(!mf.GetDefinition("CMAKE_GENERATOR")) - { - mf.AddCacheDefinition("CMAKE_GENERATOR", - gen->GetName(), - "Name of generator.", - cmCacheManager::INTERNAL); - } - - - // setup CMAKE_ROOT and CMAKE_COMMAND - if(!this->AddCMakePaths(args)) - { - return -3; - } - - // reset any system configuration information - cmMakefileGenerator::ClearEnabledLanguages(); - - std::string lf = mf.GetStartDirectory(); - lf += "/CMakeLists.txt"; - if(!mf.ReadListFile(lf.c_str())) - { - this->Usage(args[0].c_str()); - return -1; - } - // if buildMakefiles, then call GenerateMakefile - if(buildMakefiles) - { - mf.GenerateMakefile(); - } - else // do not build, but let the commands finalize - { - std::vector makefiles; - mf.FindSubDirectoryCMakeListsFiles(makefiles); - for(std::vector::iterator i = makefiles.begin(); - i != makefiles.end(); ++i) - { - cmMakefile* mf = *i; - mf->FinalPass(); - delete mf; - } - mf.FinalPass(); - } - - - // Before saving the cache - // if the project did not define one of the entries below, add them now - // so users can edit the values in the cache: - // LIBRARY_OUTPUT_PATH - // EXECUTABLE_OUTPUT_PATH - if(!this->m_CacheManager.GetCacheValue("LIBRARY_OUTPUT_PATH")) - { - this->m_CacheManager.AddCacheEntry("LIBRARY_OUTPUT_PATH", "", - "Single output directory for building all libraries.", - cmCacheManager::PATH); - } - if(!this->m_CacheManager.GetCacheValue("EXECUTABLE_OUTPUT_PATH")) - { - this->m_CacheManager.AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "", - "Single output directory for building all executables.", - cmCacheManager::PATH); - } - - this->m_CacheManager.SaveCache(&mf); - - if(m_Verbose) - { - this->m_CacheManager.PrintCache(std::cout); - } - - if(cmSystemTools::GetErrorOccuredFlag()) - { - return -1; - } - return 0; -} - - void CMakeCommandUsage(const char* program) { cmStringStream errorStream; @@ -678,39 +523,291 @@ int cmake::CMakeCommand(std::vector& args) void cmake::GetRegisteredGenerators(std::vector& names) { - for(std::map::iterator i - = this->m_RegisteredGenerators.begin(); - i != this->m_RegisteredGenerators.end(); ++i) - { - names.push_back(i->first); - } +#if defined(_WIN32) && !defined(__CYGWIN__) + names.push_back(cmGlobalVisualStudio6Generator::GetActualName()); + names.push_back(cmGlobalVisualStudio7Generator::GetActualName()); + names.push_back(cmGlobalBorlandMakefileGenerator::GetActualName()); + names.push_back(cmGlobalNMakeMakefileGenerator::GetActualName()); +#else + names.push_back(cmGlobalUnixMakefileGenerator::GetActualName()); +#endif } - -void cmake::RegisterGenerator(cmMakefileGenerator* mg) +cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name) { - std::map::iterator i = - this->m_RegisteredGenerators.find(mg->GetName()); - // delete re-registered objects - if(i != this->m_RegisteredGenerators.end()) + cmGlobalGenerator *ret = 0; +#if defined(_WIN32) && !defined(__CYGWIN__) + if (!strcmp(name,cmGlobalNMakeMakefileGenerator::GetActualName())) { - delete i->second; + ret = new cmGlobalNMakeMakefileGenerator; + ret->SetCMakeInstance(this); } - this->m_RegisteredGenerators[mg->GetName()] = mg; + if (!strcmp(name,cmGlobalVisualStudio6Generator::GetActualName())) + { + ret = new cmGlobalVisualStudio6Generator; + ret->SetCMakeInstance(this); + } + if (!strcmp(name,cmGlobalVisualStudio7Generator::GetActualName())) + { + ret = new cmGlobalVisualStudio7Generator; + ret->SetCMakeInstance(this); + } + if (!strcmp(name,cmGlobalBorlandMakefileGenerator::GetActualName())) + { + ret = new cmGlobalBorlandMakefileGenerator; + ret->SetCMakeInstance(this); + } +#else + if (!strcmp(name,cmGlobalUnixMakefileGenerator::GetActualName())) + { + ret = new cmGlobalUnixMakefileGenerator; + ret->SetCMakeInstance(this); + } +#endif + return ret; } -cmMakefileGenerator* cmake::CreateGenerator(const char* name) +void cmake::SetHomeDirectory(const char* dir) { - std::map::iterator i; - for(i = this->m_RegisteredGenerators.begin(); - i != this->m_RegisteredGenerators.end(); ++i) + m_cmHomeDirectory = dir; + cmSystemTools::ConvertToUnixSlashes(m_cmHomeDirectory); +} + +void cmake::SetHomeOutputDirectory(const char* lib) +{ + m_HomeOutputDirectory = lib; + cmSystemTools::ConvertToUnixSlashes(m_HomeOutputDirectory); +} + +void cmake::SetGlobalGenerator(cmGlobalGenerator *gg) +{ + // delete the old generator + if (m_GlobalGenerator) { - cmMakefileGenerator* gen = i->second; - if(strcmp(name, gen->GetName()) == 0) + delete m_GlobalGenerator; + } + // set the new + m_GlobalGenerator = gg; + // set the cmake instance just to be sure + gg->SetCMakeInstance(this); +} + +int cmake::Configure(const char *arg0, const std::vector* args) +{ + // Read in the cache + m_CacheManager->LoadCache(this->GetHomeOutputDirectory()); + if(m_CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY")) + { + std::string cacheStart = + m_CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY"); + cacheStart += "/CMakeLists.txt"; + std::string currentStart = this->GetHomeDirectory(); + currentStart += "/CMakeLists.txt"; + if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str())) { - return gen->CreateObject(); + std::string message = "Error: source : "; + message += currentStart; + message += "\nDoes not match source used to generate cache: "; + message += cacheStart; + message += "\nRe-run cmake with a different source directory."; + cmSystemTools::Error(message.c_str()); + return -2; } } + else + { + m_CacheManager->AddCacheEntry("CMAKE_HOME_DIRECTORY", + this->GetHomeDirectory(), + "Start directory with the top level CMakeLists.txt file for this project", + cmCacheManager::INTERNAL); + } + + // extract command line arguments that might add cache entries + if (args) + { + this->SetCacheArgs(*args); + } + + // setup CMAKE_ROOT and CMAKE_COMMAND + if(!this->AddCMakePaths(arg0)) + { + return -3; + } + + // no generator specified on the command line + if(!m_GlobalGenerator) + { + const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR"); + if(genName) + { + m_GlobalGenerator = this->CreateGlobalGenerator(genName); + } + else + { +#if defined(__BORLANDC__) + this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator); +#elif defined(_WIN32) && !defined(__CYGWIN__) + this->SetGlobalGenerator(new cmGlobalVisualStudio6Generator); +#else + this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator); +#endif + } + if(!m_GlobalGenerator) + { + cmSystemTools::Error("Could not create generator"); + return -1; + } + } + + const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR"); + if(genName) + { + if(strcmp(m_GlobalGenerator->GetName(), genName) != 0) + { + std::string message = "Error: generator : "; + message += m_GlobalGenerator->GetName(); + message += "\nDoes not match the generator used previously: "; + message += genName; + message += + "\nEither remove the CMakeCache.txt file or choose a different" + " binary directory."; + cmSystemTools::Error(message.c_str()); + return -2; + } + } + if(!m_CacheManager->GetCacheValue("CMAKE_GENERATOR")) + { + m_CacheManager->AddCacheEntry("CMAKE_GENERATOR", m_GlobalGenerator->GetName(), + "Name of generator.", + cmCacheManager::INTERNAL); + } + + // reset any system configuration information + m_GlobalGenerator->ClearEnabledLanguages(); + + // actually do the configure + m_GlobalGenerator->Configure(); + + // Before saving the cache + // if the project did not define one of the entries below, add them now + // so users can edit the values in the cache: + // LIBRARY_OUTPUT_PATH + // EXECUTABLE_OUTPUT_PATH + if(!m_CacheManager->GetCacheValue("LIBRARY_OUTPUT_PATH")) + { + m_CacheManager->AddCacheEntry("LIBRARY_OUTPUT_PATH", "", + "Single output directory for building all libraries.", + cmCacheManager::PATH); + } + if(!m_CacheManager->GetCacheValue("EXECUTABLE_OUTPUT_PATH")) + { + m_CacheManager->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "", + "Single output directory for building all executables.", + cmCacheManager::PATH); + } + + this->m_CacheManager->SaveCache(this->GetHomeOutputDirectory()); + if(cmSystemTools::GetErrorOccuredFlag()) + { + return -1; + } return 0; } +// handle a command line invocation +int cmake::Run(const std::vector& args) +{ + // a quick check for args + if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt")) + { + this->Usage(args[0].c_str()); + return -1; + } + + // look for obvious request for help + for(unsigned int i=1; i < args.size(); ++i) + { + std::string arg = args[i]; + if(arg.find("-help",0) != std::string::npos || + arg.find("--help",0) != std::string::npos || + arg.find("/?",0) != std::string::npos || + arg.find("-usage",0) != std::string::npos) + { + this->Usage(args[0].c_str()); + return -1; + } + } + + // Process the arguments + this->SetArgs(args); + + // if we are local do the local thing, otherwise do global + if (m_Local) + { + return this->LocalGenerate(); + } + + // otherwise global + int ret = this->Configure(args[0].c_str(),&args); + if (ret) + { + return ret; + } + return this->Generate(); +} + +int cmake::Generate() +{ + m_GlobalGenerator->Generate(); + if(cmSystemTools::GetErrorOccuredFlag()) + { + return -1; + } + return 0; +} + +int cmake::LocalGenerate() +{ + // Read in the cache + m_CacheManager->LoadCache(this->GetHomeOutputDirectory()); + + // create the generator based on the cache if it isn't already there + const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR"); + if(genName) + { + m_GlobalGenerator = this->CreateGlobalGenerator(genName); + } + else + { + cmSystemTools::Error("Could local Generate called without the GENERATOR being specified in the CMakeCache"); + return -1; + } + + // do the local generate + m_GlobalGenerator->LocalGenerate(); + if(cmSystemTools::GetErrorOccuredFlag()) + { + return -1; + } + return 0; +} + +unsigned int cmake::GetMajorVersion() +{ + return cmMakefile::GetMajorVersion(); +} + +unsigned int cmake::GetMinorVersion() +{ + return cmMakefile::GetMinorVersion(); +} + +const char *cmake::GetReleaseVersion() +{ + return cmMakefile::GetReleaseVersion(); +} + +const char* cmake::GetCacheDefinition(const char* name) const +{ + return m_CacheManager->GetCacheValue(name); +} diff --git a/Source/cmake.h b/Source/cmake.h index 906379485..709778f0e 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -18,18 +18,81 @@ // running cmake. Most cmake based GUIS should primarily create an instance // of this class and communicate with it. -#include "cmMakefile.h" #include "cmStandardIncludes.h" +#include "cmSystemTools.h" + +class cmGlobalGenerator; +class cmLocalGenerator; +class cmCacheManager; +class cmMakefile; class cmake { public: + ///! construct an instance of cmake + cmake(); + ///! destruct an instance of cmake + ~cmake(); /** - * Generate the SourceFilesList from the SourceLists. This should only be - * done once to be safe. + * Return major and minor version numbers for cmake. */ - void Usage(const char *program); + static unsigned int GetMajorVersion(); + static unsigned int GetMinorVersion(); + static const char *GetReleaseVersion(); + + //@{ + /** + * Set/Get the home directory (or output directory) in the project. The + * home directory is the top directory of the project. It is where + * cmake was run. Remember that CMake processes + * CMakeLists files by recursing up the tree starting at the StartDirectory + * and going up until it reaches the HomeDirectory. + */ + void SetHomeDirectory(const char* dir); + const char* GetHomeDirectory() const + { + return m_cmHomeDirectory.c_str(); + } + void SetHomeOutputDirectory(const char* lib); + const char* GetHomeOutputDirectory() const + { + return m_HomeOutputDirectory.c_str(); + } + //@} + + //@{ + /** + * Set/Get the start directory (or output directory). The start directory + * is the directory of the CMakeLists.txt file that started the current + * round of processing. Remember that CMake processes CMakeLists files by + * recursing up the tree starting at the StartDirectory and going up until + * it reaches the HomeDirectory. + */ + void SetStartDirectory(const char* dir) + { + m_cmStartDirectory = dir; + cmSystemTools::ConvertToUnixSlashes(m_cmStartDirectory); + } + const char* GetStartDirectory() const + { + return m_cmStartDirectory.c_str(); + } + void SetStartOutputDirectory(const char* lib) + { + m_StartOutputDirectory = lib; + cmSystemTools::ConvertToUnixSlashes(m_StartOutputDirectory); + } + const char* GetStartOutputDirectory() const + { + return m_StartOutputDirectory.c_str(); + } + //@} + + /** + * Handle a command line invocation of cmake. + */ + int Run(const std::vector&args); /** * Generate the SourceFilesList from the SourceLists. This should only be @@ -41,7 +104,35 @@ class cmake * If you only want to parse the CMakeLists.txt files, * but not actually generate the makefiles, use buildMakefiles = false. */ - int Generate(const std::vector&, bool buildMakefiles = true); + int Generate(); + + /** + * Configure the cmMakefiles. This routine will create a GlobalGenerator if + * one has not already been set. It will then Call Configure on the + * GlobalGenerator. This in turn will read in an process all the CMakeList + * files for the tree. It will not produce any actual Makefiles, or + * workspaces. Generate does that. */ + int Configure(const char *cmakeexec, const std::vector *args = 0); + + ///! Create a GlobalGenerator + cmGlobalGenerator* CreateGlobalGenerator(const char* name); + + ///! Return the global generator assigned to this instance of cmake + cmGlobalGenerator* GetGlobalGenerator() { return m_GlobalGenerator; }; + + ///! Return the global generator assigned to this instance of cmake + void SetGlobalGenerator(cmGlobalGenerator *); + + ///! Get the names of the current registered generators + void GetRegisteredGenerators(std::vector& names); + + ///! get the cmCachemManager used by this invocation of cmake + cmCacheManager *GetCacheManager() { return m_CacheManager; } + + /** + * Given a variable name, return its value (as a string). + */ + const char* GetCacheDefinition(const char*) const; /** * Execute commands during the build process. Supports options such @@ -49,36 +140,43 @@ class cmake */ static int CMakeCommand(std::vector&); - ///! Parse command line arguments - void SetArgs(cmMakefile& builder, const std::vector&); - ///! Parse command line arguments that might set cache values - void SetCacheArgs(cmMakefile& builder, const std::vector&); + /** + * Is cmake in the process of a local cmake invocation. If so, we know the + * cache is already configured and ready to go. + */ + bool GetLocal() + { + return m_Local; + } + + ///! Display command line useage + void Usage(const char *program); + ///! Parse command line arguments + void SetArgs(const std::vector&); + +protected: + cmGlobalGenerator *m_GlobalGenerator; + cmCacheManager *m_CacheManager; + std::string m_cmHomeDirectory; + std::string m_HomeOutputDirectory; + std::string m_cmStartDirectory; + std::string m_StartOutputDirectory; + + ///! Parse command line arguments that might set cache values + void SetCacheArgs(const std::vector&); + + ///! read in a cmake list file to initialize the cache + void ReadListFile(const char *path); + /** * Generate CMAKE_ROOT and CMAKE_COMMAND cache entries */ - int AddCMakePaths(const std::vector&); + int AddCMakePaths(const char *arg0); - /** - * constructor - */ - cmake(); - ~cmake(); + ///! used by Run + int LocalGenerate(); - ///! Create a named generator - cmMakefileGenerator* CreateGenerator(const char* name); - ///! Register a generator - void RegisterGenerator(cmMakefileGenerator*); - ///! Get the names of the current registered generators - void GetRegisteredGenerators(std::vector& names); - - ///! get the cmCachemManager used by this invocation of cmake - cmCacheManager *GetCacheManager() { - return &m_CacheManager; } - -protected: - std::map m_RegisteredGenerators; - cmCacheManager m_CacheManager; private: bool m_Verbose; bool m_Local; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index e5ad54bd8..b8214abcb 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -55,6 +55,6 @@ int main(int ac, char** av) return 0; } cmake cm; - int ret = cm.Generate(args); + int ret = cm.Run(args); return ret; } diff --git a/Source/cmaketest.cxx b/Source/cmaketest.cxx index 4228053e5..2acdc98a8 100644 --- a/Source/cmaketest.cxx +++ b/Source/cmaketest.cxx @@ -115,7 +115,7 @@ int main (int argc, char **argv) std::cout << "Generating build files...\n"; cmake cm; - if (cm.Generate(args) != 0) + if (cm.Run(args) != 0) { std::cerr << "Error: cmake execution failed\n"; // return to the original directory @@ -126,7 +126,7 @@ int main (int argc, char **argv) cmake cm2; std::cout << "Generating build files (again)...\n"; - if (cm2.Generate(args) != 0) + if (cm2.Run(args) != 0) { std::cerr << "Error: cmake execution failed\n"; // return to the original directory diff --git a/Source/cmakewizard.cxx b/Source/cmakewizard.cxx index 2880a85b1..466920657 100644 --- a/Source/cmakewizard.cxx +++ b/Source/cmakewizard.cxx @@ -98,7 +98,7 @@ void cmakewizard::RunWizard(std::vector const& args) asked = false; // run cmake this->ShowMessage("Please wait while cmake processes CMakeLists.txt files....\n"); - make.Generate(args); + make.Configure(args[0].c_str(),&args); this->ShowMessage("\n"); // load the cache from disk cmCacheManager *cachem = make.GetCacheManager(); @@ -140,5 +140,6 @@ void cmakewizard::RunWizard(std::vector const& args) cachem->SaveCache(cmSystemTools::GetCurrentWorkingDirectory().c_str()); } while(asked); + make.Generate(); this->ShowMessage("CMake complete, run make to build project.\n"); }