diff options
Diffstat (limited to 'Source')
281 files changed, 15557 insertions, 11504 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a7adb51..16b9ea1 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -88,7 +88,7 @@ option(CMAKE_REGENERATE_YACCLEX "Regenerate YACC and LEXX files" OFF) mark_as_advanced(CMAKE_REGENERATE_YACCLEX) if(CMAKE_REGENERATE_YACCLEX) - set(parsersLexers cmDependsFortran cmCommandArgument cmExpr) + set(parsersLexers cmFortran cmCommandArgument cmExpr) find_program(YACC_EXECUTABLE NAMES yacc bison PATHS /usr/bin @@ -165,6 +165,8 @@ set(SRCS cmCommandArgumentLexer.cxx cmCommandArgumentParser.cxx cmCommandArgumentParserHelper.cxx + cmCommonTargetGenerator.cxx + cmCommonTargetGenerator.h cmComputeComponentGraph.cxx cmComputeComponentGraph.h cmComputeLinkDepends.cxx @@ -191,9 +193,6 @@ set(SRCS cmDependsC.h cmDependsFortran.cxx cmDependsFortran.h - cmDependsFortranLexer.cxx - cmDependsFortranParser.cxx - cmDependsFortranParser.h cmDependsJava.cxx cmDependsJava.h cmDependsJavaLexer.cxx @@ -241,6 +240,11 @@ set(SRCS cmFileLockResult.h cmFileTimeComparison.cxx cmFileTimeComparison.h + cmFortranLexer.cxx + cmFortranLexer.h + cmFortranParser.cxx + cmFortranParser.h + cmFortranParserImpl.cxx cmGeneratedFileStream.cxx cmGeneratorExpressionContext.cxx cmGeneratorExpressionContext.h @@ -260,6 +264,8 @@ set(SRCS cmGeneratorExpression.h cmGeneratorTarget.cxx cmGeneratorTarget.h + cmGlobalCommonGenerator.cxx + cmGlobalCommonGenerator.h cmGlobalGenerator.cxx cmGlobalGenerator.h cmGlobalGeneratorFactory.h @@ -281,9 +287,13 @@ set(SRCS cmInstallTargetGenerator.cxx cmInstallDirectoryGenerator.h cmInstallDirectoryGenerator.cxx + cmLinkedTree.h + cmLinkItem.h cmListFileCache.cxx cmListFileCache.h cmListFileLexer.c + cmLocalCommonGenerator.cxx + cmLocalCommonGenerator.h cmLocalGenerator.cxx cmLocalGenerator.h cmLocalUnixMakefileGenerator3.cxx @@ -299,6 +309,8 @@ set(SRCS cmMakefileUtilityTargetGenerator.cxx cmOSXBundleGenerator.cxx cmOSXBundleGenerator.h + cmOutputConverter.cxx + cmOutputConverter.h cmNewLineStyle.h cmNewLineStyle.cxx cmOrderDirectories.cxx @@ -427,6 +439,7 @@ if (WIN32) set(SRCS ${SRCS} cmCallVisualStudioMacro.cxx cmCallVisualStudioMacro.h + bindexplib.cxx ) if(NOT UNIX) @@ -543,9 +556,10 @@ if(APPLE) target_link_libraries(CMakeLib "-framework CoreFoundation") endif() -if(CMAKE_BUILD_ON_VISUAL_STUDIO OR MINGW) - # We need the rpcrt4 library for at least the VS7-VC10 generators. - target_link_libraries(CMakeLib rpcrt4) +if(WIN32 AND NOT UNIX) + # We need the rpcrt4 library on Windows. + # We need the crypt32 library on Windows for crypto/cert APIs. + target_link_libraries(CMakeLib rpcrt4 crypt32) endif() # @@ -731,9 +745,17 @@ endif() include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL) include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL) -install(TARGETS cmake ctest cpack DESTINATION bin) +# Install tools + +set(_tools cmake ctest cpack) + if(APPLE) - install(TARGETS cmakexbuild DESTINATION bin) + list(APPEND _tools cmakexbuild) endif() +foreach(_tool ${_tools}) + CMake_OPTIONAL_COMPONENT(${_tool}) + install(TARGETS ${_tool} DESTINATION bin ${COMPONENT}) +endforeach() + install(FILES cmCPluginAPI.h DESTINATION ${CMAKE_DATA_DIR}/include) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e1bffac..33ad704 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 3) -set(CMake_VERSION_PATCH 1) -#set(CMake_VERSION_RC 0) +set(CMake_VERSION_PATCH 20150831) +#set(CMake_VERSION_RC 1) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 09e123c..43d34ee 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -191,7 +191,7 @@ int cmCPackIFWGenerator::PackageFiles() } } // TODO: set correct name for multipackages - if (this->packageFileNames.size() > 0) + if (!this->packageFileNames.empty()) { ifwCmd += " " + packageFileNames[0]; } diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index 1d7afbd..c271517 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -11,17 +11,18 @@ ============================================================================*/ #include <cmsys/SystemTools.hxx> #include <cmsys/Process.h> -#include <cmsys/ios/iostream> #include <cmsys/FStream.hxx> +#include <iostream> + #include <CoreFoundation/CoreFoundation.h> // For the PATH_MAX constant #include <sys/syslimits.h> #define DebugError(x) \ - ofs << x << cmsys_ios::endl; \ - cmsys_ios::cout << x << cmsys_ios::endl + ofs << x << std::endl; \ + std::cout << x << std::endl int main(int argc, char* argv[]) { @@ -77,7 +78,7 @@ int main(int argc, char* argv[]) std::string scriptDirectory = cmsys::SystemTools::GetFilenamePath( fullScriptPath); - ofs << fullScriptPath.c_str() << cmsys_ios::endl; + ofs << fullScriptPath.c_str() << std::endl; std::vector<const char*> args; args.push_back(fullScriptPath.c_str()); int cc; @@ -109,7 +110,7 @@ int main(int argc, char* argv[]) data[i] = ' '; } } - cmsys_ios::cout.write(data, length); + std::cout.write(data, length); } cmsysProcess_WaitForExit(cp, 0); diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index b3eb7b2..6f25e50 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -217,7 +217,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() { std::string defaultRef = "WixUI_InstallDir"; - if(this->Components.size()) + if(!this->Components.empty()) { defaultRef = "WixUI_FeatureTree"; } @@ -1005,7 +1005,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( shortcut.workingDirectoryId = directoryId; shortcuts.insert(cmWIXShortcuts::START_MENU, id, shortcut); - if(desktopExecutables.size() && + if(!desktopExecutables.empty() && std::find(desktopExecutables.begin(), desktopExecutables.end(), executableName) diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx index aeec968..fc0d3d3 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.cxx +++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx @@ -71,7 +71,7 @@ void cmWIXAccessControlList::CreatePermissionElement( this->SourceWriter.BeginElement("Permission"); this->SourceWriter.AddAttribute("User", user); - if(domain.size()) + if(!domain.empty()) { this->SourceWriter.AddAttribute("Domain", domain); } diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx index b5202e0..5a8dc63 100644 --- a/Source/CPack/WiX/cmWIXPatch.cxx +++ b/Source/CPack/WiX/cmWIXPatch.cxx @@ -79,7 +79,7 @@ bool cmWIXPatch::CheckForUnappliedFragments() fragmentList += "'"; } - if(fragmentList.size()) + if(!fragmentList.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Some XML patch fragments did not have matching IDs: " << diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index 219fca8..8d38e9b 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -128,7 +128,7 @@ void cmWIXSourceWriter::AddAttribute( void cmWIXSourceWriter::AddAttributeUnlessEmpty( std::string const& key, std::string const& value) { - if(value.size()) + if(!value.empty()) { AddAttribute(key, value); } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index bf4df60..92a4b2b 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -716,8 +716,10 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cm.AddCMakePaths(); cm.SetProgressCallback(cmCPackGeneratorProgress, this); cmGlobalGenerator gg(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); - cmMakefile *mf = lg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> mf( + new cmMakefile(&gg, cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lg( + gg.CreateLocalGenerator(mf.get())); std::string realInstallDirectory = tempInstallDirectory; if ( !installSubDirectory.empty() && installSubDirectory != "/" ) { diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 2de2bc4..6cdda28 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -49,7 +49,7 @@ int cmCPackNSISGenerator::PackageFiles() // TODO: Fix nsis to force out file name std::string nsisInFileName = this->FindTemplate("NSIS.template.in"); - if ( nsisInFileName.size() == 0 ) + if (nsisInFileName.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack error: Could not find NSIS installer template file." @@ -58,7 +58,7 @@ int cmCPackNSISGenerator::PackageFiles() } std::string nsisInInstallOptions = this->FindTemplate("NSIS.InstallOptions.ini.in"); - if ( nsisInInstallOptions.size() == 0 ) + if (nsisInInstallOptions.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack error: Could not find NSIS installer options file." @@ -536,7 +536,7 @@ int cmCPackNSISGenerator::InitializeInternal() << ".lnk\"" << std::endl; // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on // if so add a desktop link - if(cpackPackageDesktopLinksVector.size() && + if(!cpackPackageDesktopLinksVector.empty() && std::find(cpackPackageDesktopLinksVector.begin(), cpackPackageDesktopLinksVector.end(), execName) diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index e5da5cf..109dcb7 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -19,7 +19,6 @@ #include "cmMakefile.h" #include "cmCPackLog.h" -#include <cmsys/ios/sstream> #include <cmsys/FStream.hxx> #include <sys/types.h> #include <sys/stat.h> @@ -85,7 +84,7 @@ int cmCPackSTGZGenerator::PackageFiles() int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Writing header" << std::endl); - cmsys_ios::ostringstream str; + std::ostringstream str; int counter = 0; std::string inLicFile = this->GetOption("CPACK_RESOURCE_FILE_LICENSE"); diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index c2fe763..cb9cbc4 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -202,8 +202,10 @@ int main (int argc, char const* const* argv) cminst.SetHomeOutputDirectory(""); cminst.GetState()->RemoveUnscriptableCommands(); cmGlobalGenerator cmgg(&cminst); - cmsys::auto_ptr<cmLocalGenerator> cmlg(cmgg.MakeLocalGenerator()); - cmMakefile* globalMF = cmlg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> globalMF( + new cmMakefile(&cmgg, cminst.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> cmlg( + cmgg.CreateLocalGenerator(globalMF.get())); #if defined(__CYGWIN__) globalMF->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0"); #endif @@ -357,8 +359,8 @@ int main (int argc, char const* const* argv) ++it ) { const char* gen = it->c_str(); - cmMakefile::ScopePushPop raii(globalMF); - cmMakefile* mf = globalMF; + cmMakefile::ScopePushPop raii(globalMF.get()); + cmMakefile* mf = globalMF.get(); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Specified generator: " << gen << std::endl); if ( parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME") ) diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 3014a93..587b583 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -14,7 +14,6 @@ #include "cmCTest.h" #include "cmSystemTools.h" #include "cmXMLParser.h" -#include "cmXMLSafe.h" #include <cmsys/RegularExpression.hxx> diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index e141b60..6dbb245 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -920,7 +920,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, char* data; int length; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents " << tick_len << " bytes of output." << std::endl << (this->UseCTestLaunch? "" : @@ -968,7 +968,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, this->ProcessBuffer(0, 0, tick, tick_len, ofs, &this->BuildProcessingQueue); this->ProcessBuffer(0, 0, tick, tick_len, ofs, &this->BuildProcessingErrorQueue); - cmCTestOptionalLog(this->CTest, OUTPUT, " Size of output: " + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size of output: " << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl, this->Quiet); @@ -1175,12 +1175,12 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, int length, while ( this->BuildOutputLogSize > (tick * tick_len) ) { tick ++; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, this->LastTickChar, - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, + this->LastTickChar, this->Quiet); tickDisplayed = true; if ( tick % tick_line_len == 0 && tick > 0 ) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Size: " + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size: " << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl << " ", this->Quiet); } diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index f92f19a..20807c8 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -27,8 +27,6 @@ #include <cmsys/Process.h> #include <cmsys/RegularExpression.hxx> #include <cmsys/Glob.hxx> -#include <cmsys/stl/iterator> -#include <cmsys/stl/algorithm> #include <cmsys/FStream.hxx> #include <stdlib.h> @@ -446,7 +444,7 @@ int cmCTestCoverageHandler::ProcessHandler() } std::set<std::string> uncovered = this->FindUncoveredFiles(&cont); - if ( file_count == 0 ) + if (file_count == 0 && this->ExtraCoverageGlobs.empty()) { cmCTestOptionalLog(this->CTest, WARNING, " Cannot find any coverage files. Ignoring Coverage request." @@ -1474,7 +1472,12 @@ int cmCTestCoverageHandler::HandleLCovCoverage( << std::endl, this->Quiet); std::vector<std::string> files; - this->FindLCovFiles(files); + if (!this->FindLCovFiles(files)) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error while finding LCov files.\n"); + return 0; + } std::vector<std::string>::iterator it; if (files.empty()) @@ -1745,18 +1748,28 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files) } //---------------------------------------------------------------------------- -void cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) +bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) { cmsys::Glob gl; gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is // used while compiling. gl.RecurseThroughSymlinksOff(); std::string prevBinaryDir; - cmSystemTools::ChangeDirectory( - this->CTest->GetCTestConfiguration("BuildDirectory")); + std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory"); + if (cmSystemTools::ChangeDirectory(buildDir)) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error changing directory to " << buildDir << std::endl); + return false; + } // Run profmerge to merge all *.dyn files into dpi files - cmSystemTools::RunSingleCommand("profmerge"); + if (!cmSystemTools::RunSingleCommand("profmerge")) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error while running profmerge.\n"); + return false; + } prevBinaryDir = cmSystemTools::GetCurrentWorkingDirectory().c_str(); @@ -1766,10 +1779,16 @@ void cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) daGlob += "/*.dpi"; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " looking for dpi files in: " << daGlob << std::endl, this->Quiet); - gl.FindFiles(daGlob); + if (!gl.FindFiles(daGlob)) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error while finding files matching " << daGlob << std::endl); + return false; + } files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Now searching in: " << daGlob << std::endl, this->Quiet); + return true; } //---------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 2ca123a..7102d1e 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -75,7 +75,7 @@ private: //! Handle coverage using Intel's LCov int HandleLCovCoverage(cmCTestCoverageHandlerContainer* cont); - void FindLCovFiles(std::vector<std::string>& files); + bool FindLCovFiles(std::vector<std::string>& files); //! Handle coverage using xdebug php coverage int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont); diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 6b84bab..bbb3b9d 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -14,10 +14,8 @@ #include "cmCTest.h" #include "cmSystemTools.h" #include "cmAlgorithms.h" -#include "cmXMLSafe.h" #include <cmsys/RegularExpression.hxx> -#include <cmsys/ios/sstream> #include <cmsys/Process.h> #include <cmsys/FStream.hxx> diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 81eb0a8..ad79ba2 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -23,6 +23,7 @@ cmCTestGenericHandler::cmCTestGenericHandler() this->SubmitIndex = 0; this->AppendXML = false; this->Quiet = false; + this->TestLoad = 0; } //---------------------------------------------------------------------- @@ -70,6 +71,7 @@ void cmCTestGenericHandler::SetPersistentOption(const std::string& op, void cmCTestGenericHandler::Initialize() { this->AppendXML = false; + this->TestLoad = 0; this->Options.clear(); t_StringToString::iterator it; for ( it = this->PersistentOptions.begin(); diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 8567dd7..4b7ae79 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -89,6 +89,8 @@ public: void SetAppendXML(bool b) { this->AppendXML = b; } void SetQuiet(bool b) { this->Quiet = b; } bool GetQuiet() { return this->Quiet; } + void SetTestLoad(unsigned long load) { this->TestLoad = load; } + unsigned long GetTestLoad() const { return this->TestLoad; } protected: bool StartResultingXML(cmCTest::Part part, @@ -97,6 +99,7 @@ protected: bool AppendXML; bool Quiet; + unsigned long TestLoad; cmSystemTools::OutputOption HandlerVerbose; cmCTest *CTest; t_StringToString Options; diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 3003e8a..3579aee 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -109,6 +109,12 @@ bool cmCTestHandlerCommand this->Quiet); } + if(const char* changeId = + this->Makefile->GetDefinition("CTEST_CHANGE_ID")) + { + this->CTest->SetCTestConfiguration("ChangeId", changeId, this->Quiet); + } + cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;); cmCTestGenericHandler* handler = this->InitializeHandler(); if ( !handler ) diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 0f588c5..fb0cce6 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -738,8 +738,9 @@ void cmCTestLaunch::LoadConfig() cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmGlobalGenerator gg(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); - cmMakefile* mf = lg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lg( + gg.CreateLocalGenerator(mf.get())); std::string fname = this->LogDir; fname += "CTestLaunchConfig.cmake"; if(cmSystemTools::FileExists(fname.c_str()) && diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 8f26716..acf527a 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -80,8 +80,8 @@ public: int i = 0; for(; atts[i] != 0; i+=2) { - ostr << " " << cmXMLSafe(atts[i]) - << " - " << cmXMLSafe(atts[i+1]) << "\n"; + ostr << " " << atts[i] + << " - " << atts[i+1] << "\n"; } ostr << "\n"; this->Log += ostr.str(); @@ -856,7 +856,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput( defects++; ostr << "<b>" << this->ResultStrings[idx] << "</b> "; } - ostr << cmXMLSafe(*i) << std::endl; + ostr << *i << std::endl; } log = ostr.str(); if(defects) @@ -908,7 +908,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( results[failure] ++; defects ++; } - ostr << cmXMLSafe(*i) << std::endl; + ostr << *i << std::endl; } log = ostr.str(); @@ -1056,7 +1056,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( defects ++; } totalOutputSize += lines[cc].size(); - ostr << cmXMLSafe(lines[cc]) << std::endl; + ostr << lines[cc] << std::endl; } else { @@ -1070,11 +1070,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i) { totalOutputSize += lines[*i].size(); - cmCTestOptionalLog(this->CTest, DEBUG, "before xml safe " - << lines[*i] << std::endl, this->Quiet); - cmCTestOptionalLog(this->CTest, DEBUG, "after xml safe " - << cmXMLSafe(lines[*i]) << std::endl, this->Quiet); - ostr << cmXMLSafe(lines[*i]) << std::endl; + ostr << lines[*i] << std::endl; if(!unlimitedOutput && totalOutputSize > static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) { diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index bd090db..4832186 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -13,12 +13,15 @@ #include "cmProcess.h" #include "cmStandardIncludes.h" #include "cmCTest.h" +#include "cmCTestScriptHandler.h" #include "cmSystemTools.h" #include <stdlib.h> #include <stack> #include <list> #include <float.h> +#include <math.h> #include <cmsys/FStream.hxx> +#include <cmsys/SystemInformation.hxx> class TestComparator { @@ -40,10 +43,12 @@ private: cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() { this->ParallelLevel = 1; + this->TestLoad = 0; this->Completed = 0; this->RunningCount = 0; this->StopTimePassed = false; this->HasCycles = false; + this->SerialTestRunning = false; } cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler() @@ -83,6 +88,11 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level) this->ParallelLevel = level < 1 ? 1 : level; } +void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load) +{ + this->TestLoad = load; +} + //--------------------------------------------------------- void cmCTestMultiProcessHandler::RunTests() { @@ -172,6 +182,11 @@ void cmCTestMultiProcessHandler::LockResources(int index) this->LockedResources.insert( this->Properties[index]->LockedResources.begin(), this->Properties[index]->LockedResources.end()); + + if (this->Properties[index]->RunSerial) + { + this->SerialTestRunning = true; + } } //--------------------------------------------------------- @@ -198,17 +213,20 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test) { size_t processors = static_cast<int>(this->Properties[test]->Processors); - //If this is set to run serially, it must run alone. - //Also, if processors setting is set higher than the -j + //If processors setting is set higher than the -j //setting, we default to using all of the process slots. - if(this->Properties[test]->RunSerial - || processors > this->ParallelLevel) + if (processors > this->ParallelLevel) { processors = this->ParallelLevel; } return processors; } +std::string cmCTestMultiProcessHandler::GetName(int test) +{ + return this->Properties[test]->Name; +} + //--------------------------------------------------------- bool cmCTestMultiProcessHandler::StartTest(int test) { @@ -248,22 +266,136 @@ void cmCTestMultiProcessHandler::StartNextTests() return; } + // Don't start any new tests if one with the RUN_SERIAL property + // is already running. + if (this->SerialTestRunning) + { + return; + } + + bool allTestsFailedTestLoadCheck = false; + bool usedFakeLoadForTesting = false; + size_t minProcessorsRequired = this->ParallelLevel; + std::string testWithMinProcessors = ""; + + cmsys::SystemInformation info; + + unsigned long systemLoad = 0; + size_t spareLoad = 0; + if (this->TestLoad > 0) + { + // Activate possible wait. + allTestsFailedTestLoadCheck = true; + + // Check for a fake load average value used in testing. + if (const char* fake_load_value = + cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING")) + { + usedFakeLoadForTesting = true; + if (!cmSystemTools::StringToULong(fake_load_value, &systemLoad)) + { + cmSystemTools::Error("Failed to parse fake load value: ", + fake_load_value); + } + } + // If it's not set, look up the true load average. + else + { + systemLoad = static_cast<unsigned long>(ceil(info.GetLoadAverage())); + } + spareLoad = (this->TestLoad > systemLoad ? + this->TestLoad - systemLoad : 0); + + // Don't start more tests than the spare load can support. + if (numToStart > spareLoad) + { + numToStart = spareLoad; + } + } + TestList copy = this->SortedTests; for(TestList::iterator test = copy.begin(); test != copy.end(); ++test) { + // Take a nap if we're currently performing a RUN_SERIAL test. + if (this->SerialTestRunning) + { + break; + } + // We can only start a RUN_SERIAL test if no other tests are also running. + if (this->Properties[*test]->RunSerial && this->RunningCount > 0) + { + continue; + } + size_t processors = GetProcessorsUsed(*test); + bool testLoadOk = true; + if (this->TestLoad > 0) + { + if (processors <= spareLoad) + { + cmCTestLog(this->CTest, DEBUG, + "OK to run " << GetName(*test) << + ", it requires " << processors << + " procs & system load is: " << + systemLoad << std::endl); + allTestsFailedTestLoadCheck = false; + } + else + { + testLoadOk = false; + } + } - if(processors <= numToStart && this->StartTest(*test)) + if (processors <= minProcessorsRequired) { - if(this->StopTimePassed) - { - return; - } - numToStart -= processors; + minProcessorsRequired = processors; + testWithMinProcessors = GetName(*test); + } + + if(testLoadOk && processors <= numToStart && this->StartTest(*test)) + { + if(this->StopTimePassed) + { + return; + } + + numToStart -= processors; } else if(numToStart == 0) { - return; + break; + } + } + + if (allTestsFailedTestLoadCheck) + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, "); + if (this->SerialTestRunning) + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "Waiting for RUN_SERIAL test to finish."); + } + else + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "System Load: " << systemLoad << ", " + "Max Allowed Load: " << this->TestLoad << ", " + "Smallest test " << testWithMinProcessors << + " requires " << minProcessorsRequired); + } + cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl); + + if (usedFakeLoadForTesting) + { + // Break out of the infinite loop of waiting for our fake load + // to come down. + this->StopTimePassed = true; + } + else + { + // Wait between 1 and 5 seconds before trying again. + cmCTestScriptHandler::SleepInSeconds( + cmSystemTools::RandomSeed() % 5 + 1); } } } @@ -319,6 +451,11 @@ bool cmCTestMultiProcessHandler::CheckOutput() this->WriteCheckpoint(test); this->UnlockResources(test); this->RunningCount -= GetProcessorsUsed(test); + if (this->Properties[test]->RunSerial) + { + this->SerialTestRunning = false; + } + delete p; } return true; diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 6440fbc..ed3e155 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -37,6 +37,7 @@ public: void SetTests(TestMap& tests, PropertiesMap& properties); // Set the max number of tests that can be run at the same time. void SetParallelLevel(size_t); + void SetTestLoad(unsigned long load); virtual void RunTests(); void PrintTestList(); void PrintLabels(); @@ -93,6 +94,7 @@ protected: bool CheckCycles(); int FindMaxIndex(); inline size_t GetProcessorsUsed(int index); + std::string GetName(int index); void LockResources(int index); void UnlockResources(int index); @@ -116,11 +118,13 @@ protected: std::set<std::string> LockedResources; std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults; size_t ParallelLevel; // max number of process that can be run at once + unsigned long TestLoad; std::set<cmCTestRunTest*> RunningTests; // current running tests cmCTestTestHandler * TestHandler; cmCTest* CTest; bool HasCycles; bool Quiet; + bool SerialTestRunning; }; #endif diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 31002a6..5e0c54a 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -13,10 +13,8 @@ #include "cmCTest.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" #include <cmsys/RegularExpression.hxx> -#include <cmsys/ios/sstream> #include <cmsys/Process.h> #include <sys/types.h> diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index d9e4bd4..d108592 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -57,8 +57,7 @@ bool cmCTestRunTest::CheckOutput() // Process has terminated and all output read. return false; } - else if(p == cmsysProcess_Pipe_STDOUT || - p == cmsysProcess_Pipe_STDERR) + else if(p == cmsysProcess_Pipe_STDOUT) { // Store this line of output. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 047bd98..c1ba279 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -125,42 +125,25 @@ void cmCTestScriptHandler::Initialize() // what time in seconds did this script start running this->ScriptStartTime = 0; + delete this->Makefile; this->Makefile = 0; - if (this->LocalGenerator) - { - delete this->LocalGenerator; - } + + delete this->LocalGenerator; this->LocalGenerator = 0; - if (this->GlobalGenerator) - { - delete this->GlobalGenerator; - } + + delete this->GlobalGenerator; this->GlobalGenerator = 0; - if (this->CMake) - { - delete this->CMake; - } + + delete this->CMake; } //---------------------------------------------------------------------- cmCTestScriptHandler::~cmCTestScriptHandler() { - // local generator owns the makefile - this->Makefile = 0; - if (this->LocalGenerator) - { - delete this->LocalGenerator; - } - this->LocalGenerator = 0; - if (this->GlobalGenerator) - { - delete this->GlobalGenerator; - } - this->GlobalGenerator = 0; - if (this->CMake) - { - delete this->CMake; - } + delete this->Makefile; + delete this->LocalGenerator; + delete this->GlobalGenerator; + delete this->CMake; } @@ -334,6 +317,7 @@ void cmCTestScriptHandler::CreateCMake() delete this->CMake; delete this->GlobalGenerator; delete this->LocalGenerator; + delete this->Makefile; } this->CMake = new cmake; this->CMake->SetHomeDirectory(""); @@ -341,8 +325,10 @@ void cmCTestScriptHandler::CreateCMake() this->CMake->AddCMakePaths(); this->GlobalGenerator = new cmGlobalGenerator(this->CMake); - this->LocalGenerator = this->GlobalGenerator->MakeLocalGenerator(); - this->Makefile = this->LocalGenerator->GetMakefile(); + cmState::Snapshot snapshot = this->CMake->GetCurrentSnapshot(); + this->Makefile = new cmMakefile(this->GlobalGenerator, snapshot); + this->LocalGenerator = + this->GlobalGenerator->CreateLocalGenerator(this->Makefile); this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest); diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 8b357ac..b7d8318 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -26,6 +26,7 @@ cmCTestTestCommand::cmCTestTestCommand() this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL"; this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM"; this->Arguments[ctt_STOP_TIME] = "STOP_TIME"; + this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD"; this->Arguments[ctt_LAST] = 0; this->Last = ctt_LAST; } @@ -103,6 +104,38 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() { this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]); } + + // Test load is determined by: TEST_LOAD argument, + // or CTEST_TEST_LOAD script variable, or ctest --test-load + // command line argument... in that order. + unsigned long testLoad; + const char* ctestTestLoad + = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); + if(this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) + { + if (!cmSystemTools::StringToULong(this->Values[ctt_TEST_LOAD], &testLoad)) + { + testLoad = 0; + cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : " + << this->Values[ctt_TEST_LOAD] << std::endl); + } + } + else if(ctestTestLoad && *ctestTestLoad) + { + if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) + { + testLoad = 0; + cmCTestLog(this->CTest, WARNING, + "Invalid value for 'CTEST_TEST_LOAD' : " << + ctestTestLoad << std::endl); + } + } + else + { + testLoad = this->CTest->GetTestLoad(); + } + handler->SetTestLoad(testLoad); + handler->SetQuiet(this->Quiet); return handler; } diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index a1e5f36..0dfca97 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -60,6 +60,7 @@ protected: ctt_PARALLEL_LEVEL, ctt_SCHEDULE_RANDOM, ctt_STOP_TIME, + ctt_TEST_LOAD, ctt_LAST }; }; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 2af09cb..f9678e7 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -656,9 +656,8 @@ int cmCTestTestHandler::ProcessHandler() void cmCTestTestHandler::PrintLabelSummary() { cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin(); - cmCTestTestHandler::TestResultsVector::iterator ri = - this->TestResults.begin(); std::map<std::string, double> labelTimes; + std::map<std::string, int> labelCounts; std::set<std::string> labels; // initialize maps std::string::size_type maxlen = 0; @@ -676,10 +675,12 @@ void cmCTestTestHandler::PrintLabelSummary() } labels.insert(*l); labelTimes[*l] = 0; + labelCounts[*l] = 0; } } } - ri = this->TestResults.begin(); + cmCTestTestHandler::TestResultsVector::iterator ri = + this->TestResults.begin(); // fill maps for(; ri != this->TestResults.end(); ++ri) { @@ -691,6 +692,7 @@ void cmCTestTestHandler::PrintLabelSummary() l != p.Labels.end(); ++l) { labelTimes[*l] += result.ExecutionTime; + ++labelCounts[*l]; } } } @@ -705,10 +707,21 @@ void cmCTestTestHandler::PrintLabelSummary() { std::string label = *i; label.resize(maxlen +3, ' '); + char buf[1024]; sprintf(buf, "%6.2f sec", labelTimes[*i]); + + std::ostringstream labelCountStr; + labelCountStr << "(" << labelCounts[*i] << " test"; + if (labelCounts[*i] > 1) + { + labelCountStr << "s"; + } + labelCountStr << ")"; + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n" - << label << " = " << buf, this->Quiet ); + << label << " = " << buf << " " << labelCountStr.str(), + this->Quiet ); if ( this->LogFile ) { *this->LogFile << "\n" << *i << " = " @@ -1062,6 +1075,14 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string> &passed, parallel->SetParallelLevel(this->CTest->GetParallelLevel()); parallel->SetTestHandler(this); parallel->SetQuiet(this->Quiet); + if(this->TestLoad > 0) + { + parallel->SetTestLoad(this->TestLoad); + } + else + { + parallel->SetTestLoad(this->CTest->GetTestLoad()); + } *this->LogFile << "Start testing: " << this->CTest->CurrentTime() << std::endl @@ -1571,8 +1592,9 @@ void cmCTestTestHandler::GetListOfTests() cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmGlobalGenerator gg(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); - cmMakefile *mf = lg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lg( + gg.CreateLocalGenerator(mf.get())); mf->AddDefinition("CTEST_CONFIGURATION_TYPE", this->CTest->GetConfigType().c_str()); @@ -2070,7 +2092,7 @@ bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) } current = next; } - else // Bad byte will be handled by cmXMLSafe. + else // Bad byte will be handled by cmXMLWriter. { ++current; } diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 8494d28..963e501 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -283,13 +283,13 @@ int cmCTestUpdateHandler::ProcessHandler() { xml.Content("Update command failed:\n"); xml.Content(vc->GetUpdateCommandLine()); - cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: " + cmCTestLog(this->CTest, HANDLER_OUTPUT, " Update command failed: " << vc->GetUpdateCommandLine() << "\n"); } xml.EndElement(); // UpdateReturnStatus xml.EndElement(); // Update xml.EndDocument(); - return numUpdated; + return updated? numUpdated : -1; } //---------------------------------------------------------------------- diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index e1bd02b..0c25f40 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -62,6 +62,7 @@ bool cmProcess::StartProcess() this->WorkingDirectory.c_str()); } cmsysProcess_SetTimeout(this->Process, this->Timeout); + cmsysProcess_SetOption(this->Process, cmsysProcess_Option_MergeOutput, 1); cmsysProcess_Execute(this->Process); return (cmsysProcess_GetState(this->Process) == cmsysProcess_State_Executing); @@ -124,14 +125,10 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) for(;;) { // Look for lines already buffered. - if(this->StdOut.GetLine(line)) + if(this->Output.GetLine(line)) { return cmsysProcess_Pipe_STDOUT; } - else if(this->StdErr.GetLine(line)) - { - return cmsysProcess_Pipe_STDERR; - } // Check for more data from the process. char* data; @@ -143,11 +140,7 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) } else if(p == cmsysProcess_Pipe_STDOUT) { - this->StdOut.insert(this->StdOut.end(), data, data+length); - } - else if(p == cmsysProcess_Pipe_STDERR) - { - this->StdErr.insert(this->StdErr.end(), data, data+length); + this->Output.insert(this->Output.end(), data, data+length); } else // p == cmsysProcess_Pipe_None { @@ -157,14 +150,10 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) } // Look for partial last lines. - if(this->StdOut.GetLast(line)) + if(this->Output.GetLast(line)) { return cmsysProcess_Pipe_STDOUT; } - else if(this->StdErr.GetLast(line)) - { - return cmsysProcess_Pipe_STDERR; - } // No more data. Wait for process exit. if(!cmsysProcess_WaitForExit(this->Process, &timeout)) diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 1479df0..eddeeab 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -48,8 +48,7 @@ public: * Read one line of output but block for no more than timeout. * Returns: * cmsysProcess_Pipe_None = Process terminated and all output read - * cmsysProcess_Pipe_STDOUT = Line came from stdout - * cmsysProcess_Pipe_STDOUT = Line came from stderr + * cmsysProcess_Pipe_STDOUT = Line came from stdout or stderr * cmsysProcess_Pipe_Timeout = Timeout expired while waiting */ int GetNextOutputLine(std::string& line, double timeout); @@ -68,13 +67,11 @@ private: bool GetLine(std::string& line); bool GetLast(std::string& line); }; - Buffer StdErr; - Buffer StdOut; + Buffer Output; std::string Command; std::string WorkingDirectory; std::vector<std::string> Arguments; std::vector<const char*> ProcessArgs; - std::string Output; int Id; int ExitValue; }; diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt index 7d4e88c..93ff425 100644 --- a/Source/CursesDialog/CMakeLists.txt +++ b/Source/CursesDialog/CMakeLists.txt @@ -47,4 +47,5 @@ else() target_link_libraries(ccmake cmForm) endif() -install(TARGETS ccmake DESTINATION bin) +CMake_OPTIONAL_COMPONENT(ccmake) +install(TARGETS ccmake DESTINATION bin ${COMPONENT}) diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 168f57d..ad6a7fb 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -14,6 +14,7 @@ project(QtDialog) if(POLICY CMP0020) cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required endif() +CMake_OPTIONAL_COMPONENT(cmake-gui) find_package(Qt5Widgets QUIET) if (Qt5Widgets_FOUND) include_directories(${Qt5Widgets_INCLUDE_DIRS}) @@ -35,30 +36,46 @@ if (Qt5Widgets_FOUND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") - # We need to install Cocoa platform plugin and add qt.conf for Qt5 on Mac. + # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows. # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly - # Qt5 Mac support is missing there. - if(APPLE) + # Qt5 support is missing there. + if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var) get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) if(EXISTS "${_qt_plugin_path}") get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) - set(_qt_plugin_dest "PlugIns/${_qt_plugin_type}") + if(APPLE) + set(_qt_plugin_dir "PlugIns") + elseif(WIN32) + set(_qt_plugin_dir "plugins") + endif() + set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}") install(FILES "${_qt_plugin_path}" - DESTINATION "${_qt_plugin_dest}") + DESTINATION "${_qt_plugin_dest}" + ${COMPONENT}) set(${_qt_plugins_var} "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") else() message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") endif() endmacro() - install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - "[Paths]\nPlugins = PlugIns\n") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources") + if(APPLE) + install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins = ${_qt_plugin_dir}\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" + ${COMPONENT}) + elseif(WIN32) + install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins = ../${_qt_plugin_dir}\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION bin + ${COMPONENT}) + endif() endif() if(WIN32 AND TARGET Qt5::Core) @@ -130,7 +147,8 @@ endif() if(CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL) install(FILES ${CMake_SOURCE_DIR}/Licenses/LGPLv2.1.txt - DESTINATION ${CMAKE_DATA_DIR}/Licenses) + DESTINATION ${CMAKE_DATA_DIR}/Licenses + ${COMPONENT}) set_property(SOURCE CMakeSetupDialog.cxx PROPERTY COMPILE_DEFINITIONS CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL) endif() @@ -163,30 +181,39 @@ if(APPLE) ) endif() set(CMAKE_INSTALL_DESTINATION_ARGS - BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}") + BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT}) -install(TARGETS cmake-gui RUNTIME DESTINATION bin ${CMAKE_INSTALL_DESTINATION_ARGS}) +install(TARGETS cmake-gui + RUNTIME DESTINATION bin ${COMPONENT} + ${CMAKE_INSTALL_DESTINATION_ARGS}) if(UNIX AND NOT APPLE) foreach (size IN ITEMS 32 128) install( FILES "${CMAKE_CURRENT_SOURCE_DIR}/CMakeSetup${size}.png" DESTINATION "share/icons/hicolor/${size}x${size}/apps" + ${COMPONENT} RENAME "CMakeSetup.png") endforeach () # install a desktop file so CMake appears in the application start menu # with an icon - install(FILES CMake.desktop DESTINATION share/applications ) - install(FILES cmakecache.xml DESTINATION share/mime/packages ) + install(FILES CMake.desktop + DESTINATION share/applications + ${COMPONENT}) + install(FILES cmakecache.xml + DESTINATION share/mime/packages + ${COMPONENT}) endif() if(APPLE) - install(CODE "execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui - WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)") + install(CODE " + execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui + WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin) + " ${COMPONENT}) endif() -if(APPLE OR WIN32) +if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) # install rules for including 3rd party libs such as Qt # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}") @@ -197,7 +224,7 @@ if(APPLE OR WIN32) include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\") set(BU_CHMOD_BUNDLE_ITEMS ON) fixup_bundle(\"${fixup_exe}\" \"${QT_PLUGINS}\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\") - ") + " ${COMPONENT}) endif() set(CMAKE_PACKAGE_QTGUI TRUE) diff --git a/Source/QtDialog/Info.plist.in b/Source/QtDialog/Info.plist.in index b9c4af5..00a27c3 100644 --- a/Source/QtDialog/Info.plist.in +++ b/Source/QtDialog/Info.plist.in @@ -28,5 +28,7 @@ <string>public.app-category.developer-tools</string> <key>NSHumanReadableCopyright</key> <string>${MACOSX_BUNDLE_COPYRIGHT}</string> + <key>NSHighResolutionCapable</key> + <true/> </dict> </plist> diff --git a/Source/QtIFW/CMake.Dialogs.QtGUI.qs b/Source/QtIFW/CMake.Dialogs.QtGUI.qs new file mode 100644 index 0000000..219a0a9 --- /dev/null +++ b/Source/QtIFW/CMake.Dialogs.QtGUI.qs @@ -0,0 +1,21 @@ +// Component: CMake.Dialogs.QtGUI + +function Component() +{ + // Default constructor +} + +Component.prototype.createOperations = function() +{ + // Create shortcut + if (installer.value("os") === "win") { + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/bin/cmake-gui.exe", + installer.value("StartMenuDir") + "/CMake (cmake-gui).lnk"); + + } + + // Call default implementation + component.createOperations(); +} diff --git a/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in b/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in new file mode 100644 index 0000000..5c929e8 --- /dev/null +++ b/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in @@ -0,0 +1,21 @@ +// Component: CMake.Documentation.SphinxHTML + +function Component() +{ + // Default constructor +} + +Component.prototype.createOperations = function() +{ + // Create shortcut + if (installer.value("os") === "win") { + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/html/index.html", + installer.value("StartMenuDir") + "/CMake Documentation.lnk"); + + } + + // Call default implementation + component.createOperations(); +} diff --git a/Source/QtIFW/CMake.qs.in b/Source/QtIFW/CMake.qs.in new file mode 100644 index 0000000..828cc7c --- /dev/null +++ b/Source/QtIFW/CMake.qs.in @@ -0,0 +1,22 @@ +function Component() +{ + // Default constructor +} + +Component.prototype.createOperations = function() +{ + // Create shortcut + if (installer.value("os") === "win") { + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/cmake.org.html", + installer.value("StartMenuDir") + "/CMake Web Site.lnk"); + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/cmake-maintenance.exe", + installer.value("StartMenuDir") + "/CMake Maintenance Tool.lnk"); + } + + // Call default implementation + component.createOperations(); +} diff --git a/Source/QtIFW/installscript.qs.in b/Source/QtIFW/installscript.qs.in index 570dba1..3411e34 100644 --- a/Source/QtIFW/installscript.qs.in +++ b/Source/QtIFW/installscript.qs.in @@ -5,20 +5,20 @@ function Component() Component.prototype.createOperations = function() { - // call default implementation to actually install applications! - component.createOperations(); - // Create shortcut if (installer.value("os") === "win") { @_CPACK_IFW_SHORTCUT_OPTIONAL@ component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/cmake.org.html", + installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/cmake.org.html", installer.value("StartMenuDir") + "/CMake Web Site.lnk"); component.addOperation("CreateShortcut", installer.value("TargetDir") + "/cmake-maintenance.exe", installer.value("StartMenuDir") + "/CMake Maintenance Tool.lnk"); } + + // Call default implementation + component.createOperations(); } diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx new file mode 100644 index 0000000..11e3f34 --- /dev/null +++ b/Source/bindexplib.cxx @@ -0,0 +1,428 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +/*------------------------------------------------------------------------- + Portions of this source have been derived from the 'bindexplib' tool + provided by the CERN ROOT Data Analysis Framework project (root.cern.ch). + Permission has been granted by Pere Mato <pere.mato@cern.ch> to distribute + this derived work under the CMake license. +-------------------------------------------------------------------------*/ + +/* +*---------------------------------------------------------------------- +* Program: dumpexts.exe +* Author: Gordon Chaffee +* +* History: The real functionality of this file was written by +* Matt Pietrek in 1993 in his pedump utility. I've +* modified it to dump the externals in a bunch of object +* files to create a .def file. +* +* Notes: Visual C++ puts an underscore before each exported symbol. +* This file removes them. I don't know if this is a problem +* this other compilers. If _MSC_VER is defined, +* the underscore is removed. If not, it isn't. To get a +* full dump of an object file, use the -f option. This can +* help determine the something that may be different with a +* compiler other than Visual C++. +* ====================================== +* Corrections (Axel 2006-04-04): +* Conversion to C++. Mostly. +* + * Extension (Axel 2006-03-15) + * As soon as an object file contains an /EXPORT directive (which + * is generated by the compiler when a symbol is declared as + * declspec(dllexport)) no to-be-exported symbols are printed, + * as the linker will see these directives, and if those directives + * are present we only export selectively (i.e. we trust the + * programmer). + * + * ====================================== +* ====================================== +* Corrections (Valery Fine 23/02/98): +* +* The "(vector) deleting destructor" MUST not be exported +* To recognize it the following test are introduced: +* "@@UAEPAXI@Z" scalar deleting dtor +* "@@QAEPAXI@Z" vector deleting dtor +* "AEPAXI@Z" vector deleting dtor with thunk adjustor +* ====================================== +* Corrections (Valery Fine 12/02/97): +* +* It created a wrong EXPORTS for the global pointers and constants. +* The Section Header has been involved to discover the missing information +* Now the pointers are correctly supplied supplied with "DATA" descriptor +* the constants with no extra descriptor. +* +* Corrections (Valery Fine 16/09/96): +* +* It didn't work for C++ code with global variables and class definitons +* The DumpExternalObject function has been introduced to generate .DEF file +* +* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch) +*---------------------------------------------------------------------- +*/ + +#include <cmsys/Encoding.hxx> +#include <windows.h> +#include <stdio.h> +#include <string> +#include <fstream> +#include <iostream> + +typedef struct cmANON_OBJECT_HEADER_BIGOBJ { + /* same as ANON_OBJECT_HEADER_V2 */ + WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN + WORD Sig2; // Must be 0xffff + WORD Version; // >= 2 (implies the Flags field is present) + WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx + DWORD TimeDateStamp; + CLSID ClassID; // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8} + DWORD SizeOfData; // Size of data that follows the header + DWORD Flags; // 0x1 -> contains metadata + DWORD MetaDataSize; // Size of CLR metadata + DWORD MetaDataOffset; // Offset of CLR metadata + + /* bigobj specifics */ + DWORD NumberOfSections; // extended from WORD + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; +} cmANON_OBJECT_HEADER_BIGOBJ; + +typedef struct _cmIMAGE_SYMBOL_EX { + union { + BYTE ShortName[8]; + struct { + DWORD Short; // if 0, use LongName + DWORD Long; // offset into string table + } Name; + DWORD LongName[2]; // PBYTE [2] + } N; + DWORD Value; + LONG SectionNumber; + WORD Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} cmIMAGE_SYMBOL_EX; +typedef cmIMAGE_SYMBOL_EX UNALIGNED *cmPIMAGE_SYMBOL_EX; + +PIMAGE_SECTION_HEADER GetSectionHeaderOffset(PIMAGE_FILE_HEADER + pImageFileHeader) +{ + return (PIMAGE_SECTION_HEADER) + ((DWORD_PTR)pImageFileHeader + + IMAGE_SIZEOF_FILE_HEADER + + pImageFileHeader->SizeOfOptionalHeader); +} + +PIMAGE_SECTION_HEADER GetSectionHeaderOffset(cmANON_OBJECT_HEADER_BIGOBJ* + pImageFileHeader) +{ + return (PIMAGE_SECTION_HEADER) + ((DWORD_PTR)pImageFileHeader + + sizeof(cmANON_OBJECT_HEADER_BIGOBJ)); +} + +/* ++ * Utility func, strstr with size ++ */ +const char* StrNStr(const char* start, const char* find, size_t &size) { + size_t len; + const char* hint; + + if (!start || !find || !size) { + size = 0; + return 0; + } + len = strlen(find); + + while ((hint = (const char*) memchr(start, find[0], size-len+1))) { + size -= (hint - start); + if (!strncmp(hint, find, len)) + return hint; + start = hint + 1; + } + + size = 0; + return 0; +} + +template < + // cmANON_OBJECT_HEADER_BIGOBJ or IMAGE_FILE_HEADER + class ObjectHeaderType, + // cmPIMAGE_SYMBOL_EX or PIMAGE_SYMBOL + class SymbolTableType> +class DumpSymbols +{ +public: + /* + *---------------------------------------------------------------------- + * Constructor -- + * + * Initialize variables from pointer to object header. + * + *---------------------------------------------------------------------- + */ + + DumpSymbols(ObjectHeaderType* ih, + FILE* fout) { + this->ObjectImageHeader = ih; + this->SymbolTable = (SymbolTableType*) + ((DWORD_PTR)this->ObjectImageHeader + + this->ObjectImageHeader->PointerToSymbolTable); + this->FileOut = fout; + this->SectionHeaders = + GetSectionHeaderOffset(this->ObjectImageHeader); + this->ImportFlag = true; + this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols; + } + + /* + *---------------------------------------------------------------------- + * HaveExportedObjects -- + * + * Returns true if export directives (declspec(dllexport)) exist. + * + *---------------------------------------------------------------------- + */ + + bool HaveExportedObjects() { + WORD i = 0; + size_t size = 0; + const char * rawdata = 0; + PIMAGE_SECTION_HEADER pDirectivesSectionHeader = 0; + PIMAGE_SECTION_HEADER pSectionHeaders = this->SectionHeaders; + for(i = 0; (i < this->ObjectImageHeader->NumberOfSections && + !pDirectivesSectionHeader); i++) + if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8)) + pDirectivesSectionHeader = &pSectionHeaders[i]; + if (!pDirectivesSectionHeader) return 0; + + rawdata=(const char*) + this->ObjectImageHeader+pDirectivesSectionHeader->PointerToRawData; + if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; + + size = pDirectivesSectionHeader->SizeOfRawData; + const char* posImportFlag = rawdata; + while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) { + const char* lookingForDict = posImportFlag + 9; + if (!strncmp(lookingForDict, "_G__cpp_",8) || + !strncmp(lookingForDict, "_G__set_cpp_",12)) { + posImportFlag = lookingForDict; + continue; + } + + const char* lookingForDATA = posImportFlag + 9; + while (*(++lookingForDATA) && *lookingForDATA != ' '); + lookingForDATA -= 5; + // ignore DATA exports + if (strncmp(lookingForDATA, ",DATA", 5)) break; + posImportFlag = lookingForDATA + 5; + } + if(posImportFlag) { + return true; + } + return false; + } + + /* + *---------------------------------------------------------------------- + * DumpObjFile -- + * + * Dump an object file's exported symbols. + *---------------------------------------------------------------------- + */ + void DumpObjFile() { + if(!HaveExportedObjects()) { + this->DumpExternalsObjects(); + } + } + + /* + *---------------------------------------------------------------------- + * DumpExternalsObjects -- + * + * Dumps a COFF symbol table from an OBJ. + *---------------------------------------------------------------------- + */ + void DumpExternalsObjects() { + unsigned i; + PSTR stringTable; + std::string symbol; + DWORD SectChar; + /* + * The string table apparently starts right after the symbol table + */ + stringTable = (PSTR)&this->SymbolTable[this->SymbolCount]; + SymbolTableType* pSymbolTable = this->SymbolTable; + for ( i=0; i < this->SymbolCount; i++ ) { + if (pSymbolTable->SectionNumber > 0 && + ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { + if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { + /* + * The name of the Function entry points + */ + if (pSymbolTable->N.Name.Short != 0) { + symbol = ""; + symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8); + } else { + symbol = stringTable + pSymbolTable->N.Name.Long; + } + + // clear out any leading spaces + while (isspace(symbol[0])) symbol.erase(0,1); + // if it starts with _ and has an @ then it is a __cdecl + // so remove the @ stuff for the export + if(symbol[0] == '_') { + std::string::size_type posAt = symbol.find('@'); + if (posAt != std::string::npos) { + symbol.erase(posAt); + } + } + if (symbol[0] == '_') symbol.erase(0,1); + if (this->ImportFlag) { + this->ImportFlag = false; + fprintf(this->FileOut,"EXPORTS \n"); + } + /* + Check whether it is "Scalar deleting destructor" and + "Vector deleting destructor" + */ + const char *scalarPrefix = "??_G"; + const char *vectorPrefix = "??_E"; + // original code had a check for + // symbol.find("real@") == std::string::npos) + // but if this disallows memmber functions with the name real + // if scalarPrefix and vectorPrefix are not found then print + // the symbol + if (symbol.compare(0, 4, scalarPrefix) && + symbol.compare(0, 4, vectorPrefix) ) + { + SectChar = + this-> + SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; + if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) { + // Read only (i.e. constants) must be excluded + fprintf(this->FileOut, "\t%s \t DATA\n", symbol.c_str()); + } else { + if ( pSymbolTable->Type || + !(SectChar & IMAGE_SCN_MEM_READ)) { + fprintf(this->FileOut, "\t%s\n", symbol.c_str()); + } else { + // printf(" strange symbol: %s \n",symbol.c_str()); + } + } + } + } + } + else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED && + !pSymbolTable->Type && 0) { + /* + * The IMPORT global variable entry points + */ + if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { + symbol = stringTable + pSymbolTable->N.Name.Long; + while (isspace(symbol[0])) symbol.erase(0,1); + if (symbol[0] == '_') symbol.erase(0,1); + if (!this->ImportFlag) { + this->ImportFlag = true; + fprintf(this->FileOut,"IMPORTS \n"); + } + fprintf(this->FileOut, "\t%s DATA \n", symbol.c_str()+1); + } + } + + /* + * Take into account any aux symbols + */ + i += pSymbolTable->NumberOfAuxSymbols; + pSymbolTable += pSymbolTable->NumberOfAuxSymbols; + pSymbolTable++; + } + } +private: + bool ImportFlag; + FILE* FileOut; + DWORD_PTR SymbolCount; + PIMAGE_SECTION_HEADER SectionHeaders; + ObjectHeaderType* ObjectImageHeader; + SymbolTableType* SymbolTable; +}; + +bool +DumpFile(const char* filename, FILE *fout) +{ + HANDLE hFile; + HANDLE hFileMapping; + LPVOID lpFileBase; + PIMAGE_DOS_HEADER dosHeader; + + hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(), + GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + if (hFile == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename); + return false; + } + + hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hFileMapping == 0) { + CloseHandle(hFile); + fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n"); + return false; + } + + lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); + if (lpFileBase == 0) { + CloseHandle(hFileMapping); + CloseHandle(hFile); + fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n"); + return false; + } + + dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; + if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { + fprintf(stderr, "File is an executable. I don't dump those.\n"); + return false; + } + /* Does it look like a i386 COFF OBJ file??? */ + else if ( + ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || + (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)) + && (dosHeader->e_sp == 0) + ) { + /* + * The two tests above aren't what they look like. They're + * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) + * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; + */ + DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> + symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout); + symbolDumper.DumpObjFile(); + } else { + // check for /bigobj format + cmANON_OBJECT_HEADER_BIGOBJ* h = + (cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase; + if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) { + DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX> + symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout); + symbolDumper.DumpObjFile(); + } else { + printf("unrecognized file format in '%s'\n", filename); + return false; + } + } + UnmapViewOfFile(lpFileBase); + CloseHandle(hFileMapping); + CloseHandle(hFile); + return true; +} diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index f117475..bda933b 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -122,35 +122,6 @@ struct DefaultDeleter<Range, /* valueTypeIsPair = */ true> } }; -template<typename const_iterator_> -struct Range -{ - typedef const_iterator_ const_iterator; - typedef typename std::iterator_traits<const_iterator>::value_type value_type; - typedef typename std::iterator_traits<const_iterator>::difference_type - difference_type; - Range(const_iterator begin_, const_iterator end_) - : Begin(begin_), End(end_) {} - const_iterator begin() const { return Begin; } - const_iterator end() const { return End; } - bool empty() const { return std::distance(Begin, End) == 0; } - difference_type size() const { return std::distance(Begin, End); } - Range& advance(cmIML_INT_intptr_t amount) - { - std::advance(Begin, amount); - return *this; - } - - Range& retreat(cmIML_INT_intptr_t amount) - { - std::advance(End, -amount); - return *this; - } -private: - const_iterator Begin; - const_iterator End; -}; - template<typename FwdIt> FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n) { @@ -178,17 +149,52 @@ private: } +template<typename const_iterator_> +struct cmRange +{ + typedef const_iterator_ const_iterator; + typedef typename std::iterator_traits<const_iterator>::value_type value_type; + typedef typename std::iterator_traits<const_iterator>::difference_type + difference_type; + cmRange(const_iterator begin_, const_iterator end_) + : Begin(begin_), End(end_) {} + const_iterator begin() const { return Begin; } + const_iterator end() const { return End; } + bool empty() const { return std::distance(Begin, End) == 0; } + difference_type size() const { return std::distance(Begin, End); } + cmRange& advance(cmIML_INT_intptr_t amount) + { + std::advance(Begin, amount); + return *this; + } + + cmRange& retreat(cmIML_INT_intptr_t amount) + { + std::advance(End, -amount); + return *this; + } +private: + const_iterator Begin; + const_iterator End; +}; + +typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange; + +class cmListFileBacktrace; +typedef +cmRange<std::vector<cmListFileBacktrace>::const_iterator> cmBacktraceRange; + template<typename Iter1, typename Iter2> -ContainerAlgorithms::Range<Iter1> cmRange(Iter1 begin, Iter2 end) +cmRange<Iter1> cmMakeRange(Iter1 begin, Iter2 end) { - return ContainerAlgorithms::Range<Iter1>(begin, end); + return cmRange<Iter1>(begin, end); } template<typename Range> -ContainerAlgorithms::Range<typename Range::const_iterator> -cmRange(Range const& range) +cmRange<typename Range::const_iterator> +cmMakeRange(Range const& range) { - return ContainerAlgorithms::Range<typename Range::const_iterator>( + return cmRange<typename Range::const_iterator>( range.begin(), range.end()); } @@ -350,11 +356,17 @@ typename Range::const_iterator cmFindNot(Range const& r, T const& t) } template<typename Range> -ContainerAlgorithms::Range<typename Range::const_reverse_iterator> +cmRange<typename Range::const_reverse_iterator> cmReverseRange(Range const& range) { - return ContainerAlgorithms::Range<typename Range::const_reverse_iterator>( + return cmRange<typename Range::const_reverse_iterator>( range.rbegin(), range.rend()); } +template <class Iter> +std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it) +{ + return std::reverse_iterator<Iter>(it); +} + #endif diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 72818f5..9f56324 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -13,7 +13,6 @@ #include "cmSystemTools.h" #include "cmLocale.h" -#include <cmsys/ios/iostream> #include <cmsys/Directory.hxx> #include <cmsys/FStream.hxx> #include <cm_libarchive.h> @@ -67,7 +66,7 @@ struct cmArchiveWrite::Callback { cmArchiveWrite* self = static_cast<cmArchiveWrite*>(cd); if(self->Stream.write(static_cast<const char*>(b), - static_cast<cmsys_ios::streamsize>(n))) + static_cast<std::streamsize>(n))) { return static_cast<__LA_SSIZE_T>(n); } @@ -84,54 +83,55 @@ cmArchiveWrite::cmArchiveWrite( Stream(os), Archive(archive_write_new()), Disk(archive_read_disk_new()), - Verbose(false) + Verbose(false), + Format(format) { switch (c) { case CompressNone: - if(archive_write_set_compression_none(this->Archive) != ARCHIVE_OK) + if(archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_set_compression_none: "; + this->Error = "archive_write_add_filter_none: "; this->Error += cm_archive_error_string(this->Archive); return; } break; case CompressCompress: - if(archive_write_set_compression_compress(this->Archive) != ARCHIVE_OK) + if(archive_write_add_filter_compress(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_set_compression_compress: "; + this->Error = "archive_write_add_filter_compress: "; this->Error += cm_archive_error_string(this->Archive); return; } break; case CompressGZip: - if(archive_write_set_compression_gzip(this->Archive) != ARCHIVE_OK) + if(archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_set_compression_gzip: "; + this->Error = "archive_write_add_filter_gzip: "; this->Error += cm_archive_error_string(this->Archive); return; } break; case CompressBZip2: - if(archive_write_set_compression_bzip2(this->Archive) != ARCHIVE_OK) + if(archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_set_compression_bzip2: "; + this->Error = "archive_write_add_filter_bzip2: "; this->Error += cm_archive_error_string(this->Archive); return; } break; case CompressLZMA: - if(archive_write_set_compression_lzma(this->Archive) != ARCHIVE_OK) + if(archive_write_add_filter_lzma(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_set_compression_lzma: "; + this->Error = "archive_write_add_filter_lzma: "; this->Error += cm_archive_error_string(this->Archive); return; } break; case CompressXZ: - if(archive_write_set_compression_xz(this->Archive) != ARCHIVE_OK) + if(archive_write_add_filter_xz(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_set_compression_xz: "; + this->Error = "archive_write_add_filter_xz: "; this->Error += cm_archive_error_string(this->Archive); return; } @@ -176,8 +176,8 @@ cmArchiveWrite::cmArchiveWrite( //---------------------------------------------------------------------------- cmArchiveWrite::~cmArchiveWrite() { - archive_read_finish(this->Disk); - archive_write_finish(this->Archive); + archive_read_free(this->Disk); + archive_write_free(this->Archive); } //---------------------------------------------------------------------------- @@ -282,6 +282,14 @@ bool cmArchiveWrite::AddFile(const char* file, archive_entry_acl_clear(e); archive_entry_xattr_clear(e); archive_entry_set_fflags(e, 0, 0); + + if (this->Format == "pax" || this->Format == "paxr") + { + // Sparse files are a GNU tar extension. + // Do not use them in standard tar files. + archive_entry_sparse_clear(e); + } + if(archive_write_header(this->Archive, e) != ARCHIVE_OK) { this->Error = "archive_write_header: "; @@ -304,7 +312,7 @@ bool cmArchiveWrite::AddFile(const char* file, //---------------------------------------------------------------------------- bool cmArchiveWrite::AddData(const char* file, size_t size) { - cmsys::ifstream fin(file, std::ios::in | cmsys_ios_binary); + cmsys::ifstream fin(file, std::ios::in | std::ios::binary); if(!fin) { this->Error = "Error opening \""; @@ -318,7 +326,7 @@ bool cmArchiveWrite::AddData(const char* file, size_t size) size_t nleft = size; while(nleft > 0) { - typedef cmsys_ios::streamsize ssize_type; + typedef std::streamsize ssize_type; size_t const nnext = nleft > sizeof(buffer)? sizeof(buffer) : nleft; ssize_type const nnext_s = static_cast<ssize_type>(nnext); fin.read(buffer, nnext_s); diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 794cb28..e6f515d 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -84,6 +84,7 @@ private: struct archive* Archive; struct archive* Disk; bool Verbose; + std::string Format; std::string Error; std::string MTime; }; diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 5234538..6ff7c0d 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -11,8 +11,6 @@ ============================================================================*/ #include "cmCMakeHostSystemInformationCommand.h" -#include <cmsys/ios/sstream> - // cmCMakeHostSystemInformation bool cmCMakeHostSystemInformationCommand ::InitialPass(std::vector<std::string> const &args, cmExecutionStatus &) @@ -107,7 +105,7 @@ bool cmCMakeHostSystemInformationCommand std::string cmCMakeHostSystemInformationCommand ::ValueToString(size_t value) const { - cmsys_ios::stringstream tmp; + std::stringstream tmp; tmp << value; return tmp.str(); } diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 3c878bf..3ef6d35 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -93,6 +93,22 @@ bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args) this->SetError("SET failed to set policy."); return false; } + if(args[1] == "CMP0001" && + (status == cmPolicies::WARN || status == cmPolicies::OLD)) + { + if(!(this->Makefile->GetState() + ->GetInitializedCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))) + { + // Set it to 2.4 because that is the last version where the + // variable had meaning. + this->Makefile->AddCacheDefinition + ("CMAKE_BACKWARDS_COMPATIBILITY", "2.4", + "For backwards compatibility, what version of CMake " + "commands and " + "syntax should this version of CMake try to support.", + cmState::STRING); + } + } return true; } diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx index cf24c13..cbcdd81 100644 --- a/Source/cmCPackPropertiesGenerator.cxx +++ b/Source/cmCPackPropertiesGenerator.cxx @@ -1,13 +1,14 @@ #include "cmCPackPropertiesGenerator.h" +#include "cmOutputConverter.h" #include "cmLocalGenerator.h" cmCPackPropertiesGenerator::cmCPackPropertiesGenerator( - cmMakefile* mf, + cmLocalGenerator* lg, cmInstalledFile const& installedFile, std::vector<std::string> const& configurations): cmScriptGenerator("CPACK_BUILD_CONFIG", configurations), - Makefile(mf), + LG(lg), InstalledFile(installedFile) { this->ActionsPerConfig = true; @@ -17,7 +18,8 @@ void cmCPackPropertiesGenerator::GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent const& indent) { std::string const& expandedFileName = - this->InstalledFile.GetNameExpression().Evaluate(this->Makefile, config); + this->InstalledFile.GetNameExpression().Evaluate(this->LG->GetMakefile(), + config); cmInstalledFile::PropertyMapType const& properties = this->InstalledFile.GetProperties(); @@ -29,15 +31,15 @@ void cmCPackPropertiesGenerator::GenerateScriptForConfig(std::ostream& os, cmInstalledFile::Property const& property = i->second; os << indent << "set_property(INSTALL " << - cmLocalGenerator::EscapeForCMake(expandedFileName) << " PROPERTY " << - cmLocalGenerator::EscapeForCMake(name); + cmOutputConverter::EscapeForCMake(expandedFileName) << " PROPERTY " << + cmOutputConverter::EscapeForCMake(name); for(cmInstalledFile::ExpressionVectorType::const_iterator j = property.ValueExpressions.begin(); j != property.ValueExpressions.end(); ++j) { - std::string value = (*j)->Evaluate(this->Makefile, config); - os << " " << cmLocalGenerator::EscapeForCMake(value); + std::string value = (*j)->Evaluate(LG->GetMakefile(), config); + os << " " << cmOutputConverter::EscapeForCMake(value); } os << ")\n"; diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h index 71e2eaa..eec3df0 100644 --- a/Source/cmCPackPropertiesGenerator.h +++ b/Source/cmCPackPropertiesGenerator.h @@ -15,6 +15,8 @@ #include "cmScriptGenerator.h" #include "cmInstalledFile.h" +class cmLocalGenerator; + /** \class cmCPackPropertiesGenerator * \brief Support class for generating CPackProperties.cmake. * @@ -23,7 +25,7 @@ class cmCPackPropertiesGenerator: public cmScriptGenerator { public: cmCPackPropertiesGenerator( - cmMakefile* mf, + cmLocalGenerator* lg, cmInstalledFile const& installedFile, std::vector<std::string> const& configurations); @@ -31,7 +33,7 @@ protected: virtual void GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent const& indent); - cmMakefile* Makefile; + cmLocalGenerator* LG; cmInstalledFile const& InstalledFile; }; diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index c55ea35..7da334e 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -115,7 +115,9 @@ void CCONV cmAddCacheDefinition(void *arg, const char* name, const char* CCONV cmGetProjectName(void *arg) { cmMakefile *mf = static_cast<cmMakefile *>(arg); - return mf->GetProjectName(); + static std::string name; + name = mf->GetProjectName(); + return name.c_str(); } const char* CCONV cmGetHomeDirectory(void *arg) @@ -426,8 +428,7 @@ int CCONV cmExecuteCommand(void *arg, const char *name, { // Assume all arguments are quoted. lff.Arguments.push_back( - cmListFileArgument(args[i], cmListFileArgument::Quoted, - "[CMake-Plugin]", 0)); + cmListFileArgument(args[i], cmListFileArgument::Quoted, 0)); } cmExecutionStatus status; return mf->ExecuteCommand(lff,status); @@ -526,11 +527,9 @@ void * CCONV cmCreateSourceFile(void) return (void*)new cmCPluginAPISourceFile; } -void * CCONV cmCreateNewSourceFile(void *arg) +void * CCONV cmCreateNewSourceFile(void *) { - cmMakefile *mf = static_cast<cmMakefile *>(arg); cmCPluginAPISourceFile *sf = new cmCPluginAPISourceFile; - sf->Properties.SetCMakeInstance(mf->GetCMakeInstance()); return (void*)sf; } @@ -630,11 +629,7 @@ const char * CCONV cmSourceFileGetProperty(void *arg,const char *prop) { return sf->FullPath.c_str(); } - bool chain = false; - // Ignore chain because old code will not expect it and it is a - // pain to implement here anyway. - return sf->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE, - chain); + return sf->Properties.GetPropertyValue(prop); } } @@ -662,7 +657,7 @@ void CCONV cmSourceFileSetProperty(void *arg,const char *prop, else if(prop) { if(!value) { value = "NOTFOUND"; } - sf->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE); + sf->Properties.SetProperty(prop, value); } } @@ -801,8 +796,7 @@ void CCONV cmSourceFileSetName2(void *arg, const char* name, const char* dir, // Implement the old SetName method code here. if(headerFileOnly) { - sf->Properties.SetProperty("HEADER_FILE_ONLY", "1", - cmProperty::SOURCE_FILE); + sf->Properties.SetProperty("HEADER_FILE_ONLY", "1"); } sf->SourceName = name; std::string fname = sf->SourceName; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index e3b7a2b..b2ad4a8 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -22,7 +22,6 @@ #include <cmsys/FStream.hxx> #include "cmDynamicLoader.h" #include "cmGeneratedFileStream.h" -#include "cmXMLSafe.h" #include "cmVersionMacros.h" #include "cmCTestCommand.h" #include "cmCTestStartCommand.h" @@ -156,7 +155,7 @@ std::string cmCTest::CurrentTime() strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t); } cmCTestLog(this, DEBUG, " Current_Time: " << current_time << std::endl); - return cmXMLSafe(cmCTest::CleanString(current_time)).str(); + return cmCTest::CleanString(current_time); } //---------------------------------------------------------------------- @@ -294,6 +293,7 @@ cmCTest::cmCTest() this->LabelSummary = true; this->ParallelLevel = 1; this->ParallelLevelSetInCli = false; + this->TestLoad = 0; this->SubmitIndex = 0; this->Failover = false; this->BatchJobs = false; @@ -393,6 +393,11 @@ void cmCTest::SetParallelLevel(int level) this->ParallelLevel = level < 1 ? 1 : level; } +void cmCTest::SetTestLoad(unsigned long load) +{ + this->TestLoad = load; +} + //---------------------------------------------------------------------------- bool cmCTest::ShouldCompressTestOutput() { @@ -514,9 +519,10 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmGlobalGenerator gg(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); - cmMakefile *mf = lg->GetMakefile(); - if ( !this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), mf) ) + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator(mf.get())); + if ( !this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), + mf.get()) ) { cmCTestOptionalLog(this, DEBUG, "Cannot find custom configuration file tree" << std::endl, quiet); @@ -820,6 +826,20 @@ bool cmCTest::UpdateCTestConfiguration() cmSystemTools::ChangeDirectory(this->BinaryDir); } this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str()); + std::string const& testLoad = this->GetCTestConfiguration("TestLoad"); + if (!testLoad.empty()) + { + unsigned long load; + if (cmSystemTools::StringToULong(testLoad.c_str(), &load)) + { + this->SetTestLoad(load); + } + else + { + cmCTestLog(this, WARNING, "Invalid value for 'Test Load' : " + << testLoad << std::endl); + } + } if ( this->ProduceXML ) { this->CompressXMLFiles = cmSystemTools::IsOn( @@ -1200,7 +1220,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, char* data; int length; - cmCTestLog(this, HANDLER_OUTPUT, + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Each . represents " << tick_len << " bytes of output" << std::endl << " " << std::flush); while(cmsysProcess_WaitForData(cp, &data, &length, 0)) @@ -1216,10 +1236,10 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, while ( output.size() > (tick * tick_len) ) { tick ++; - cmCTestLog(this, HANDLER_OUTPUT, "." << std::flush); + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush); if ( tick % tick_line_len == 0 && tick > 0 ) { - cmCTestLog(this, HANDLER_OUTPUT, + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size: " << int((double(output.size()) / 1024.0) + 1) << "K" << std::endl @@ -1232,7 +1252,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, ofs << cmCTestLogWrite(data, length); } } - cmCTestLog(this, OUTPUT, " Size of output: " + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size of output: " << int(double(output.size()) / 1024.0) << "K" << std::endl); cmsysProcess_WaitForExit(cp, 0); @@ -1477,8 +1497,6 @@ std::string cmCTest::SafeBuildIdField(const std::string& value) cmSystemTools::ReplaceString(safevalue, replace, ""); } } - - safevalue = cmXMLSafe(safevalue).str(); } if (safevalue == "") @@ -1526,9 +1544,8 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append) xml.Attribute("Append", "true"); } xml.Attribute("CompilerName", this->GetCTestConfiguration("Compiler")); -#ifdef _COMPILER_VERSION - xml.Attribute("CompilerVersion", _COMPILER_VERSION); -#endif + xml.Attribute("CompilerVersion", + this->GetCTestConfiguration("CompilerVersion")); xml.Attribute("OSName", info.GetOSName()); xml.Attribute("Hostname", info.GetHostname()); xml.Attribute("OSRelease", info.GetOSRelease()); @@ -1547,6 +1564,13 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append) xml.Attribute("LogicalProcessorsPerPhysical", info.GetLogicalProcessorsPerPhysical()); xml.Attribute("ProcessorClockFrequency", info.GetProcessorClockFrequency()); + + std::string changeId = this->GetCTestConfiguration("ChangeId"); + if(!changeId.empty()) + { + xml.Attribute("ChangeId", changeId); + } + this->AddSiteProperties(xml); } @@ -2051,6 +2075,21 @@ bool cmCTest::HandleCommandLineArguments(size_t &i, } } + if(this->CheckArgument(arg, "--test-load") && i < args.size() - 1) + { + i++; + unsigned long load; + if (cmSystemTools::StringToULong(args[i].c_str(), &load)) + { + this->SetTestLoad(load); + } + else + { + cmCTestLog(this, WARNING, + "Invalid value for 'Test Load' : " << args[i] << std::endl); + } + } + if(this->CheckArgument(arg, "--no-compress-output")) { this->CompressTestOutput = false; @@ -3066,6 +3105,7 @@ static const char* cmCTestStringLogType[] = "DEBUG", "OUTPUT", "HANDLER_OUTPUT", + "HANDLER_PROGRESS_OUTPUT", "HANDLER_VERBOSE_OUTPUT", "WARNING", "ERROR_MESSAGE", @@ -3104,6 +3144,11 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, { return; } + if ( logType == cmCTest::HANDLER_PROGRESS_OUTPUT && + ( this->Debug || this->ExtraVerbose ) ) + { + return; + } if ( this->OutputLogFile ) { bool display = true; diff --git a/Source/cmCTest.h b/Source/cmCTest.h index db3ea10..73c2807 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -161,6 +161,9 @@ public: int GetParallelLevel() { return this->ParallelLevel; } void SetParallelLevel(int); + unsigned long GetTestLoad() { return this->TestLoad; } + void SetTestLoad(unsigned long); + /** * Check if CTest file exists */ @@ -379,6 +382,7 @@ public: DEBUG = 0, OUTPUT, HANDLER_OUTPUT, + HANDLER_PROGRESS_OUTPUT, HANDLER_VERBOSE_OUTPUT, WARNING, ERROR_MESSAGE, @@ -499,6 +503,8 @@ private: int ParallelLevel; bool ParallelLevelSetInCli; + unsigned long TestLoad; + int CompatibilityMode; // information for the --build-and-test options diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 108208e..54209c5 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -161,7 +161,6 @@ bool cmCacheManager::LoadCache(const std::string& path, // Format is key:type=value std::string helpString; CacheEntry e; - e.Properties.SetCMakeInstance(this->CMakeInstance); cmSystemTools::GetLineFromStream(fin, buffer); realbuffer = buffer.c_str(); while(*realbuffer != '0' && @@ -323,7 +322,6 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, { // Create an entry and store the property. CacheEntry& ne = this->Cache[key]; - ne.Properties.SetCMakeInstance(this->CMakeInstance); ne.Type = cmState::UNINITIALIZED; ne.SetProperty(*p, e.Value.c_str()); } @@ -645,7 +643,6 @@ void cmCacheManager::AddCacheEntry(const std::string& key, cmState::CacheEntryType type) { CacheEntry& e = this->Cache[key]; - e.Properties.SetCMakeInstance(this->CMakeInstance); if ( value ) { e.Value = value; @@ -744,9 +741,7 @@ cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const { return this->Value.c_str(); } - bool c = false; - return - this->Properties.GetPropertyValue(prop, cmProperty::CACHE, c); + return this->Properties.GetPropertyValue(prop); } //---------------------------------------------------------------------------- @@ -763,7 +758,7 @@ void cmCacheManager::CacheEntry::SetProperty(const std::string& prop, } else { - this->Properties.SetProperty(prop, value, cmProperty::CACHE); + this->Properties.SetProperty(prop, value); } } @@ -789,7 +784,7 @@ void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop, } else { - this->Properties.AppendProperty(prop, value, cmProperty::CACHE, asString); + this->Properties.AppendProperty(prop, value, asString); } } diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx index c211111..0e04838 100644 --- a/Source/cmCallVisualStudioMacro.cxx +++ b/Source/cmCallVisualStudioMacro.cxx @@ -498,7 +498,7 @@ int cmCallVisualStudioMacro::CallMacro( } } - if(0 == instances.size()) + if(instances.empty()) { // no instances to call diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index bd098a5..14e9e56 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -14,7 +14,7 @@ #include "cmSystemTools.h" #include "cmMakefile.h" #include "cmState.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmCommandArgumentLexer.h" @@ -141,8 +141,9 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) { std::ostringstream msg; cmListFileContext lfc; - lfc.FilePath = this->Makefile->GetLocalGenerator() - ->Convert(this->FileName, cmLocalGenerator::HOME); + cmOutputConverter converter(this->Makefile->GetStateSnapshot()); + lfc.FilePath = converter.Convert(this->FileName, + cmOutputConverter::HOME); lfc.Line = this->FileLine; msg << "uninitialized variable \'" << var << "\'"; diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index d375ae6..387afc6 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -80,8 +80,6 @@ private: std::string::size_type InputBufferPos; std::string InputBuffer; std::vector<char> OutputBuffer; - int CurrentLine; - int Verbose; void Print(const char* place, const char* str); void SafePrintMissing(const char* str, int line, int cnt); @@ -94,12 +92,14 @@ private: std::vector<char*> Variables; const cmMakefile* Makefile; std::string Result; + std::string ErrorString; const char* FileName; + long FileLine; + int CurrentLine; + int Verbose; bool WarnUninitialized; bool CheckSystemVars; - long FileLine; bool EscapeQuotes; - std::string ErrorString; bool NoEscapeMode; bool ReplaceAtSyntax; bool RemoveEmpty; diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx new file mode 100644 index 0000000..4840e89 --- /dev/null +++ b/Source/cmCommonTargetGenerator.cxx @@ -0,0 +1,414 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmCommonTargetGenerator.h" + +#include "cmComputeLinkInformation.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalCommonGenerator.h" +#include "cmLocalCommonGenerator.h" +#include "cmMakefile.h" +#include "cmSourceFile.h" +#include "cmSystemTools.h" +#include "cmTarget.h" + +cmCommonTargetGenerator::cmCommonTargetGenerator( + cmOutputConverter::RelativeRoot wd, + cmGeneratorTarget* gt + ) + : WorkingDirectory(wd) + , GeneratorTarget(gt) + , Target(gt->Target) + , Makefile(gt->Makefile) + , LocalGenerator(static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator)) + , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>( + gt->LocalGenerator->GetGlobalGenerator())) + , ConfigName(LocalGenerator->GetConfigName()) + , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName)) + , FortranModuleDirectoryComputed(false) +{ +} + +cmCommonTargetGenerator::~cmCommonTargetGenerator() +{ +} + +std::string const& cmCommonTargetGenerator::GetConfigName() const +{ + return this->ConfigName; +} + +std::string cmCommonTargetGenerator::Convert( + std::string const& source, + cmLocalGenerator::RelativeRoot relative, + cmLocalGenerator::OutputFormat output) +{ + return this->LocalGenerator->Convert(source, relative, output); +} + +//---------------------------------------------------------------------------- +const char* cmCommonTargetGenerator::GetFeature(const std::string& feature) +{ + return this->GeneratorTarget->GetFeature(feature, this->ConfigName); +} + +//---------------------------------------------------------------------------- +bool cmCommonTargetGenerator::GetFeatureAsBool(const std::string& feature) +{ + return this->GeneratorTarget->GetFeatureAsBool(feature, this->ConfigName); +} + +//---------------------------------------------------------------------------- +void cmCommonTargetGenerator::AddFeatureFlags( + std::string& flags, const std::string& lang + ) +{ + // Add language-specific flags. + this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName); + + if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) + { + this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); + } +} + +//---------------------------------------------------------------------------- +void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags) +{ + if(this->ModuleDefinitionFile.empty()) + { + return; + } + + // TODO: Create a per-language flag variable. + const char* defFileFlag = + this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); + if(!defFileFlag) + { + return; + } + + // Append the flag and value. Use ConvertToLinkReference to help + // vs6's "cl -link" pass it to the linker. + std::string flag = defFileFlag; + flag += (this->LocalGenerator->ConvertToLinkReference( + this->ModuleDefinitionFile)); + this->LocalGenerator->AppendFlags(flags, flag); +} + +//---------------------------------------------------------------------------- +std::string cmCommonTargetGenerator::ComputeFortranModuleDirectory() const +{ + std::string mod_dir; + const char* target_mod_dir = + this->Target->GetProperty("Fortran_MODULE_DIRECTORY"); + const char* moddir_flag = + this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG"); + if(target_mod_dir && moddir_flag) + { + // Compute the full path to the module directory. + if(cmSystemTools::FileIsFullPath(target_mod_dir)) + { + // Already a full path. + mod_dir = target_mod_dir; + } + else + { + // Interpret relative to the current output directory. + mod_dir = this->Makefile->GetCurrentBinaryDirectory(); + mod_dir += "/"; + mod_dir += target_mod_dir; + } + + // Make sure the module output directory exists. + cmSystemTools::MakeDirectory(mod_dir); + } + return mod_dir; +} + +//---------------------------------------------------------------------------- +std::string cmCommonTargetGenerator::GetFortranModuleDirectory() +{ + // Compute the module directory. + if(!this->FortranModuleDirectoryComputed) + { + this->FortranModuleDirectoryComputed = true; + this->FortranModuleDirectory = this->ComputeFortranModuleDirectory(); + } + + // Return the computed directory. + return this->FortranModuleDirectory; +} + +//---------------------------------------------------------------------------- +void cmCommonTargetGenerator::AddFortranFlags(std::string& flags) +{ + // Enable module output if necessary. + if(const char* modout_flag = + this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG")) + { + this->LocalGenerator->AppendFlags(flags, modout_flag); + } + + // Add a module output directory flag if necessary. + std::string mod_dir = this->GetFortranModuleDirectory(); + if (!mod_dir.empty()) + { + mod_dir = this->Convert(mod_dir, + this->WorkingDirectory, + cmLocalGenerator::SHELL); + } + else + { + mod_dir = + this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT"); + } + if (!mod_dir.empty()) + { + const char* moddir_flag = + this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"); + std::string modflag = moddir_flag; + modflag += mod_dir; + this->LocalGenerator->AppendFlags(flags, modflag); + } + + // If there is a separate module path flag then duplicate the + // include path with it. This compiler does not search the include + // path for modules. + if(const char* modpath_flag = + this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) + { + std::vector<std::string> includes; + const std::string& config = + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + "C", config); + for(std::vector<std::string>::const_iterator idi = includes.begin(); + idi != includes.end(); ++idi) + { + std::string flg = modpath_flag; + flg += this->Convert(*idi, + cmLocalGenerator::NONE, + cmLocalGenerator::SHELL); + this->LocalGenerator->AppendFlags(flags, flg); + } + } +} + +//---------------------------------------------------------------------------- +void +cmCommonTargetGenerator +::AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source) +{ + const char* srcfmt = source.GetProperty("Fortran_FORMAT"); + cmLocalGenerator::FortranFormat format = + this->LocalGenerator->GetFortranFormat(srcfmt); + if(format == cmLocalGenerator::FortranFormatNone) + { + const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT"); + format = this->LocalGenerator->GetFortranFormat(tgtfmt); + } + const char* var = 0; + switch (format) + { + case cmLocalGenerator::FortranFormatFixed: + var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break; + case cmLocalGenerator::FortranFormatFree: + var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break; + default: break; + } + if(var) + { + this->LocalGenerator->AppendFlags( + flags, this->Makefile->GetDefinition(var)); + } +} + +//---------------------------------------------------------------------------- +std::string cmCommonTargetGenerator::GetFrameworkFlags(std::string const& l) +{ + if(!this->Makefile->IsOn("APPLE")) + { + return std::string(); + } + + std::string fwSearchFlagVar = "CMAKE_" + l + "_FRAMEWORK_SEARCH_FLAG"; + const char* fwSearchFlag = + this->Makefile->GetDefinition(fwSearchFlagVar); + if(!(fwSearchFlag && *fwSearchFlag)) + { + return std::string(); + } + + std::set<std::string> emitted; +#ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */ + emitted.insert("/System/Library/Frameworks"); +#endif + std::vector<std::string> includes; + + const std::string& config = + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + "C", config); + // check all include directories for frameworks as this + // will already have added a -F for the framework + for(std::vector<std::string>::iterator i = includes.begin(); + i != includes.end(); ++i) + { + if(this->Target->NameResolvesToFramework(*i)) + { + std::string frameworkDir = *i; + frameworkDir += "/../"; + frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); + emitted.insert(frameworkDir); + } + } + + std::string flags; + const char* cfg = this->LocalGenerator->GetConfigName().c_str(); + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(cfg)) + { + std::vector<std::string> const& frameworks = cli->GetFrameworkPaths(); + for(std::vector<std::string>::const_iterator i = frameworks.begin(); + i != frameworks.end(); ++i) + { + if(emitted.insert(*i).second) + { + flags += fwSearchFlag; + flags += this->LocalGenerator + ->ConvertToOutputFormat(*i, cmLocalGenerator::SHELL); + flags += " "; + } + } + } + return flags; +} + +//---------------------------------------------------------------------------- +std::string cmCommonTargetGenerator::GetFlags(const std::string &l) +{ + ByLanguageMap::iterator i = this->FlagsByLanguage.find(l); + if (i == this->FlagsByLanguage.end()) + { + std::string flags; + const char *lang = l.c_str(); + + // Add language feature flags. + this->AddFeatureFlags(flags, lang); + + this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, + lang, this->ConfigName); + + // Fortran-specific flags computed for this target. + if(l == "Fortran") + { + this->AddFortranFlags(flags); + } + + this->LocalGenerator->AddCMP0018Flags(flags, this->Target, + lang, this->ConfigName); + + this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, + lang); + + // Append old-style preprocessor definition flags. + this->LocalGenerator-> + AppendFlags(flags, this->Makefile->GetDefineFlags()); + + // Add framework directory flags. + this->LocalGenerator-> + AppendFlags(flags,this->GetFrameworkFlags(l)); + + // Add target-specific flags. + this->LocalGenerator->AddCompileOptions(flags, this->Target, + lang, this->ConfigName); + + ByLanguageMap::value_type entry(l, flags); + i = this->FlagsByLanguage.insert(entry).first; + } + return i->second; +} + +std::string cmCommonTargetGenerator::GetDefines(const std::string &l) +{ + ByLanguageMap::iterator i = this->DefinesByLanguage.find(l); + if (i == this->DefinesByLanguage.end()) + { + std::set<std::string> defines; + const char *lang = l.c_str(); + // Add the export symbol definition for shared library objects. + if(const char* exportMacro = this->Target->GetExportMacro()) + { + this->LocalGenerator->AppendDefines(defines, exportMacro); + } + + // Add preprocessor definitions for this target and configuration. + this->LocalGenerator->AddCompileDefinitions(defines, this->Target, + this->LocalGenerator->GetConfigName(), l); + + std::string definesString; + this->LocalGenerator->JoinDefines(defines, definesString, lang); + + ByLanguageMap::value_type entry(l, definesString); + i = this->DefinesByLanguage.insert(entry).first; + } + return i->second; +} + +std::string cmCommonTargetGenerator::GetIncludes(std::string const& l) +{ + ByLanguageMap::iterator i = this->IncludesByLanguage.find(l); + if (i == this->IncludesByLanguage.end()) + { + std::string includes; + this->AddIncludeFlags(includes, l); + ByLanguageMap::value_type entry(l, includes); + i = this->IncludesByLanguage.insert(entry).first; + } + return i->second; +} + +std::vector<std::string> +cmCommonTargetGenerator::GetLinkedTargetDirectories() const +{ + std::vector<std::string> dirs; + std::set<cmTarget const*> emitted; + if (cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(this->ConfigName)) + { + cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); + for(cmComputeLinkInformation::ItemVector::const_iterator + i = items.begin(); i != items.end(); ++i) + { + cmTarget const* linkee = i->Target; + if(linkee && !linkee->IsImported() + // We can ignore the INTERFACE_LIBRARY items because + // Target->GetLinkInformation already processed their + // link interface and they don't have any output themselves. + && linkee->GetType() != cmTarget::INTERFACE_LIBRARY + && emitted.insert(linkee).second) + { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(linkee); + cmLocalGenerator* lg = gt->GetLocalGenerator(); + cmMakefile* mf = linkee->GetMakefile(); + std::string di = mf->GetCurrentBinaryDirectory(); + di += "/"; + di += lg->GetTargetDirectory(*linkee); + dirs.push_back(di); + } + } + } + return dirs; +} diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h new file mode 100644 index 0000000..0a49e12 --- /dev/null +++ b/Source/cmCommonTargetGenerator.h @@ -0,0 +1,95 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmCommonTargetGenerator_h +#define cmCommonTargetGenerator_h + +#include "cmStandardIncludes.h" + +#include "cmLocalGenerator.h" + +class cmGeneratorTarget; +class cmGlobalCommonGenerator; +class cmLocalCommonGenerator; +class cmMakefile; +class cmSourceFile; +class cmTarget; + +/** \class cmCommonTargetGenerator + * \brief Common infrastructure for Makefile and Ninja per-target generators + */ +class cmCommonTargetGenerator +{ +public: + cmCommonTargetGenerator(cmOutputConverter::RelativeRoot wd, + cmGeneratorTarget* gt); + virtual ~cmCommonTargetGenerator(); + + std::string const& GetConfigName() const; + +protected: + + // Add language feature flags. + void AddFeatureFlags(std::string& flags, const std::string& lang); + + // Feature query methods. + const char* GetFeature(const std::string& feature); + bool GetFeatureAsBool(const std::string& feature); + + // Helper to add flag for windows .def file. + void AddModuleDefinitionFlag(std::string& flags); + + cmOutputConverter::RelativeRoot WorkingDirectory; + cmGeneratorTarget* GeneratorTarget; + cmTarget* Target; + cmMakefile* Makefile; + cmLocalCommonGenerator* LocalGenerator; + cmGlobalCommonGenerator* GlobalGenerator; + std::string ConfigName; + + // The windows module definition source file (.def), if any. + std::string ModuleDefinitionFile; + + // Target-wide Fortran module output directory. + bool FortranModuleDirectoryComputed; + std::string FortranModuleDirectory; + std::string GetFortranModuleDirectory(); + virtual std::string ComputeFortranModuleDirectory() const; + + // Compute target-specific Fortran language flags. + void AddFortranFlags(std::string& flags); + + std::string Convert(std::string const& source, + cmLocalGenerator::RelativeRoot relative, + cmLocalGenerator::OutputFormat output = + cmLocalGenerator::UNCHANGED); + + void AppendFortranFormatFlags(std::string& flags, + cmSourceFile const& source); + + // Return the a string with -F flags on apple + std::string GetFrameworkFlags(std::string const& l); + + virtual void AddIncludeFlags(std::string& flags, + std::string const& lang) = 0; + + typedef std::map<std::string, std::string> ByLanguageMap; + std::string GetFlags(const std::string &l); + ByLanguageMap FlagsByLanguage; + std::string GetDefines(const std::string &l); + ByLanguageMap DefinesByLanguage; + std::string GetIncludes(std::string const& l); + ByLanguageMap IncludesByLanguage; + + std::vector<std::string> GetLinkedTargetDirectories() const; +}; + +#endif diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h index a2ce946..4dbac4a 100644 --- a/Source/cmComputeComponentGraph.h +++ b/Source/cmComputeComponentGraph.h @@ -67,17 +67,17 @@ private: int Root; int VisitIndex; }; - int TarjanWalkId; std::vector<int> TarjanVisited; std::vector<int> TarjanComponents; std::vector<TarjanEntry> TarjanEntries; + std::vector<NodeList> Components; std::stack<int> TarjanStack; + int TarjanWalkId; int TarjanIndex; void Tarjan(); void TarjanVisit(int i); // Connected components. - std::vector<NodeList> Components; }; #endif diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index abd9877..1b5c9f4 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -12,14 +12,13 @@ #include "cmComputeLinkDepends.h" #include "cmComputeComponentGraph.h" +#include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmTarget.h" #include "cmake.h" #include "cmAlgorithms.h" -#include <cmsys/stl/algorithm> - #include <assert.h> /* @@ -173,18 +172,20 @@ items that we know the linker will re-use automatically (shared libs). //---------------------------------------------------------------------------- cmComputeLinkDepends -::cmComputeLinkDepends(cmTarget const* target, const std::string& config) +::cmComputeLinkDepends(const cmGeneratorTarget* target, + const std::string& config) { // Store context information. this->Target = target; - this->Makefile = this->Target->GetMakefile(); - this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); + this->Makefile = this->Target->Target->GetMakefile(); + this->GlobalGenerator = + this->Target->GetLocalGenerator()->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); // The configuration being linked. this->HasConfig = !config.empty(); this->Config = (this->HasConfig)? config : std::string(); - this->LinkType = this->Target->ComputeLinkType(this->Config); + this->LinkType = this->Target->Target->ComputeLinkType(this->Config); // Enable debug mode if requested. this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE"); @@ -361,9 +362,11 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) // Follow the item's dependencies. if(entry.Target) { + cmGeneratorTarget* gtgt = + this->GlobalGenerator->GetGeneratorTarget(entry.Target); // Follow the target dependencies. - if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config, this->Target)) + if(cmLinkInterface const* iface = + gtgt->GetLinkInterface(this->Config, this->Target->Target)) { const bool isIface = entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY; @@ -397,7 +400,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) //---------------------------------------------------------------------------- void cmComputeLinkDepends -::FollowSharedDeps(int depender_index, cmTarget::LinkInterface const* iface, +::FollowSharedDeps(int depender_index, cmLinkInterface const* iface, bool follow_interface) { // Follow dependencies if we have not followed them already. @@ -460,8 +463,10 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) // Target items may have their own dependencies. if(entry.Target) { - if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config, this->Target)) + cmGeneratorTarget* gtgt = + this->GlobalGenerator->GetGeneratorTarget(entry.Target); + if(cmLinkInterface const* iface = + gtgt->GetLinkInterface(this->Config, this->Target->Target)) { // Follow public and private dependencies transitively. this->FollowSharedDeps(index, iface, true); @@ -551,7 +556,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, void cmComputeLinkDepends::AddDirectLinkEntries() { // Add direct link dependencies in this configuration. - cmTarget::LinkImplementation const* impl = + cmLinkImplementation const* impl = this->Target->GetLinkImplementation(this->Config); this->AddLinkEntries(-1, impl->Libraries); for(std::vector<cmLinkItem>::const_iterator @@ -634,7 +639,7 @@ cmTarget const* cmComputeLinkDepends::FindTargetToLink(int depender_index, const std::string& name) { // Look for a target in the scope of the depender. - cmTarget const* from = this->Target; + cmTarget const* from = this->Target->Target; if(depender_index >= 0) { if(cmTarget const* depender = this->EntryList[depender_index].Target) @@ -931,8 +936,10 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) { if(cmTarget const* target = this->EntryList[*ni].Target) { - if(cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config, this->Target)) + cmGeneratorTarget* gtgt = + this->GlobalGenerator->GetGeneratorTarget(target); + if(cmLinkInterface const* iface = + gtgt->GetLinkInterface(this->Config, this->Target->Target)) { if(iface->Multiplicity > count) { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 09b9d70..2cbb430 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -22,6 +22,7 @@ class cmComputeComponentGraph; class cmGlobalGenerator; class cmMakefile; +class cmGeneratorTarget; class cmTarget; class cmake; @@ -31,7 +32,8 @@ class cmake; class cmComputeLinkDepends { public: - cmComputeLinkDepends(cmTarget const* target, const std::string& config); + cmComputeLinkDepends(cmGeneratorTarget const* target, + const std::string& config); ~cmComputeLinkDepends(); // Basic information about each link item. @@ -57,18 +59,11 @@ public: private: // Context information. - cmTarget const* Target; + cmGeneratorTarget const* Target; cmMakefile* Makefile; cmGlobalGenerator const* GlobalGenerator; cmake* CMakeInstance; - bool DebugMode; - - // Configuration information. - bool HasConfig; std::string Config; - cmTarget::LinkLibraryType LinkType; - - // Output information. EntryVector FinalLinkEntries; typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType; @@ -107,7 +102,7 @@ private: std::queue<SharedDepEntry> SharedDepQueue; std::set<int> SharedDepFollowed; void FollowSharedDeps(int depender_index, - cmTarget::LinkInterface const* iface, + cmLinkInterface const* iface, bool follow_interface = false); void QueueSharedDependencies(int depender_index, std::vector<cmLinkItem> const& deps); @@ -131,7 +126,7 @@ private: void OrderLinkEntires(); std::vector<char> ComponentVisited; std::vector<int> ComponentOrder; - int ComponentOrderId; + struct PendingComponent { // The real component id. Needed because the map is indexed by @@ -158,11 +153,14 @@ private: // Record of the original link line. std::vector<int> OriginalEntries; + std::set<cmTarget const*> OldWrongConfigItems; + void CheckWrongConfigItem(cmLinkItem const& item); - // Compatibility help. + int ComponentOrderId; + cmTarget::LinkLibraryType LinkType; + bool HasConfig; + bool DebugMode; bool OldLinkDirMode; - void CheckWrongConfigItem(cmLinkItem const& item); - std::set<cmTarget const*> OldWrongConfigItems; }; #endif diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index e6cbe60..4b70e5e 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -14,11 +14,13 @@ #include "cmComputeLinkDepends.h" #include "cmOrderDirectories.h" +#include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" #include "cmState.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmMakefile.h" #include "cmTarget.h" +#include "cmGeneratorTarget.h" #include "cmake.h" #include "cmAlgorithms.h" @@ -241,13 +243,14 @@ because this need be done only for shared libraries without soname-s. //---------------------------------------------------------------------------- cmComputeLinkInformation -::cmComputeLinkInformation(cmTarget const* target, const std::string& config) +::cmComputeLinkInformation(const cmGeneratorTarget* target, + const std::string& config) { // Store context information. this->Target = target; - this->Makefile = this->Target->GetMakefile(); - this->LocalGenerator = this->Makefile->GetLocalGenerator(); - this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); + this->Makefile = this->Target->Target->GetMakefile(); + this->GlobalGenerator = + this->Target->GetLocalGenerator()->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); // Check whether to recognize OpenBSD-style library versioned names. @@ -281,14 +284,14 @@ cmComputeLinkInformation // Check whether we should skip dependencies on shared library files. this->LinkDependsNoShared = - this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED"); + this->Target->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED"); // On platforms without import libraries there may be a special flag // to use when creating a plugin (module) that obtains symbols from // the program that will load it. this->LoaderFlag = 0; if(!this->UseImportLibrary && - this->Target->GetType() == cmTarget::MODULE_LIBRARY) + this->Target->Target->GetType() == cmTarget::MODULE_LIBRARY) { std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_"; loader_flag_var += this->LinkLanguage; @@ -306,10 +309,10 @@ cmComputeLinkInformation // Get options needed to specify RPATHs. this->RuntimeUseChrpath = false; - if(this->Target->GetType() != cmTarget::STATIC_LIBRARY) + if(this->Target->Target->GetType() != cmTarget::STATIC_LIBRARY) { const char* tType = - ((this->Target->GetType() == cmTarget::EXECUTABLE)? + ((this->Target->Target->GetType() == cmTarget::EXECUTABLE)? "EXECUTABLE" : "SHARED_LIBRARY"); std::string rtVar = "CMAKE_"; rtVar += tType; @@ -322,6 +325,7 @@ cmComputeLinkInformation this->RuntimeAlways = (this->Makefile-> GetSafeDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH")); + this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config); // Get options needed to help find dependent libraries. @@ -374,9 +378,9 @@ cmComputeLinkInformation // Add the search path entries requested by the user to path ordering. this->OrderLinkerSearchPath - ->AddUserDirectories(this->Target->GetLinkDirectories()); + ->AddUserDirectories(this->Target->Target->GetLinkDirectories()); this->OrderRuntimeSearchPath - ->AddUserDirectories(this->Target->GetLinkDirectories()); + ->AddUserDirectories(this->Target->Target->GetLinkDirectories()); // Set up the implicit link directories. this->LoadImplicitLinkInfo(); @@ -404,12 +408,13 @@ cmComputeLinkInformation // order to support such projects we need to add the directories // containing libraries linked with a full path to the -L path. this->OldLinkDirMode = - this->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW; + this->Target->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW; if(this->OldLinkDirMode) { // Construct a mask to not bother with this behavior for link // directories already specified by the user. - std::vector<std::string> const& dirs = this->Target->GetLinkDirectories(); + std::vector<std::string> const& dirs = + this->Target->Target->GetLinkDirectories(); this->OldLinkDirMask.insert(dirs.begin(), dirs.end()); } @@ -515,10 +520,12 @@ bool cmComputeLinkInformation::Compute() // Restore the target link type so the correct system runtime // libraries are found. - const char* lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC"); - if(cmSystemTools::IsOn(lss)) + const char* lss = + this->Target->Target->GetProperty("LINK_SEARCH_END_STATIC"); + if(lss) { - this->SetCurrentLinkType(LinkStatic); + this->SetCurrentLinkType( + cmSystemTools::IsOn(lss) ? LinkStatic : LinkShared); } else { @@ -536,10 +543,11 @@ bool cmComputeLinkInformation::Compute() i != wrongItems.end(); ++i) { cmTarget const* tgt = *i; + cmGeneratorTarget *gtgt = this->GlobalGenerator->GetGeneratorTarget(tgt); bool implib = (this->UseImportLibrary && (tgt->GetType() == cmTarget::SHARED_LIBRARY)); - std::string lib = tgt->GetFullPath(this->Config , implib, true); + std::string lib = gtgt->GetFullPath(this->Config , implib, true); this->OldLinkDirItems.push_back(lib); } } @@ -565,7 +573,7 @@ bool cmComputeLinkInformation::Compute() "name." ; this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } return true; @@ -575,7 +583,8 @@ bool cmComputeLinkInformation::Compute() void cmComputeLinkInformation::AddImplicitLinkInfo() { // The link closure lists all languages whose implicit info is needed. - cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config); + cmGeneratorTarget::LinkClosure const* lc = + this->Target->GetLinkClosure(this->Config); for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) { @@ -638,6 +647,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item, if(tgt && tgt->IsLinkable()) { + cmGeneratorTarget *gtgt = this->GlobalGenerator->GetGeneratorTarget(tgt); // This is a CMake target. Ask the target for its real name. if(impexe && this->LoaderFlag) { @@ -646,7 +656,8 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // platform. Add it now. std::string linkItem; linkItem = this->LoaderFlag; - std::string exe = tgt->GetFullPath(config, this->UseImportLibrary, + + std::string exe = gtgt->GetFullPath(config, this->UseImportLibrary, true); linkItem += exe; this->Items.push_back(Item(linkItem, true, tgt)); @@ -667,7 +678,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item, (impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY)); // Pass the full path to the target file. - std::string lib = tgt->GetFullPath(config, implib, true); + std::string lib = gtgt->GetFullPath(config, implib, true); if(!this->LinkDependsNoShared || tgt->GetType() != cmTarget::SHARED_LIBRARY) { @@ -750,13 +761,17 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, return; } + cmGeneratorTarget *gtgt = 0; + // Get a full path to the dependent shared library. // Add it to the runtime path computation so that the target being // linked will be able to find it. std::string lib; if(tgt) { - lib = tgt->GetFullPath(this->Config, this->UseImportLibrary); + gtgt = this->GlobalGenerator->GetGeneratorTarget(tgt); + + lib = gtgt->GetFullPath(this->Config, this->UseImportLibrary); this->AddLibraryRuntimeInfo(lib, tgt); } else @@ -781,9 +796,9 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, } if(order) { - if(tgt) + if(gtgt) { - std::string soName = tgt->GetSOName(this->Config); + std::string soName = gtgt->GetSOName(this->Config); const char* soname = soName.empty()? 0 : soName.c_str(); order->AddRuntimeLibrary(lib, soname); } @@ -845,9 +860,11 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() } // Lookup the starting link type from the target (linked statically?). - const char* lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC"); + const char* lss = + this->Target->Target->GetProperty("LINK_SEARCH_START_STATIC"); this->StartLinkType = cmSystemTools::IsOn(lss)? LinkStatic : LinkShared; - this->CurrentLinkType = this->StartLinkType; + this->CurrentLinkType = LinkUnknown; + this->SetCurrentLinkType(this->StartLinkType); } //---------------------------------------------------------------------------- @@ -1131,7 +1148,7 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item) // Full path libraries should specify a valid library file name. // See documentation of CMP0008. std::string generator = this->GlobalGenerator->GetName(); - if(this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW && + if(this->Target->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW && (generator.find("Visual Studio") != generator.npos || generator.find("Xcode") != generator.npos)) { @@ -1212,7 +1229,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) } // Check the policy for whether we should use the approach below. - switch (this->Target->GetPolicyStatusCMP0060()) + switch (this->Target->Target->GetPolicyStatusCMP0060()) { case cmPolicies::WARN: if (this->CMP0060Warn) @@ -1395,7 +1412,8 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) // Add the item using the -framework option. this->Items.push_back(Item("-framework", false)); - fw = this->LocalGenerator->EscapeForShell(fw); + cmOutputConverter converter(this->Makefile->GetStateSnapshot()); + fw = converter.EscapeForShell(fw); this->Items.push_back(Item(fw, false)); } @@ -1521,7 +1539,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, this->OrderLinkerSearchPath->AddLinkLibrary(item); // Produce any needed message. - switch(this->Target->GetPolicyStatusCMP0008()) + switch(this->Target->Target->GetPolicyStatusCMP0008()) { case cmPolicies::WARN: { @@ -1538,7 +1556,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } } case cmPolicies::OLD: @@ -1556,7 +1574,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } break; } @@ -1573,7 +1591,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() } // Enforce policy constraints. - switch(this->Target->GetPolicyStatusCMP0003()) + switch(this->Target->Target->GetPolicyStatusCMP0003()) { case cmPolicies::WARN: if(!this->CMakeInstance->GetState() @@ -1584,7 +1602,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() std::ostringstream w; this->PrintLinkPolicyDiagnosis(w); this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } case cmPolicies::OLD: // OLD behavior is to add the paths containing libraries with @@ -1600,7 +1618,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n"; this->PrintLinkPolicyDiagnosis(e); this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); return false; } } @@ -1794,7 +1812,8 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath, // Try to get the soname of the library. Only files with this name // could possibly conflict. - std::string soName = target->GetSOName(this->Config); + cmGeneratorTarget *gtgt = this->GlobalGenerator->GetGeneratorTarget(target); + std::string soName = gtgt->GetSOName(this->Config); const char* soname = soName.empty()? 0 : soName.c_str(); // Include this library in the runtime path ordering. @@ -1901,9 +1920,9 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // build tree. bool linking_for_install = (for_install || - this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")); + this->Target->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")); bool use_install_rpath = - (outputRuntime && this->Target->HaveInstallTreeRPATH() && + (outputRuntime && this->Target->Target->HaveInstallTreeRPATH() && linking_for_install); bool use_build_rpath = (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) && @@ -1911,13 +1930,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, bool use_link_rpath = outputRuntime && linking_for_install && !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") && - this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH"); + this->Target->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH"); // Construct the RPATH. std::set<std::string> emitted; if(use_install_rpath) { - const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH"); + const char* install_rpath = + this->Target->Target->GetProperty("INSTALL_RPATH"); cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); } if(use_build_rpath || use_link_rpath) @@ -1989,7 +2009,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // Add runtime paths required by the languages to always be // present. This is done even when skipping rpath support. { - cmTarget::LinkClosure const* lc = + cmGeneratorTarget::LinkClosure const* lc = this->Target->GetLinkClosure(this->Config); for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 8847141..8b83574 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -18,9 +18,9 @@ class cmake; class cmGlobalGenerator; -class cmLocalGenerator; class cmMakefile; class cmTarget; +class cmGeneratorTarget; class cmOrderDirectories; /** \class cmComputeLinkInformation @@ -29,7 +29,8 @@ class cmOrderDirectories; class cmComputeLinkInformation { public: - cmComputeLinkInformation(cmTarget const* target, const std::string& config); + cmComputeLinkInformation(cmGeneratorTarget const* target, + const std::string& config); ~cmComputeLinkInformation(); bool Compute(); @@ -73,16 +74,14 @@ private: std::set<cmTarget const*> SharedLibrariesLinked; // Context information. - cmTarget const* Target; + cmGeneratorTarget const* Target; cmMakefile* Makefile; - cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; cmake* CMakeInstance; // Configuration information. std::string Config; std::string LinkLanguage; - bool LinkDependsNoShared; // Modes for dealing with dependent shared libraries. enum SharedDepMode @@ -93,8 +92,6 @@ private: SharedDepModeLink // List file on link line }; - // System info. - bool UseImportLibrary; const char* LoaderFlag; std::string LibLinkFlag; std::string LibLinkFileFlag; @@ -102,22 +99,18 @@ private: std::string RuntimeFlag; std::string RuntimeSep; std::string RuntimeAlways; - bool RuntimeUseChrpath; - bool NoSONameUsesPath; - bool LinkWithRuntimePath; std::string RPathLinkFlag; SharedDepMode SharedDependencyMode; + enum LinkType { LinkUnknown, LinkStatic, LinkShared }; + void SetCurrentLinkType(LinkType lt); + // Link type adjustment. void ComputeLinkTypeInfo(); - enum LinkType { LinkUnknown, LinkStatic, LinkShared }; LinkType StartLinkType; LinkType CurrentLinkType; std::string StaticLinkTypeFlag; std::string SharedLinkTypeFlag; - bool LinkTypeEnabled; - void SetCurrentLinkType(LinkType lt); - bool ArchivesMayBeShared; // Link item parsing. void ComputeItemParserInfo(); @@ -129,7 +122,6 @@ private: cmsys::RegularExpression ExtractSharedLibraryName; cmsys::RegularExpression ExtractAnyLibraryName; std::string SharedRegexString; - bool OpenBSD; void AddLinkPrefix(const char* p); void AddLinkExtension(const char* e, LinkType type); std::string CreateExtensionRegex(std::vector<std::string> const& exts, @@ -173,20 +165,27 @@ private: std::set<std::string> OldLinkDirMask; std::vector<std::string> OldLinkDirItems; std::vector<std::string> OldUserFlagItems; - bool OldLinkDirMode; - - // CMP0060 warnings. - bool CMP0060Warn; std::set<std::string> CMP0060WarnItems; - + // Dependent library path computation. + cmOrderDirectories* OrderDependentRPath; // Runtime path computation. cmOrderDirectories* OrderRuntimeSearchPath; + + bool OldLinkDirMode; + bool OpenBSD; + bool LinkDependsNoShared; + bool UseImportLibrary; + bool RuntimeUseChrpath; + bool NoSONameUsesPath; + bool LinkWithRuntimePath; + bool LinkTypeEnabled; + bool ArchivesMayBeShared; + bool CMP0060Warn; + void AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget const* target); void AddLibraryRuntimeInfo(std::string const& fullPath); - // Dependent library path computation. - cmOrderDirectories* OrderDependentRPath; }; #endif diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 87b47b4..9e37c35 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -147,12 +147,12 @@ bool cmComputeTargetDepends::Compute() //---------------------------------------------------------------------------- void -cmComputeTargetDepends::GetTargetDirectDepends(cmTarget const* t, +cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t, cmTargetDependSet& deps) { // Lookup the index for this target. All targets should be known by // this point. - std::map<cmTarget const*, int>::const_iterator tii + std::map<cmGeneratorTarget const*, int>::const_iterator tii = this->TargetIndex.find(t); assert(tii != this->TargetIndex.end()); int i = tii->second; @@ -161,7 +161,7 @@ cmComputeTargetDepends::GetTargetDirectDepends(cmTarget const* t, EdgeList const& nl = this->FinalGraph[i]; for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) { - cmTarget const* dep = this->Targets[*ni]; + cmGeneratorTarget const* dep = this->Targets[*ni]; cmTargetDependSet::iterator di = deps.insert(dep).first; di->SetType(ni->IsStrong()); } @@ -180,9 +180,11 @@ void cmComputeTargetDepends::CollectTargets() ti != targets.end(); ++ti) { cmTarget const* target = &ti->second; + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(target); int index = static_cast<int>(this->Targets.size()); - this->TargetIndex[target] = index; - this->Targets.push_back(target); + this->TargetIndex[gt] = index; + this->Targets.push_back(gt); } } } @@ -204,7 +206,7 @@ void cmComputeTargetDepends::CollectDepends() void cmComputeTargetDepends::CollectTargetDepends(int depender_index) { // Get the depender. - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; if (depender->GetType() == cmTarget::INTERFACE_LIBRARY) { return; @@ -216,10 +218,9 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // deal with config-specific dependencies. { std::set<std::string> emitted; - cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(depender); std::vector<std::string> configs; - depender->GetMakefile()->GetConfigurations(configs); + depender->Makefile->GetConfigurations(configs); if (configs.empty()) { configs.push_back(""); @@ -228,7 +229,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) it != configs.end(); ++it) { std::vector<cmSourceFile const*> objectFiles; - gt->GetExternalObjects(objectFiles, *it); + depender->GetExternalObjects(objectFiles, *it); for(std::vector<cmSourceFile const*>::const_iterator oi = objectFiles.begin(); oi != objectFiles.end(); ++oi) { @@ -244,15 +245,14 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) ->IssueMessage(cmake::FATAL_ERROR, "Only executables and non-OBJECT libraries may " "reference target objects.", - depender->GetBacktrace()); + depender->Target->GetBacktrace()); return; } - const_cast<cmTarget*>(depender)->AddUtility(objLib); + const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib); } } - cmTarget::LinkImplementation const* impl = - depender->GetLinkImplementation(*it); + cmLinkImplementation const* impl = depender->GetLinkImplementation(*it); // A target should not depend on itself. emitted.insert(depender->GetName()); @@ -272,7 +272,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Loop over all utility dependencies. { - std::set<cmLinkItem> const& tutils = depender->GetUtilityItems(); + std::set<cmLinkItem> const& tutils = depender->Target->GetUtilityItems(); std::set<std::string> emitted; // A target should not depend on itself. emitted.insert(depender->GetName()); @@ -290,13 +290,14 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, - cmTarget const* dependee, - const std::string& config, - std::set<std::string> &emitted) + const cmGeneratorTarget* dependee, + const std::string& config, + std::set<std::string> &emitted) { - cmTarget const* depender = this->Targets[depender_index]; - if(cmTarget::LinkInterface const* iface = - dependee->GetLinkInterface(config, depender)) + cmGeneratorTarget const* depender = this->Targets[depender_index]; + if(cmLinkInterface const* iface = + dependee->GetLinkInterface(config, + depender->Target)) { for(std::vector<cmLinkItem>::const_iterator lib = iface->Libraries.begin(); @@ -317,7 +318,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, std::set<std::string> &emitted) { - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; cmTarget const* dependee = dependee_name.Target; // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable @@ -331,16 +332,17 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, if(dependee) { - this->AddInterfaceDepends(depender_index, dependee, "", emitted); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(dependee); + this->AddInterfaceDepends(depender_index, gt, "", emitted); std::vector<std::string> configs; - depender->GetMakefile()->GetConfigurations(configs); + depender->Makefile->GetConfigurations(configs); for (std::vector<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) { // A target should not depend on itself. emitted.insert(depender->GetName()); - this->AddInterfaceDepends(depender_index, dependee, - *it, emitted); + this->AddInterfaceDepends(depender_index, gt, *it, emitted); } } } @@ -351,7 +353,7 @@ void cmComputeTargetDepends::AddTargetDepend( bool linking) { // Get the depender. - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; // Check the target's makefile first. cmTarget const* dependee = dependee_name.Target; @@ -362,7 +364,7 @@ void cmComputeTargetDepends::AddTargetDepend( cmake::MessageType messageType = cmake::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; - switch(depender->GetPolicyStatusCMP0046()) + switch(depender->Target->GetPolicyStatusCMP0046()) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n"; @@ -383,7 +385,7 @@ void cmComputeTargetDepends::AddTargetDepend( << "\" of target \"" << depender->GetName() << "\" does not exist."; cmListFileBacktrace const* backtrace = - depender->GetUtilityBacktrace(dependee_name); + depender->Target->GetUtilityBacktrace(dependee_name); if(backtrace) { cm->IssueMessage(messageType, e.str(), *backtrace); @@ -408,27 +410,31 @@ void cmComputeTargetDepends::AddTargetDepend( if(dependee) { - this->AddTargetDepend(depender_index, dependee, linking); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(dependee); + this->AddTargetDepend(depender_index, gt, linking); } } //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddTargetDepend(int depender_index, - cmTarget const* dependee, + const cmGeneratorTarget* dependee, bool linking) { - if(dependee->IsImported() || + if(dependee->Target->IsImported() || dependee->GetType() == cmTarget::INTERFACE_LIBRARY) { // Skip IMPORTED and INTERFACE targets but follow their utility // dependencies. - std::set<cmLinkItem> const& utils = dependee->GetUtilityItems(); + std::set<cmLinkItem> const& utils = dependee->Target->GetUtilityItems(); for(std::set<cmLinkItem>::const_iterator i = utils.begin(); i != utils.end(); ++i) { if(cmTarget const* transitive_dependee = i->Target) { - this->AddTargetDepend(depender_index, transitive_dependee, false); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(transitive_dependee); + this->AddTargetDepend(depender_index, gt, false); } } } @@ -436,7 +442,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, { // Lookup the index for this target. All targets should be known by // this point. - std::map<cmTarget const*, int>::const_iterator tii = + std::map<cmGeneratorTarget const*, int>::const_iterator tii = this->TargetIndex.find(dependee); assert(tii != this->TargetIndex.end()); int dependee_index = tii->second; @@ -457,13 +463,13 @@ cmComputeTargetDepends::DisplayGraph(Graph const& graph, for(int depender_index = 0; depender_index < n; ++depender_index) { EdgeList const& nl = graph[depender_index]; - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; fprintf(stderr, "target %d is [%s]\n", depender_index, depender->GetName().c_str()); for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) { int dependee_index = *ni; - cmTarget const* dependee = this->Targets[dependee_index]; + cmGeneratorTarget const* dependee = this->Targets[dependee_index]; fprintf(stderr, " depends on target %d [%s] (%s)\n", dependee_index, dependee->GetName().c_str(), ni->IsStrong()? "strong" : "weak"); } @@ -550,11 +556,11 @@ cmComputeTargetDepends { // Get the depender. int i = *ci; - cmTarget const* depender = this->Targets[i]; + cmGeneratorTarget const* depender = this->Targets[i]; // Describe the depender. e << " \"" << depender->GetName() << "\" of type " - << cmTarget::GetTargetTypeName(depender->GetType()) << "\n"; + << cmTarget::GetTargetTypeName(depender->Target->GetType()) << "\n"; // List its dependencies that are inside the component. EdgeList const& nl = this->InitialGraph[i]; @@ -563,7 +569,7 @@ cmComputeTargetDepends int j = *ni; if(cmap[j] == c) { - cmTarget const* dependee = this->Targets[j]; + cmGeneratorTarget const* dependee = this->Targets[j]; e << " depends on \"" << dependee->GetName() << "\"" << " (" << (ni->IsStrong()? "strong" : "weak") << ")\n"; } diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 902f342..6100d97 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -21,7 +21,7 @@ class cmComputeComponentGraph; class cmGlobalGenerator; class cmLinkItem; -class cmTarget; +class cmGeneratorTarget; class cmTargetDependSet; /** \class cmComputeTargetDepends @@ -39,9 +39,10 @@ public: bool Compute(); - std::vector<cmTarget const*> const& + std::vector<cmGeneratorTarget const*> const& GetTargets() const { return this->Targets; } - void GetTargetDirectDepends(cmTarget const* t, cmTargetDependSet& deps); + void GetTargetDirectDepends(cmGeneratorTarget const* t, + cmTargetDependSet& deps); private: void CollectTargets(); void CollectDepends(); @@ -49,13 +50,14 @@ private: void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name, bool linking); - void AddTargetDepend(int depender_index, cmTarget const* dependee, + void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, std::set<std::string> &emitted); - void AddInterfaceDepends(int depender_index, cmTarget const* dependee, + void AddInterfaceDepends(int depender_index, + cmGeneratorTarget const* dependee, const std::string& config, std::set<std::string> &emitted); cmGlobalGenerator* GlobalGenerator; @@ -63,8 +65,8 @@ private: bool NoCycles; // Collect all targets. - std::vector<cmTarget const*> Targets; - std::map<cmTarget const*, int> TargetIndex; + std::vector<cmGeneratorTarget const*> Targets; + std::map<cmGeneratorTarget const*, int> TargetIndex; // Represent the target dependency graph. The entry at each // top-level index corresponds to a depender whose dependencies are diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 61847d4..7874803 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -16,7 +16,8 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile): Makefile(makefile), Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)), Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)), - Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057)) + Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057)), + Policy64Status(makefile.GetPolicyStatus(cmPolicies::CMP0064)) { } @@ -299,11 +300,11 @@ void cmConditionEvaluator::IncrementArguments(cmArgumentList &newArgs, cmArgumentList::iterator &argP1, cmArgumentList::iterator &argP2) const { - if (argP1 != newArgs.end()) + if (argP1 != newArgs.end()) { argP1++; argP2 = argP1; - if (argP1 != newArgs.end()) + if (argP1 != newArgs.end()) { argP2++; } @@ -442,35 +443,35 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList &newArgs, argP1 = arg; this->IncrementArguments(newArgs,argP1,argP2); // does a file exist - if (this->IsKeyword("EXISTS", *arg) && argP1 != newArgs.end()) + if (this->IsKeyword("EXISTS", *arg) && argP1 != newArgs.end()) { this->HandlePredicate( cmSystemTools::FileExists(argP1->c_str()), reducible, arg, newArgs, argP1, argP2); } // does a directory with this name exist - if (this->IsKeyword("IS_DIRECTORY", *arg) && argP1 != newArgs.end()) + if (this->IsKeyword("IS_DIRECTORY", *arg) && argP1 != newArgs.end()) { this->HandlePredicate( cmSystemTools::FileIsDirectory(argP1->c_str()), reducible, arg, newArgs, argP1, argP2); } // does a symlink with this name exist - if (this->IsKeyword("IS_SYMLINK", *arg) && argP1 != newArgs.end()) + if (this->IsKeyword("IS_SYMLINK", *arg) && argP1 != newArgs.end()) { this->HandlePredicate( cmSystemTools::FileIsSymlink(argP1->c_str()), reducible, arg, newArgs, argP1, argP2); } // is the given path an absolute path ? - if (this->IsKeyword("IS_ABSOLUTE", *arg) && argP1 != newArgs.end()) + if (this->IsKeyword("IS_ABSOLUTE", *arg) && argP1 != newArgs.end()) { this->HandlePredicate( cmSystemTools::FileIsFullPath(argP1->c_str()), reducible, arg, newArgs, argP1, argP2); } // does a command exist - if (this->IsKeyword("COMMAND", *arg) && argP1 != newArgs.end()) + if (this->IsKeyword("COMMAND", *arg) && argP1 != newArgs.end()) { cmCommand* command = this->Makefile.GetState()->GetCommand(argP1->c_str()); @@ -493,8 +494,31 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList &newArgs, this->Makefile.FindTargetToUse(argP1->GetValue())?true:false, reducible, arg, newArgs, argP1, argP2); } + // does a test exist + if(this->Policy64Status != cmPolicies::OLD && + this->Policy64Status != cmPolicies::WARN) + { + if (this->IsKeyword("TEST", *arg) && argP1 != newArgs.end()) + { + const cmTest* haveTest = this->Makefile.GetTest(argP1->c_str()); + this->HandlePredicate( + haveTest?true:false, + reducible, arg, newArgs, argP1, argP2); + } + } + else if(this->Policy64Status == cmPolicies::WARN && + this->IsKeyword("TEST", *arg)) + { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n"; + e << "TEST will be interpreted as an operator " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; + + this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + } // is a variable defined - if (this->IsKeyword("DEFINED", *arg) && argP1 != newArgs.end()) + if (this->IsKeyword("DEFINED", *arg) && argP1 != newArgs.end()) { size_t argP1len = argP1->GetValue().size(); bool bdef = false; diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index c923d76..c4e2d11 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -94,6 +94,7 @@ private: cmPolicies::PolicyStatus Policy12Status; cmPolicies::PolicyStatus Policy54Status; cmPolicies::PolicyStatus Policy57Status; + cmPolicies::PolicyStatus Policy64Status; }; #endif diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index dd276a8..9411555 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -11,7 +11,7 @@ ============================================================================*/ #include "cmCoreTryCompile.h" #include "cmake.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmGlobalGenerator.h" #include "cmAlgorithms.h" #include "cmExportTryCompileFileGenerator.h" @@ -322,7 +322,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) std::string langFlags = "CMAKE_" + *li + "_FLAGS"; const char* flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li->c_str(), - cmLocalGenerator::EscapeForCMake(flags?flags:"").c_str()); + cmOutputConverter::EscapeForCMake(flags?flags:"").c_str()); fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str()); } @@ -355,7 +355,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) const char* exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", - cmLocalGenerator::EscapeForCMake( + cmOutputConverter::EscapeForCMake( exeLinkFlags ? exeLinkFlags : "").c_str()); } break; } @@ -379,7 +379,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) if (!targets.empty()) { std::string fname = "/" + std::string(targetName) + "Targets.cmake"; - cmExportTryCompileFileGenerator tcfg; + cmExportTryCompileFileGenerator tcfg(gg); tcfg.SetExportFile((this->BinaryDirectory + fname).c_str()); tcfg.SetExports(targets); tcfg.SetConfig(this->Makefile->GetSafeDefinition( @@ -470,6 +470,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) { fprintf(fout, "set(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n"); } + if (const char *lssDef = this->Makefile->GetDefinition( + "CMAKE_LINK_SEARCH_START_STATIC")) + { + fprintf(fout, "set(CMAKE_LINK_SEARCH_START_STATIC \"%s\")\n", lssDef); + } + if (const char *lssDef = this->Makefile->GetDefinition( + "CMAKE_LINK_SEARCH_END_STATIC")) + { + fprintf(fout, "set(CMAKE_LINK_SEARCH_END_STATIC \"%s\")\n", lssDef); + } /* Put the executable at a known location (for COPY_FILE). */ fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n", diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index 74e17b6..6616218 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -46,7 +46,7 @@ std::string cmCryptoHash::HashString(const std::string& input) //---------------------------------------------------------------------------- std::string cmCryptoHash::HashFile(const std::string& file) { - cmsys::ifstream fin(file.c_str(), std::ios::in | cmsys_ios_binary); + cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary); if(!fin) { return ""; diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 96d3547..ad0c7d3 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -13,7 +13,7 @@ #include "cmSystemTools.h" #define check_curl_result(result, errstr) \ - if (result != CURLE_OK) \ + if (result != CURLE_OK && result != CURLE_NOT_BUILT_IN) \ { \ e += e.empty()? "" : "\n"; \ e += errstr; \ diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index 015825d..7c37e3b 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -17,7 +17,7 @@ //---------------------------------------------------------------------------- cmCustomCommand::cmCustomCommand() - : Backtrace(NULL) + : Backtrace() { this->HaveComment = false; this->EscapeOldStyle = true; @@ -26,46 +26,6 @@ cmCustomCommand::cmCustomCommand() } //---------------------------------------------------------------------------- -cmCustomCommand::cmCustomCommand(const cmCustomCommand& r): - Outputs(r.Outputs), - Byproducts(r.Byproducts), - Depends(r.Depends), - CommandLines(r.CommandLines), - HaveComment(r.HaveComment), - Comment(r.Comment), - WorkingDirectory(r.WorkingDirectory), - EscapeAllowMakeVars(r.EscapeAllowMakeVars), - EscapeOldStyle(r.EscapeOldStyle), - Backtrace(r.Backtrace), - UsesTerminal(r.UsesTerminal) -{ -} - -//---------------------------------------------------------------------------- -cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r) -{ - if(this == &r) - { - return *this; - } - - this->Outputs = r.Outputs; - this->Byproducts= r.Byproducts; - this->Depends = r.Depends; - this->CommandLines = r.CommandLines; - this->HaveComment = r.HaveComment; - this->Comment = r.Comment; - this->WorkingDirectory = r.WorkingDirectory; - this->EscapeAllowMakeVars = r.EscapeAllowMakeVars; - this->EscapeOldStyle = r.EscapeOldStyle; - this->ImplicitDepends = r.ImplicitDepends; - this->Backtrace = r.Backtrace; - this->UsesTerminal = r.UsesTerminal; - - return *this; -} - -//---------------------------------------------------------------------------- cmCustomCommand::cmCustomCommand(cmMakefile const* mf, const std::vector<std::string>& outputs, const std::vector<std::string>& byproducts, @@ -77,15 +37,13 @@ cmCustomCommand::cmCustomCommand(cmMakefile const* mf, Byproducts(byproducts), Depends(depends), CommandLines(commandLines), - HaveComment(comment?true:false), + Backtrace(), Comment(comment?comment:""), WorkingDirectory(workingDirectory?workingDirectory:""), + HaveComment(comment?true:false), EscapeAllowMakeVars(false), - EscapeOldStyle(true), - Backtrace(NULL) + EscapeOldStyle(true) { - this->EscapeOldStyle = true; - this->EscapeAllowMakeVars = false; if(mf) { this->Backtrace = mf->GetBacktrace(); @@ -93,11 +51,6 @@ cmCustomCommand::cmCustomCommand(cmMakefile const* mf, } //---------------------------------------------------------------------------- -cmCustomCommand::~cmCustomCommand() -{ -} - -//---------------------------------------------------------------------------- const std::vector<std::string>& cmCustomCommand::GetOutputs() const { return this->Outputs; diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 0bfaef2..f9b38c3 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -26,8 +26,6 @@ class cmCustomCommand public: /** Default and copy constructors for STL containers. */ cmCustomCommand(); - cmCustomCommand(const cmCustomCommand& r); - cmCustomCommand& operator=(cmCustomCommand const& r); /** Main constructor specifies all information for the command. */ cmCustomCommand(cmMakefile const* mf, @@ -38,8 +36,6 @@ public: const char* comment, const char* workingDirectory); - ~cmCustomCommand(); - /** Get the output file produced by the command. */ const std::vector<std::string>& GetOutputs() const; @@ -93,13 +89,13 @@ private: std::vector<std::string> Byproducts; std::vector<std::string> Depends; cmCustomCommandLines CommandLines; - bool HaveComment; + cmListFileBacktrace Backtrace; + ImplicitDependsList ImplicitDepends; std::string Comment; std::string WorkingDirectory; + bool HaveComment; bool EscapeAllowMakeVars; bool EscapeOldStyle; - cmListFileBacktrace Backtrace; - ImplicitDependsList ImplicitDepends; bool UsesTerminal; }; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index d23f815..7f3b651 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -12,16 +12,17 @@ #include "cmCustomCommandGenerator.h" #include "cmMakefile.h" -#include "cmCustomCommand.h" #include "cmLocalGenerator.h" +#include "cmCustomCommand.h" +#include "cmOutputConverter.h" #include "cmGeneratorExpression.h" //---------------------------------------------------------------------------- cmCustomCommandGenerator::cmCustomCommandGenerator( - cmCustomCommand const& cc, const std::string& config, cmMakefile* mf): - CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()), + cmCustomCommand const& cc, const std::string& config, cmLocalGenerator* lg): + CC(cc), Config(config), LG(lg), OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()), - GE(new cmGeneratorExpression(&cc.GetBacktrace())), DependsDone(false) + GE(new cmGeneratorExpression(cc.GetBacktrace())), DependsDone(false) { } @@ -41,13 +42,16 @@ unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const { std::string const& argv0 = this->CC.GetCommandLines()[c][0]; - cmTarget* target = this->Makefile->FindTargetToUse(argv0); + cmGeneratorTarget* target = + this->LG->GetMakefile()->FindGeneratorTargetToUse(argv0); if(target && target->GetType() == cmTarget::EXECUTABLE && - (target->IsImported() || !this->Makefile->IsOn("CMAKE_CROSSCOMPILING"))) + (target->Target->IsImported() + || !this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) { return target->GetLocation(this->Config); } - return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config); + return this->GE->Parse(argv0)->Evaluate(this->LG->GetMakefile(), + this->Config); } //---------------------------------------------------------------------------- @@ -87,8 +91,9 @@ cmCustomCommandGenerator cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; for(unsigned int j=1;j < commandLine.size(); ++j) { - std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile, - this->Config); + std::string arg = + this->GE->Parse(commandLine[j])->Evaluate(this->LG->GetMakefile(), + this->Config); cmd += " "; if(this->OldStyle) { @@ -96,7 +101,8 @@ cmCustomCommandGenerator } else { - cmd += this->LG->EscapeForShell(arg, this->MakeVars); + cmOutputConverter converter(this->LG->GetMakefile()->GetStateSnapshot()); + cmd += converter.EscapeForShell(arg, this->MakeVars); } } } @@ -140,7 +146,7 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const = this->GE->Parse(*i); std::vector<std::string> result; cmSystemTools::ExpandListArgument( - cge->Evaluate(this->Makefile, this->Config), result); + cge->Evaluate(this->LG->GetMakefile(), this->Config), result); for (std::vector<std::string>::iterator it = result.begin(); it != result.end(); ++it) { diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index b4ae014..a637fed 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -15,7 +15,6 @@ #include "cmStandardIncludes.h" class cmCustomCommand; -class cmMakefile; class cmLocalGenerator; class cmGeneratorExpression; @@ -23,7 +22,6 @@ class cmCustomCommandGenerator { cmCustomCommand const& CC; std::string Config; - cmMakefile* Makefile; cmLocalGenerator* LG; bool OldStyle; bool MakeVars; @@ -33,7 +31,7 @@ class cmCustomCommandGenerator public: cmCustomCommandGenerator(cmCustomCommand const& cc, const std::string& config, - cmMakefile* mf); + cmLocalGenerator* lg); ~cmCustomCommandGenerator(); cmCustomCommand const& GetCC() const { return this->CC; } unsigned int GetNumberOfCommands() const; diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 2dab169..b06fb5c 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -56,9 +56,9 @@ void cmDefinitions::Raise(const std::string& key, } bool cmDefinitions::HasKey(const std::string& key, - StackConstIter begin, StackConstIter end) + StackIter begin, StackIter end) { - for (StackConstIter it = begin; it != end; ++it) + for (StackIter it = begin; it != end; ++it) { MapType::const_iterator i = it->Map.find(key); if (i != it->Map.end()) @@ -94,12 +94,12 @@ std::vector<std::string> cmDefinitions::UnusedKeys() const } //---------------------------------------------------------------------------- -cmDefinitions cmDefinitions::MakeClosure(StackConstIter begin, - StackConstIter end) +cmDefinitions cmDefinitions::MakeClosure(StackIter begin, + StackIter end) { cmDefinitions closure; std::set<std::string> undefined; - for (StackConstIter it = begin; it != end; ++it) + for (StackIter it = begin; it != end; ++it) { // Consider local definitions. for(MapType::const_iterator mi = it->Map.begin(); @@ -125,12 +125,12 @@ cmDefinitions cmDefinitions::MakeClosure(StackConstIter begin, //---------------------------------------------------------------------------- std::vector<std::string> -cmDefinitions::ClosureKeys(StackConstIter begin, StackConstIter end) +cmDefinitions::ClosureKeys(StackIter begin, StackIter end) { std::set<std::string> bound; std::vector<std::string> defined; - for (StackConstIter it = begin; it != end; ++it) + for (StackIter it = begin; it != end; ++it) { defined.reserve(defined.size() + it->Map.size()); for(MapType::const_iterator mi = it->Map.begin(); diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 5fdcaab..411867c 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -13,6 +13,9 @@ #define cmDefinitions_h #include "cmStandardIncludes.h" + +#include "cmLinkedTree.h" + #if defined(CMAKE_BUILD_WITH_CMAKE) #ifdef CMake_HAVE_CXX11_UNORDERED_MAP #include <unordered_map> @@ -32,26 +35,26 @@ */ class cmDefinitions { - typedef std::list<cmDefinitions>::reverse_iterator StackIter; - typedef std::list<cmDefinitions>::const_reverse_iterator StackConstIter; + typedef cmLinkedTree<cmDefinitions>::iterator StackIter; public: static const char* Get(const std::string& key, StackIter begin, StackIter end); - static void Raise(const std::string& key, StackIter begin, StackIter end); + static void Raise(const std::string& key, + StackIter begin, StackIter end); static bool HasKey(const std::string& key, - StackConstIter begin, StackConstIter end); + StackIter begin, StackIter end); /** Set (or unset if null) a value associated with a key. */ void Set(const std::string& key, const char* value); std::vector<std::string> UnusedKeys() const; - static std::vector<std::string> ClosureKeys(StackConstIter begin, - StackConstIter end); + static std::vector<std::string> ClosureKeys(StackIter begin, + StackIter end); - static cmDefinitions MakeClosure(StackConstIter begin, StackConstIter end); + static cmDefinitions MakeClosure(StackIter begin, StackIter end); private: // String with existence boolean. diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 1b2586c..856dcd4 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -16,84 +16,15 @@ #include "cmMakefile.h" #include "cmGeneratedFileStream.h" -#include "cmDependsFortranParser.h" /* Interface to parser object. */ +#include "cmFortranParser.h" /* Interface to parser object. */ #include <cmsys/FStream.hxx> #include <assert.h> -#include <stack> // TODO: Test compiler for the case of the mod file. Some always // use lower case and some always use upper case. I do not know if any // use the case from the source code. //---------------------------------------------------------------------------- -// Information about a single source file. -class cmDependsFortranSourceInfo -{ -public: - // The name of the source file. - std::string Source; - - // Set of provided and required modules. - std::set<std::string> Provides; - std::set<std::string> Requires; - - // Set of files included in the translation unit. - std::set<std::string> Includes; -}; - -//---------------------------------------------------------------------------- -// Parser methods not included in generated interface. - -// Get the current buffer processed by the lexer. -YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner); - -// The parser entry point. -int cmDependsFortran_yyparse(yyscan_t); - -//---------------------------------------------------------------------------- -// Define parser object internal structure. -struct cmDependsFortranFile -{ - cmDependsFortranFile(FILE* file, YY_BUFFER_STATE buffer, - const std::string& dir): - File(file), Buffer(buffer), Directory(dir) {} - FILE* File; - YY_BUFFER_STATE Buffer; - std::string Directory; -}; - -struct cmDependsFortranParser_s -{ - cmDependsFortranParser_s(cmDependsFortran* self, - std::set<std::string>& ppDefines, - cmDependsFortranSourceInfo& info); - ~cmDependsFortranParser_s(); - - // Pointer back to the main class. - cmDependsFortran* Self; - - // Lexical scanner instance. - yyscan_t Scanner; - - // Stack of open files in the translation unit. - std::stack<cmDependsFortranFile> FileStack; - - // Buffer for string literals. - std::string TokenString; - - // Flag for whether lexer is reading from inside an interface. - bool InInterface; - - int OldStartcond; - std::set<std::string> PPDefinitions; - size_t InPPFalseBranch; - std::stack<bool> SkipToEnd; - - // Information about the parsed source. - cmDependsFortranSourceInfo& Info; -}; - -//---------------------------------------------------------------------------- class cmDependsFortranInternals { public: @@ -105,18 +36,18 @@ public: TargetRequiresMap TargetRequires; // Information about each object file. - typedef std::map<std::string, cmDependsFortranSourceInfo> ObjectInfoMap; + typedef std::map<std::string, cmFortranSourceInfo> ObjectInfoMap; ObjectInfoMap ObjectInfo; - cmDependsFortranSourceInfo& CreateObjectInfo(const char* obj, + cmFortranSourceInfo& CreateObjectInfo(const char* obj, const char* src) { - std::map<std::string, cmDependsFortranSourceInfo>::iterator i = + std::map<std::string, cmFortranSourceInfo>::iterator i = this->ObjectInfo.find(obj); if(i == this->ObjectInfo.end()) { - std::map<std::string, cmDependsFortranSourceInfo>::value_type - entry(obj, cmDependsFortranSourceInfo()); + std::map<std::string, cmFortranSourceInfo>::value_type + entry(obj, cmFortranSourceInfo()); i = this->ObjectInfo.insert(entry).first; i->second.Source = src; } @@ -126,7 +57,7 @@ public: //---------------------------------------------------------------------------- cmDependsFortran::cmDependsFortran(): - PPDefinitions(0), Internal(0) + Internal(0) { } @@ -159,7 +90,7 @@ cmDependsFortran { def = it->substr(0, assignment); } - this->PPDefinitions.push_back(def); + this->PPDefinitions.insert(def); } } @@ -192,22 +123,18 @@ bool cmDependsFortran::WriteDependencies( { const std::string& src = *it; // Get the information object for this source. - cmDependsFortranSourceInfo& info = + cmFortranSourceInfo& info = this->Internal->CreateObjectInfo(obj.c_str(), src.c_str()); - // Make a copy of the macros defined via ADD_DEFINITIONS - std::set<std::string> ppDefines(this->PPDefinitions.begin(), - this->PPDefinitions.end()); - - // Create the parser object. The constructor takes ppMacro and info per - // reference, so we may look into the resulting objects later. - cmDependsFortranParser parser(this, ppDefines, info); + // Create the parser object. The constructor takes info by reference, + // so we may look into the resulting objects later. + cmFortranParser parser(this->IncludePath, this->PPDefinitions, info); // Push on the starting file. - cmDependsFortranParser_FilePush(&parser, src.c_str()); + cmFortranParser_FilePush(&parser, src.c_str()); // Parse the translation unit. - if(cmDependsFortran_yyparse(parser.Scanner) != 0) + if(cmFortran_yyparse(parser.Scanner) != 0) { // Failed to parse the file. Report failure to write dependencies. okay = false; @@ -227,14 +154,10 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, const char* stamp_dir = this->TargetDirectory.c_str(); // Get the directory in which module files will be created. - const char* mod_dir; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - if(const char* target_mod_dir = - mf->GetDefinition("CMAKE_Fortran_TARGET_MODULE_DIR")) - { - mod_dir = target_mod_dir; - } - else + std::string mod_dir = + mf->GetSafeDefinition("CMAKE_Fortran_TARGET_MODULE_DIR"); + if (mod_dir.empty()) { mod_dir = this->LocalGenerator->GetMakefile()->GetCurrentBinaryDirectory(); @@ -318,7 +241,7 @@ void cmDependsFortran::LocateModules() for(ObjectInfoMap::const_iterator infoI = objInfo.begin(); infoI != objInfo.end(); ++infoI) { - cmDependsFortranSourceInfo const& info = infoI->second; + cmFortranSourceInfo const& info = infoI->second; // Include this module in the set provided by this target. this->Internal->TargetProvides.insert(info.Provides.begin(), info.Provides.end()); @@ -428,8 +351,9 @@ void cmDependsFortran::ConsiderModule(const char* name, bool cmDependsFortran ::WriteDependenciesReal(const char *obj, - cmDependsFortranSourceInfo const& info, - const char* mod_dir, const char* stamp_dir, + cmFortranSourceInfo const& info, + std::string const& mod_dir, + const char* stamp_dir, std::ostream& makeDepends, std::ostream& internalDepends) { @@ -701,7 +625,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args) // is later used for longer sequences it should be re-written using an // efficient string search algorithm such as Boyer-Moore. static -bool cmDependsFortranStreamContainsSequence(std::istream& ifs, +bool cmFortranStreamContainsSequence(std::istream& ifs, const char* seq, int len) { assert(len > 0); @@ -734,7 +658,7 @@ bool cmDependsFortranStreamContainsSequence(std::istream& ifs, //---------------------------------------------------------------------------- // Helper function to compare the remaining content in two streams. -static bool cmDependsFortranStreamsDiffer(std::istream& ifs1, +static bool cmFortranStreamsDiffer(std::istream& ifs1, std::istream& ifs2) { // Compare the remaining content. @@ -837,7 +761,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, const char seq[1] = {'\n'}; const int seqlen = 1; - if(!cmDependsFortranStreamContainsSequence(finModFile, seq, seqlen)) + if(!cmFortranStreamContainsSequence(finModFile, seq, seqlen)) { // The module is of unexpected format. Assume it is different. std::cerr << compilerId << " fortran module " << modFile @@ -845,7 +769,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, return true; } - if(!cmDependsFortranStreamContainsSequence(finStampFile, seq, seqlen)) + if(!cmFortranStreamContainsSequence(finStampFile, seq, seqlen)) { // The stamp must differ if the sequence is not contained. return true; @@ -857,7 +781,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, const char seq[2] = {'\n', '\0'}; const int seqlen = 2; - if(!cmDependsFortranStreamContainsSequence(finModFile, seq, seqlen)) + if(!cmFortranStreamContainsSequence(finModFile, seq, seqlen)) { // The module is of unexpected format. Assume it is different. std::cerr << compilerId << " fortran module " << modFile @@ -865,7 +789,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, return true; } - if(!cmDependsFortranStreamContainsSequence(finStampFile, seq, seqlen)) + if(!cmFortranStreamContainsSequence(finStampFile, seq, seqlen)) { // The stamp must differ if the sequence is not contained. return true; @@ -875,7 +799,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, // Compare the remaining content. If no compiler id matched above, // including the case none was given, this will compare the whole // content. - if(!cmDependsFortranStreamsDiffer(finModFile, finStampFile)) + if(!cmFortranStreamsDiffer(finModFile, finStampFile)) { return false; } @@ -883,396 +807,3 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, // The modules are different. return true; } - -//---------------------------------------------------------------------------- -bool cmDependsFortran::FindIncludeFile(const char* dir, - const char* includeName, - std::string& fileName) -{ - // If the file is a full path, include it directly. - if(cmSystemTools::FileIsFullPath(includeName)) - { - fileName = includeName; - return cmSystemTools::FileExists(fileName.c_str(), true); - } - else - { - // Check for the file in the directory containing the including - // file. - std::string fullName = dir; - fullName += "/"; - fullName += includeName; - if(cmSystemTools::FileExists(fullName.c_str(), true)) - { - fileName = fullName; - return true; - } - - // Search the include path for the file. - for(std::vector<std::string>::const_iterator i = - this->IncludePath.begin(); i != this->IncludePath.end(); ++i) - { - fullName = *i; - fullName += "/"; - fullName += includeName; - if(cmSystemTools::FileExists(fullName.c_str(), true)) - { - fileName = fullName; - return true; - } - } - } - return false; -} - -//---------------------------------------------------------------------------- -cmDependsFortranParser_s -::cmDependsFortranParser_s(cmDependsFortran* self, - std::set<std::string>& ppDefines, - cmDependsFortranSourceInfo& info): - Self(self), PPDefinitions(ppDefines), Info(info) -{ - this->InInterface = 0; - this->InPPFalseBranch = 0; - - // Initialize the lexical scanner. - cmDependsFortran_yylex_init(&this->Scanner); - cmDependsFortran_yyset_extra(this, this->Scanner); - - // Create a dummy buffer that is never read but is the fallback - // buffer when the last file is popped off the stack. - YY_BUFFER_STATE buffer = - cmDependsFortran_yy_create_buffer(0, 4, this->Scanner); - cmDependsFortran_yy_switch_to_buffer(buffer, this->Scanner); -} - -//---------------------------------------------------------------------------- -cmDependsFortranParser_s::~cmDependsFortranParser_s() -{ - cmDependsFortran_yylex_destroy(this->Scanner); -} - -//---------------------------------------------------------------------------- -bool cmDependsFortranParser_FilePush(cmDependsFortranParser* parser, - const char* fname) -{ - // Open the new file and push it onto the stack. Save the old - // buffer with it on the stack. - if(FILE* file = cmsys::SystemTools::Fopen(fname, "rb")) - { - YY_BUFFER_STATE current = - cmDependsFortranLexer_GetCurrentBuffer(parser->Scanner); - std::string dir = cmSystemTools::GetParentDirectory(fname); - cmDependsFortranFile f(file, current, dir); - YY_BUFFER_STATE buffer = - cmDependsFortran_yy_create_buffer(0, 16384, parser->Scanner); - cmDependsFortran_yy_switch_to_buffer(buffer, parser->Scanner); - parser->FileStack.push(f); - return 1; - } - else - { - return 0; - } -} - -//---------------------------------------------------------------------------- -bool cmDependsFortranParser_FilePop(cmDependsFortranParser* parser) -{ - // Pop one file off the stack and close it. Switch the lexer back - // to the next one on the stack. - if(parser->FileStack.empty()) - { - return 0; - } - else - { - cmDependsFortranFile f = parser->FileStack.top(); parser->FileStack.pop(); - fclose(f.File); - YY_BUFFER_STATE current = - cmDependsFortranLexer_GetCurrentBuffer(parser->Scanner); - cmDependsFortran_yy_delete_buffer(current, parser->Scanner); - cmDependsFortran_yy_switch_to_buffer(f.Buffer, parser->Scanner); - return 1; - } -} - -//---------------------------------------------------------------------------- -int cmDependsFortranParser_Input(cmDependsFortranParser* parser, - char* buffer, size_t bufferSize) -{ - // Read from the file on top of the stack. If the stack is empty, - // the end of the translation unit has been reached. - if(!parser->FileStack.empty()) - { - FILE* file = parser->FileStack.top().File; - return (int)fread(buffer, 1, bufferSize, file); - } - return 0; -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_StringStart(cmDependsFortranParser* parser) -{ - parser->TokenString = ""; -} - -//---------------------------------------------------------------------------- -const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser) -{ - return parser->TokenString.c_str(); -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser, - char c) -{ - parser->TokenString += c; -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser, - bool in) -{ - if(parser->InPPFalseBranch) - { - return; - } - - parser->InInterface = in; -} - -//---------------------------------------------------------------------------- -bool cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser) -{ - return parser->InInterface; -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_SetOldStartcond(cmDependsFortranParser* parser, - int arg) -{ - parser->OldStartcond = arg; -} - -//---------------------------------------------------------------------------- -int cmDependsFortranParser_GetOldStartcond(cmDependsFortranParser* parser) -{ - return parser->OldStartcond; -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_Error(cmDependsFortranParser*, const char*) -{ - // If there is a parser error just ignore it. The source will not - // compile and the user will edit it. Then dependencies will have - // to be regenerated anyway. -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser, - const char* name) -{ - if(!parser->InPPFalseBranch) - { - parser->Info.Requires.insert(cmSystemTools::LowerCase(name) ); - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser, - const char* name) -{ - if(parser->InPPFalseBranch) - { - return; - } - - // If processing an include statement there must be an open file. - assert(!parser->FileStack.empty()); - - // Get the directory containing the source in which the include - // statement appears. This is always the first search location for - // Fortran include files. - std::string dir = parser->FileStack.top().Directory; - - // Find the included file. If it cannot be found just ignore the - // problem because either the source will not compile or the user - // does not care about depending on this included source. - std::string fullName; - if(parser->Self->FindIncludeFile(dir.c_str(), name, fullName)) - { - // Found the included file. Save it in the set of included files. - parser->Info.Includes.insert(fullName); - - // Parse it immediately to translate the source inline. - cmDependsFortranParser_FilePush(parser, fullName.c_str()); - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser, - const char* name) -{ - if(!parser->InPPFalseBranch && !parser->InInterface) - { - parser->Info.Provides.insert(cmSystemTools::LowerCase(name)); - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleDefine(cmDependsFortranParser* parser, - const char* macro) -{ - if(!parser->InPPFalseBranch) - { - parser->PPDefinitions.insert(macro); - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleUndef(cmDependsFortranParser* parser, - const char* macro) -{ - if(!parser->InPPFalseBranch) - { - std::set<std::string>::iterator match; - match = parser->PPDefinitions.find(macro); - if(match != parser->PPDefinitions.end()) - { - parser->PPDefinitions.erase(match); - } - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleIfdef(cmDependsFortranParser* parser, - const char* macro) -{ - // A new PP branch has been opened - parser->SkipToEnd.push(false); - - if (parser->InPPFalseBranch) - { - parser->InPPFalseBranch++; - } - else if(parser->PPDefinitions.find(macro) == parser->PPDefinitions.end()) - { - parser->InPPFalseBranch=1; - } - else - { - parser->SkipToEnd.top() = true; - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleIfndef(cmDependsFortranParser* parser, - const char* macro) -{ - // A new PP branch has been opened - parser->SkipToEnd.push(false); - - if (parser->InPPFalseBranch) - { - parser->InPPFalseBranch++; - } - else if(parser->PPDefinitions.find(macro) != parser->PPDefinitions.end()) - { - parser->InPPFalseBranch = 1; - } - else - { - // ignore other branches - parser->SkipToEnd.top() = true; - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleIf(cmDependsFortranParser* parser) -{ - /* Note: The current parser is _not_ able to get statements like - * #if 0 - * #if 1 - * #if MYSMBOL - * #if defined(MYSYMBOL) - * #if defined(MYSYMBOL) && ... - * right. The same for #elif. Thus in - * #if SYMBOL_1 - * .. - * #elif SYMBOL_2 - * ... - * ... - * #elif SYMBOL_N - * .. - * #else - * .. - * #endif - * _all_ N+1 branches are considered. If you got something like this - * #if defined(MYSYMBOL) - * #if !defined(MYSYMBOL) - * use - * #ifdef MYSYMBOL - * #ifndef MYSYMBOL - * instead. - */ - - // A new PP branch has been opened - // Never skip! See note above. - parser->SkipToEnd.push(false); -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleElif(cmDependsFortranParser* parser) -{ - /* Note: There are parser limitations. See the note at - * cmDependsFortranParser_RuleIf(..) - */ - - // Always taken unless an #ifdef or #ifndef-branch has been taken - // already. If the second condition isn't meet already - // (parser->InPPFalseBranch == 0) correct it. - if(!parser->SkipToEnd.empty() && - parser->SkipToEnd.top() && !parser->InPPFalseBranch) - { - parser->InPPFalseBranch = 1; - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleElse(cmDependsFortranParser* parser) -{ - // if the parent branch is false do nothing! - if(parser->InPPFalseBranch > 1) - { - return; - } - - // parser->InPPFalseBranch is either 0 or 1. We change it depending on - // parser->SkipToEnd.top() - if(!parser->SkipToEnd.empty() && - parser->SkipToEnd.top()) - { - parser->InPPFalseBranch = 1; - } - else - { - parser->InPPFalseBranch = 0; - } -} - -//---------------------------------------------------------------------------- -void cmDependsFortranParser_RuleEndif(cmDependsFortranParser* parser) -{ - if(!parser->SkipToEnd.empty()) - { - parser->SkipToEnd.pop(); - } - - // #endif doesn't know if there was a "#else" in before, so it - // always decreases InPPFalseBranch - if(parser->InPPFalseBranch) - { - parser->InPPFalseBranch--; - } -} diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index cb40796..a8a4013 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -9,13 +9,13 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ -#ifndef cmDependsFortran_h -#define cmDependsFortran_h +#ifndef cmFortran_h +#define cmFortran_h #include "cmDepends.h" class cmDependsFortranInternals; -class cmDependsFortranSourceInfo; +class cmFortranSourceInfo; /** \class cmDependsFortran * \brief Dependency scanner for Fortran object files. @@ -46,12 +46,6 @@ public: static bool ModulesDiffer(const char* modFile, const char* stampFile, const char* compilerId); - /** Method to find an included file in the include path. Fortran - always searches the directory containing the including source - first. */ - bool FindIncludeFile(const char* dir, const char* includeName, - std::string& fileName); - protected: // Finalize the dependency information for the target. virtual bool Finalize(std::ostream& makeDepends, @@ -71,15 +65,16 @@ protected: // Actually write the depenencies to the streams. bool WriteDependenciesReal(const char *obj, - cmDependsFortranSourceInfo const& info, - const char* mod_dir, const char* stamp_dir, + cmFortranSourceInfo const& info, + std::string const& mod_dir, + const char* stamp_dir, std::ostream& makeDepends, std::ostream& internalDepends); // The source file from which to start scanning. std::string SourceFile; - std::vector<std::string> PPDefinitions; + std::set<std::string> PPDefinitions; // Internal implementation details. cmDependsFortranInternals* Internal; diff --git a/Source/cmDependsFortranParser.h b/Source/cmDependsFortranParser.h deleted file mode 100644 index 399c3c8..0000000 --- a/Source/cmDependsFortranParser.h +++ /dev/null @@ -1,96 +0,0 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef cmDependsFortranParser_h -#define cmDependsFortranParser_h - -#include <stddef.h> /* size_t */ - -/* Forward declare parser object type. */ -typedef struct cmDependsFortranParser_s cmDependsFortranParser; - -/* Functions to enter/exit #include'd files in order. */ -bool cmDependsFortranParser_FilePush(cmDependsFortranParser* parser, - const char* fname); -bool cmDependsFortranParser_FilePop(cmDependsFortranParser* parser); - -/* Callbacks for lexer. */ -int cmDependsFortranParser_Input(cmDependsFortranParser* parser, - char* buffer, size_t bufferSize); - - -void cmDependsFortranParser_StringStart(cmDependsFortranParser* parser); -const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser); -void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser, - char c); - -void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser, - bool is_in); -bool cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser); - - -void cmDependsFortranParser_SetInPPFalseBranch(cmDependsFortranParser* parser, - bool is_in); -bool cmDependsFortranParser_GetInPPFalseBranch(cmDependsFortranParser* parser); - - -void cmDependsFortranParser_SetOldStartcond(cmDependsFortranParser* parser, - int arg); -int cmDependsFortranParser_GetOldStartcond(cmDependsFortranParser* parser); - -/* Callbacks for parser. */ -void cmDependsFortranParser_Error(cmDependsFortranParser* parser, - const char* message); -void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleDefine(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleUndef(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleIfdef(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleIfndef(cmDependsFortranParser* parser, - const char* name); -void cmDependsFortranParser_RuleIf(cmDependsFortranParser* parser); -void cmDependsFortranParser_RuleElif(cmDependsFortranParser* parser); -void cmDependsFortranParser_RuleElse(cmDependsFortranParser* parser); -void cmDependsFortranParser_RuleEndif(cmDependsFortranParser* parser); - -/* Define the parser stack element type. */ -typedef union cmDependsFortran_yystype_u cmDependsFortran_yystype; -union cmDependsFortran_yystype_u -{ - char* string; -}; - -/* Setup the proper yylex interface. */ -#define YY_EXTRA_TYPE cmDependsFortranParser* -#define YY_DECL \ -int cmDependsFortran_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) -#define YYSTYPE cmDependsFortran_yystype -#define YYSTYPE_IS_DECLARED 1 -#if !defined(cmDependsFortranLexer_cxx) -# include "cmDependsFortranLexer.h" -#endif -#if !defined(cmDependsFortranLexer_cxx) -#if !defined(cmDependsFortranParser_cxx) -# undef YY_EXTRA_TYPE -# undef YY_DECL -# undef YYSTYPE -# undef YYSTYPE_IS_DECLARED -#endif -#endif - -#endif diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 8854c36..b6c5fde 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -13,7 +13,6 @@ #define _cmDocumentation_h #include "cmStandardIncludes.h" -#include "cmProperty.h" #include "cmDocumentationFormatter.h" #include "cmDocumentationSection.h" #include "cmake.h" diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index e021d0b..41785c2 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -156,7 +156,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, verbose = false; } -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) // if the command does not start with a quote, then // try to find the program, and if the program can not be // found use system to run the command as it must be a built in @@ -219,7 +219,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, return false; } -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) if(dir) { cmsysProcess_SetWorkingDirectory(cp, dir); @@ -305,7 +305,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, } if(!msg.empty()) { -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) // Old Windows process execution printed this info. msg += "\n\nfor command: "; msg += command; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index bf18deb..fed0dbc 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -18,7 +18,7 @@ //---------------------------------------------------------------------------- cmExportBuildFileGenerator::cmExportBuildFileGenerator() - : Backtrace(NULL) + : Backtrace() { this->Makefile = 0; this->ExportSet = 0; @@ -27,6 +27,7 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator() //---------------------------------------------------------------------------- bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { + std::vector<cmGeneratorTarget*> allTargets; { std::string expectedTargets; std::string sep; @@ -36,10 +37,11 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) tei = targets.begin(); tei != targets.end(); ++tei) { - cmTarget *te = this->Makefile->FindTargetToUse(*tei); - expectedTargets += sep + this->Namespace + te->GetExportName(); + cmGeneratorTarget *te = this->Makefile + ->FindGeneratorTargetToUse(*tei); + expectedTargets += sep + this->Namespace + te->Target->GetExportName(); sep = " "; - if(this->ExportedTargets.insert(te).second) + if(this->ExportedTargets.insert(te->Target).second) { this->Exports.push_back(te); } @@ -63,11 +65,12 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) std::vector<std::string> missingTargets; // Create all the imported targets. - for(std::vector<cmTarget*>::const_iterator + for(std::vector<cmGeneratorTarget*>::const_iterator tei = this->Exports.begin(); tei != this->Exports.end(); ++tei) { - cmTarget* te = *tei; + cmGeneratorTarget* gte = *tei; + cmTarget* te = gte->Target; this->GenerateImportTargetCode(os, te); te->AppendBuildInterfaceIncludes(); @@ -103,7 +106,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) cmGeneratorExpression::BuildInterface, properties, missingTargets); } - this->PopulateCompatibleInterfaceProperties(te, properties); + this->PopulateCompatibleInterfaceProperties(gte, properties); this->GenerateInterfaceProperties(te, os, properties); } @@ -129,12 +132,12 @@ cmExportBuildFileGenerator std::string const& suffix, std::vector<std::string> &missingTargets) { - for(std::vector<cmTarget*>::const_iterator + for(std::vector<cmGeneratorTarget*>::const_iterator tei = this->Exports.begin(); tei != this->Exports.end(); ++tei) { // Collect import properties for this target. - cmTarget* target = *tei; + cmGeneratorTarget* target = *tei; ImportPropertyMap properties; if (target->GetType() != cmTarget::INTERFACE_LIBRARY) @@ -147,10 +150,12 @@ cmExportBuildFileGenerator if (target->GetType() != cmTarget::INTERFACE_LIBRARY) { this->SetImportDetailProperties(config, suffix, - target, properties, missingTargets); + target, + properties, missingTargets); this->SetImportLinkInterface(config, suffix, - cmGeneratorExpression::BuildInterface, - target, properties, missingTargets); + cmGeneratorExpression::BuildInterface, + target, + properties, missingTargets); } // TOOD: PUBLIC_HEADER_LOCATION @@ -160,7 +165,8 @@ cmExportBuildFileGenerator // properties); // Generate code in the export file. - this->GenerateImportPropertyCode(os, config, target, properties); + this->GenerateImportPropertyCode(os, config, target->Target, + properties); } } } @@ -176,17 +182,18 @@ void cmExportBuildFileGenerator ::SetImportLocationProperty(const std::string& config, std::string const& suffix, - cmTarget* target, ImportPropertyMap& properties) + cmGeneratorTarget* target, + ImportPropertyMap& properties) { // Get the makefile in which to lookup target information. - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Makefile; // Add the main target file. { std::string prop = "IMPORTED_LOCATION"; prop += suffix; std::string value; - if(target->IsAppBundleOnApple()) + if(target->Target->IsAppBundleOnApple()) { value = target->GetFullPath(config, false); } @@ -204,13 +211,13 @@ cmExportBuildFileGenerator // Add the import library for windows DLLs. if(dll_platform && (target->GetType() == cmTarget::SHARED_LIBRARY || - target->IsExecutableWithExports()) && + target->Target->IsExecutableWithExports()) && mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { std::string prop = "IMPORTED_IMPLIB"; prop += suffix; std::string value = target->GetFullPath(config, true); - target->GetImplibGNUtoMS(value, value, + target->Target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); properties[prop] = value; } @@ -326,12 +333,12 @@ cmExportBuildFileGenerator } std::string -cmExportBuildFileGenerator::InstallNameDir(cmTarget* target, +cmExportBuildFileGenerator::InstallNameDir(cmGeneratorTarget* target, const std::string& config) { std::string install_name_dir; - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { install_name_dir = diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 8b5694c..ff3d2e1 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -68,17 +68,18 @@ protected: /** Fill in properties indicating built file locations. */ void SetImportLocationProperty(const std::string& config, std::string const& suffix, - cmTarget* target, + cmGeneratorTarget* target, ImportPropertyMap& properties); - std::string InstallNameDir(cmTarget* target, const std::string& config); + std::string InstallNameDir(cmGeneratorTarget* target, + const std::string& config); std::vector<std::string> FindNamespaces(cmMakefile* mf, const std::string& name); std::vector<std::string> Targets; cmExportSet *ExportSet; - std::vector<cmTarget*> Exports; + std::vector<cmGeneratorTarget*> Exports; cmMakefile* Makefile; cmListFileBacktrace Backtrace; }; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 43d26f9..96ea77b 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -177,6 +177,12 @@ bool cmExportCommand this->SetError(e.str()); return false; } + if (target->GetType() == cmTarget::UTILITY) + { + this->SetError("given custom target \"" + *currentTarget + + "\" which may not be exported."); + return false; + } } else { diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index a51fb2a..9a7d73f 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -23,12 +23,28 @@ #include "cmVersion.h" #include "cmComputeLinkInformation.h" #include "cmAlgorithms.h" +#include "cmOutputConverter.h" #include <cmsys/auto_ptr.hxx> #include <cmsys/FStream.hxx> #include <assert.h> //---------------------------------------------------------------------------- +static std::string cmExportFileGeneratorEscape(std::string const& str) +{ + // Escape a property value for writing into a .cmake file. + std::string result = cmOutputConverter::EscapeForCMake(str); + // Un-escape variable references generated by our own export code. + cmSystemTools::ReplaceString(result, + "\\${_IMPORT_PREFIX}", + "${_IMPORT_PREFIX}"); + cmSystemTools::ReplaceString(result, + "\\${CMAKE_IMPORT_LIBRARY_SUFFIX}", + "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); + return result; +} + +//---------------------------------------------------------------------------- cmExportFileGenerator::cmExportFileGenerator() { this->AppendMode = false; @@ -509,7 +525,7 @@ void getPropertyContents(cmTarget const* tgt, const std::string& prop, } //---------------------------------------------------------------------------- -void getCompatibleInterfaceProperties(cmTarget *target, +void getCompatibleInterfaceProperties(cmGeneratorTarget *target, std::set<std::string> &ifaceProperties, const std::string& config) { @@ -517,7 +533,7 @@ void getCompatibleInterfaceProperties(cmTarget *target, if (!info) { - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); std::ostringstream e; e << "Exporting the target \"" << target->GetName() << "\" is not " "allowed since its linker language cannot be determined"; @@ -552,9 +568,10 @@ void getCompatibleInterfaceProperties(cmTarget *target, //---------------------------------------------------------------------------- void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( - cmTarget *target, + cmGeneratorTarget *gtarget, ImportPropertyMap &properties) { + cmTarget *target = gtarget->Target; this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", target, properties); this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", @@ -575,7 +592,7 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( if (target->GetType() != cmTarget::INTERFACE_LIBRARY) { - getCompatibleInterfaceProperties(target, ifaceProperties, ""); + getCompatibleInterfaceProperties(gtarget, ifaceProperties, ""); std::vector<std::string> configNames; target->GetMakefile()->GetConfigurations(configNames); @@ -583,7 +600,7 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( for (std::vector<std::string>::const_iterator ci = configNames.begin(); ci != configNames.end(); ++ci) { - getCompatibleInterfaceProperties(target, ifaceProperties, *ci); + getCompatibleInterfaceProperties(gtarget, ifaceProperties, *ci); } } @@ -608,7 +625,8 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget const* target, for(ImportPropertyMap::const_iterator pi = properties.begin(); pi != properties.end(); ++pi) { - os << " " << pi->first << " \"" << pi->second << "\"\n"; + os << " " << pi->first << " " + << cmExportFileGeneratorEscape(pi->second) << "\n"; } os << ")\n\n"; } @@ -774,12 +792,12 @@ void cmExportFileGenerator ::SetImportLinkInterface(const std::string& config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, - cmTarget* target, ImportPropertyMap& properties, + cmGeneratorTarget* target, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { // Add the transitive link dependencies for this configuration. - cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, - target); + cmLinkInterface const* iface = target->GetLinkInterface(config, + target->Target); if (!iface) { return; @@ -812,12 +830,14 @@ cmExportFileGenerator } const bool newCMP0022Behavior = - target->GetPolicyStatusCMP0022() != cmPolicies::WARN - && target->GetPolicyStatusCMP0022() != cmPolicies::OLD; + target->Target + ->GetPolicyStatusCMP0022() != cmPolicies::WARN + && target->Target + ->GetPolicyStatusCMP0022() != cmPolicies::OLD; if(newCMP0022Behavior && !this->ExportOld) { - cmMakefile *mf = target->GetMakefile(); + cmMakefile *mf = target->Target->GetMakefile(); std::ostringstream e; e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, " "but also has old-style LINK_INTERFACE_LIBRARIES properties " @@ -837,7 +857,7 @@ cmExportFileGenerator preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, + this->ResolveTargetsInGeneratorExpressions(prepro, target->Target, missingTargets, ReplaceFreeTargets); properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro; @@ -849,12 +869,13 @@ void cmExportFileGenerator ::SetImportDetailProperties(const std::string& config, std::string const& suffix, - cmTarget* target, ImportPropertyMap& properties, + cmGeneratorTarget* target, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets ) { // Get the makefile in which to lookup target information. - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Makefile; // Add the soname for unix shared libraries. if(target->GetType() == cmTarget::SHARED_LIBRARY || @@ -887,8 +908,8 @@ cmExportFileGenerator } // Add the transitive link dependencies for this configuration. - if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, - target)) + if(cmLinkInterface const* iface = + target->GetLinkInterface(config, target->Target)) { this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", @@ -914,7 +935,7 @@ template <typename T> void cmExportFileGenerator ::SetImportLinkProperty(std::string const& suffix, - cmTarget* target, + cmGeneratorTarget* target, const std::string& propName, std::vector<T> const& entries, ImportPropertyMap& properties, @@ -938,7 +959,7 @@ cmExportFileGenerator sep = ";"; std::string temp = *li; - this->AddTargetNamespace(temp, target, missingTargets); + this->AddTargetNamespace(temp, target->Target, missingTargets); link_entries += temp; } @@ -1112,7 +1133,8 @@ cmExportFileGenerator for(ImportPropertyMap::const_iterator pi = properties.begin(); pi != properties.end(); ++pi) { - os << " " << pi->first << " \"" << pi->second << "\"\n"; + os << " " << pi->first << " " + << cmExportFileGeneratorEscape(pi->second) << "\n"; } os << " )\n" << "\n"; @@ -1223,7 +1245,7 @@ cmExportFileGenerator ImportPropertyMap::const_iterator pi = properties.find(*li); if (pi != properties.end()) { - os << "\"" << pi->second << "\" "; + os << cmExportFileGeneratorEscape(pi->second) << " "; } } diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index b6f4166..44f779b 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -92,13 +92,15 @@ protected: // Collect properties with detailed information about targets beyond // their location on disk. void SetImportDetailProperties(const std::string& config, - std::string const& suffix, cmTarget* target, + std::string const& suffix, + cmGeneratorTarget* target, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); template <typename T> void SetImportLinkProperty(std::string const& suffix, - cmTarget* target, const std::string& propName, + cmGeneratorTarget* target, + const std::string& propName, std::vector<T> const& entries, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); @@ -130,7 +132,7 @@ protected: std::vector<std::string> &missingTargets); void PopulateInterfaceProperty(const std::string& propName, cmTarget *target, ImportPropertyMap &properties); - void PopulateCompatibleInterfaceProperties(cmTarget *target, + void PopulateCompatibleInterfaceProperties(cmGeneratorTarget *target, ImportPropertyMap &properties); void GenerateInterfaceProperties(cmTarget const* target, std::ostream& os, const ImportPropertyMap &properties); @@ -148,7 +150,7 @@ protected: void SetImportLinkInterface(const std::string& config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, - cmTarget* target, ImportPropertyMap& properties, + cmGeneratorTarget* target, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); enum FreeTargetsReplace { @@ -198,7 +200,7 @@ private: virtual void ReplaceInstallPrefix(std::string &input); - virtual std::string InstallNameDir(cmTarget* target, + virtual std::string InstallNameDir(cmGeneratorTarget* target, const std::string& config) = 0; }; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 89c6ca2..7ffab0c 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -72,8 +72,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) // Set an _IMPORT_PREFIX variable for import location properties // to reference if they are relative to the install prefix. - std::string installPrefix = - this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + std::string installPrefix = this->IEGen->GetLocalGenerator() + ->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); std::string const& expDest = this->IEGen->GetDestination(); if(cmSystemTools::FileIsFullPath(expDest)) { @@ -193,7 +193,11 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); - this->PopulateCompatibleInterfaceProperties(te, properties); + cmGeneratorTarget *gtgt = te->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(te); + + this->PopulateCompatibleInterfaceProperties(gtgt, properties); this->GenerateInterfaceProperties(te, os, properties); } @@ -358,12 +362,14 @@ cmExportInstallFileGenerator if(!properties.empty()) { // Get the rest of the target details. + cmGeneratorTarget *gtgt = te->Target->GetMakefile() + ->GetGlobalGenerator()->GetGeneratorTarget(te->Target); this->SetImportDetailProperties(config, suffix, - te->Target, properties, missingTargets); + gtgt, properties, missingTargets); this->SetImportLinkInterface(config, suffix, cmGeneratorExpression::InstallInterface, - te->Target, properties, missingTargets); + gtgt, properties, missingTargets); // TOOD: PUBLIC_HEADER_LOCATION // This should wait until the build feature propagation stuff @@ -396,7 +402,7 @@ cmExportInstallFileGenerator } // Get the target to be installed. - cmTarget* target = itgen->GetTarget(); + cmTarget* target = itgen->GetTarget()->Target; // Construct the installed location of the target. std::string dest = itgen->GetDestination(config); @@ -540,12 +546,12 @@ cmExportInstallFileGenerator } std::string -cmExportInstallFileGenerator::InstallNameDir(cmTarget* target, +cmExportInstallFileGenerator::InstallNameDir(cmGeneratorTarget* target, const std::string&) { std::string install_name_dir; - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { install_name_dir = diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 6f86ac9..b06fee5 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -83,7 +83,8 @@ protected: std::set<std::string>& importedLocations ); - std::string InstallNameDir(cmTarget* target, const std::string& config); + std::string InstallNameDir(cmGeneratorTarget* target, + const std::string& config); cmInstallExportGenerator* IEGen; diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index cb150a7..fde8fb1 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -11,7 +11,6 @@ ============================================================================*/ #include "cmExportLibraryDependenciesCommand.h" #include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" #include "cmGeneratedFileStream.h" #include "cmake.h" #include "cmVersion.h" @@ -82,15 +81,14 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const // the project. cmake* cm = this->Makefile->GetCMakeInstance(); cmGlobalGenerator* global = cm->GetGlobalGenerator(); - const std::vector<cmLocalGenerator *>& locals = global->GetLocalGenerators(); + const std::vector<cmMakefile*>& locals = global->GetMakefiles(); std::map<std::string, std::string> libDepsOld; std::map<std::string, std::string> libDepsNew; std::map<std::string, std::string> libTypes; - for(std::vector<cmLocalGenerator *>::const_iterator i = locals.begin(); + for(std::vector<cmMakefile*>::const_iterator i = locals.begin(); i != locals.end(); ++i) { - const cmLocalGenerator* gen = *i; - const cmTargets &tgts = gen->GetMakefile()->GetTargets(); + const cmTargets &tgts = (*i)->GetTargets(); for(cmTargets::const_iterator l = tgts.begin(); l != tgts.end(); ++l) { diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index eb8d193..ba66531 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -13,9 +13,16 @@ #include "cmExportTryCompileFileGenerator.h" #include "cmGeneratedFileStream.h" +#include "cmGlobalGenerator.h" #include "cmGeneratorExpressionDAGChecker.h" //---------------------------------------------------------------------------- +cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator( + cmGlobalGenerator* gg) +{ + gg->CreateGenerationObjects(cmGlobalGenerator::ImportedOnly); +} + bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os) { std::set<cmTarget const*> emitted; @@ -99,8 +106,6 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget const* target, || i->first.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0 || i->first.find("INTERFACE_LINK_LIBRARIES") == 0) { - const std::string libs = i->second.GetValue(); - std::string evalResult = this->FindTargets(i->first, target, emitted); @@ -118,13 +123,14 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget const* target, } } } + std::string -cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target, +cmExportTryCompileFileGenerator::InstallNameDir(cmGeneratorTarget* target, const std::string& config) { std::string install_name_dir; - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { install_name_dir = diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index ec70d81..8838eca 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -9,8 +9,8 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ -#ifndef cmExportInstallFileGenerator_h -#define cmExportInstallFileGenerator_h +#ifndef cmExportTryCompileFileGenerator_h +#define cmExportTryCompileFileGenerator_h #include "cmExportFileGenerator.h" @@ -20,6 +20,8 @@ class cmInstallTargetGenerator; class cmExportTryCompileFileGenerator: public cmExportFileGenerator { public: + cmExportTryCompileFileGenerator(cmGlobalGenerator* gg); + /** Set the list of targets to export. */ void SetExports(const std::vector<cmTarget const*> &exports) { this->Exports = exports; } @@ -43,7 +45,7 @@ protected: ImportPropertyMap& properties, std::set<cmTarget const*> &emitted); - std::string InstallNameDir(cmTarget* target, + std::string InstallNameDir(cmGeneratorTarget* target, const std::string& config); private: std::string FindTargets(const std::string& prop, cmTarget const* tgt, diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index e374387..dfd51c7 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -313,7 +313,7 @@ void cmExtraCodeBlocksGenerator " "<<virtualFolders<<"\n" " <Build>\n"; - this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str()); + this->AppendTarget(fout, "all", 0, make.c_str(), lgs[0], compiler.c_str()); // add all executable and library targets and some of the GLOBAL // and UTILITY targets @@ -335,7 +335,7 @@ void cmExtraCodeBlocksGenerator makefile->GetHomeOutputDirectory())==0) { this->AppendTarget(fout, ti->first, 0, - make.c_str(), makefile, compiler.c_str()); + make.c_str(), *lg, compiler.c_str()); } } break; @@ -351,7 +351,7 @@ void cmExtraCodeBlocksGenerator } this->AppendTarget(fout, ti->first, 0, - make.c_str(), makefile, compiler.c_str()); + make.c_str(), *lg, compiler.c_str()); break; case cmTarget::EXECUTABLE: case cmTarget::STATIC_LIBRARY: @@ -360,11 +360,11 @@ void cmExtraCodeBlocksGenerator case cmTarget::OBJECT_LIBRARY: { this->AppendTarget(fout, ti->first, &ti->second, - make.c_str(), makefile, compiler.c_str()); + make.c_str(), *lg, compiler.c_str()); std::string fastTarget = ti->first; fastTarget += "/fast"; this->AppendTarget(fout, fastTarget, &ti->second, - make.c_str(), makefile, compiler.c_str()); + make.c_str(), *lg, compiler.c_str()); } break; default: @@ -519,14 +519,16 @@ void cmExtraCodeBlocksGenerator // Write a dummy file for OBJECT libraries, so C::B can reference some file std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile( - cmMakefile* mf, cmTarget* target) const + cmLocalGenerator* lg, + cmTarget* target) const { + cmMakefile *mf = lg->GetMakefile(); // this file doesn't seem to be used by C::B in custom makefile mode, // but we generate a unique file for each OBJECT library so in case // C::B uses it in some way, the targets don't interfere with each other. std::string filename = mf->GetCurrentBinaryDirectory(); filename += "/"; - filename += mf->GetLocalGenerator()->GetTargetDirectory(*target); + filename += lg->GetTargetDirectory(*target); filename += "/"; filename += target->GetName(); filename += ".objlib"; @@ -547,9 +549,10 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, const std::string& targetName, cmTarget* target, const char* make, - const cmMakefile* makefile, + const cmLocalGenerator* lg, const char* compiler) { + cmMakefile const* makefile = lg->GetMakefile(); std::string makefileName = makefile->GetCurrentBinaryDirectory(); makefileName += "/Makefile"; @@ -583,12 +586,14 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, std::string location; if ( target->GetType()==cmTarget::OBJECT_LIBRARY) { - location = this->CreateDummyTargetFile(const_cast<cmMakefile*>(makefile), + location = this->CreateDummyTargetFile(const_cast<cmLocalGenerator*>(lg), target); } else { - location = target->GetLocation(buildType); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(target); + location = gt->GetLocation(buildType); } fout<<" <Option output=\"" << location @@ -604,7 +609,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, // the compilerdefines for this target std::vector<std::string> cdefs; - target->GetCompileDefinitions(cdefs, buildType, "C"); + gtgt->GetCompileDefinitions(cdefs, buildType, "C"); // Expand the list. for(std::vector<std::string>::const_iterator di = cdefs.begin(); @@ -618,8 +623,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, std::set<std::string> uniqIncludeDirs; std::vector<std::string> includes; - target->GetMakefile()->GetLocalGenerator()-> - GetIncludeDirectories(includes, gtgt, "C", buildType); + lg->GetIncludeDirectories(includes, gtgt, "C", buildType); uniqIncludeDirs.insert(includes.begin(), includes.end()); diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h index 97da1b8..e5ede9a 100644 --- a/Source/cmExtraCodeBlocksGenerator.h +++ b/Source/cmExtraCodeBlocksGenerator.h @@ -48,7 +48,8 @@ private: void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs, const std::string& filename); - std::string CreateDummyTargetFile(cmMakefile* mf, cmTarget* target) const; + std::string CreateDummyTargetFile(cmLocalGenerator* lg, + cmTarget* target) const; std::string GetCBCompilerId(const cmMakefile* mf); int GetCBTargetType(cmTarget* target); @@ -58,7 +59,7 @@ private: const std::string& targetName, cmTarget* target, const char* make, - const cmMakefile* makefile, + const cmLocalGenerator* lg, const char* compiler); }; diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 9705d2b..c2cff14 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -141,24 +141,6 @@ void cmExtraCodeLiteGenerator return; } - // figure out the compiler - //std::string compiler = this->GetCBCompilerId(mf); - std::string workspaceSourcePath = mf->GetHomeDirectory(); - std::string workspaceOutputDir = mf->GetHomeOutputDirectory(); - std::vector<std::string> outputFiles = mf->GetOutputFiles(); - std::string projectName = mf->GetProjectName(); - std::string incDirs; - std::vector<cmValueWithOrigin> incDirsVec = - mf->GetIncludeDirectoriesEntries(); - std::vector<cmValueWithOrigin>::const_iterator iterInc = incDirsVec.begin(); - - //std::cout << "GetIncludeDirectories:" << std::endl; - for(; iterInc != incDirsVec.end(); ++iterInc ) - { - //std::cout << (*ItStrVec) << std::endl; - incDirs += iterInc->Value + " "; - } - //////////////////////////////////// fout << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<CodeLite_Project Name=\"" << mf->GetProjectName() diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index a81e53c..44bf586 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -598,7 +598,8 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets( linkName4 += "/"; linkName4 += cmSystemTools::GetFilenameName(fullPath); this->AppendLinkedResource(fout, linkName4, - fullPath, LinkToFile); + this->GetEclipsePath(fullPath), + LinkToFile); } } } diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index 578e7d3..f83b5cf 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -19,7 +19,6 @@ #include "cmGeneratedFileStream.h" #include "cmTarget.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" #include <cmsys/SystemTools.hxx> diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 4e721d4..163a75b 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -21,7 +21,6 @@ #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmXMLSafe.h" #include <cmsys/SystemTools.hxx> diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 4698468..87faf84 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -66,7 +66,7 @@ static mode_t mode_setuid = S_ISUID; static mode_t mode_setgid = S_ISGID; #endif -#if defined(WIN32) && defined(CMAKE_ENCODING_UTF8) +#if defined(_WIN32) && defined(CMAKE_ENCODING_UTF8) // libcurl doesn't support file:// urls for unicode filenames on Windows. // Convert string from UTF-8 to ACP if this is a file:// URL. static std::string fix_file_url_windows(const std::string& url) @@ -270,7 +270,7 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, this->SetError(error); return false; } - std::string message = cmJoin(cmRange(i, args.end()), std::string()); + std::string message = cmJoin(cmMakeRange(i, args.end()), std::string()); file << message; file.close(); if(mode) @@ -906,13 +906,13 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, { switch(status) { + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: g.RecurseThroughSymlinksOff(); break; case cmPolicies::OLD: case cmPolicies::WARN: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: g.RecurseThroughSymlinksOn(); break; } @@ -1044,6 +1044,8 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, { switch (status) { + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: // Correct behavior, yay! break; @@ -1059,12 +1061,6 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, cmPolicies::GetPolicyWarning(cmPolicies::CMP0009)); } break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - this->SetError("policy CMP0009 error"); - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0009)); - return false; } } @@ -3160,7 +3156,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) return false; } -#if defined(WIN32) && defined(CMAKE_ENCODING_UTF8) +#if defined(_WIN32) && defined(CMAKE_ENCODING_UTF8) url = fix_file_url_windows(url); #endif @@ -3415,7 +3411,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) unsigned long file_size = cmsys::SystemTools::FileLength(filename); -#if defined(WIN32) && defined(CMAKE_ENCODING_UTF8) +#if defined(_WIN32) && defined(CMAKE_ENCODING_UTF8) url = fix_file_url_windows(url); #endif @@ -3569,19 +3565,16 @@ void cmFileCommand::AddEvaluationFile(const std::string &inputName, { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression outputGe(&lfbt); + cmGeneratorExpression outputGe(lfbt); cmsys::auto_ptr<cmCompiledGeneratorExpression> outputCge = outputGe.Parse(outputExpr); - cmGeneratorExpression conditionGe(&lfbt); + cmGeneratorExpression conditionGe(lfbt); cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge = conditionGe.Parse(condition); - this->Makefile->GetGlobalGenerator()->AddEvaluationFile(inputName, - outputCge, - this->Makefile, - conditionCge, - inputIsContent); + this->Makefile->AddEvaluationFile(inputName, outputCge, + conditionCge, inputIsContent); } //---------------------------------------------------------------------------- diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index add06a7..7959ffe 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -170,8 +170,8 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) else { this->VariableDocumentation += "one of the "; - this->VariableDocumentation += cmJoin(cmRange(this->Names).retreat(1), - ", "); + this->VariableDocumentation += + cmJoin(cmMakeRange(this->Names).retreat(1), ", "); this->VariableDocumentation += " or " + this->Names[this->Names.size() - 1] + " libraries be found"; } diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 0a66732..e8d158e 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -11,7 +11,6 @@ ============================================================================*/ #include "cmFindLibraryCommand.h" #include <cmsys/Directory.hxx> -#include <cmsys/stl/algorithm> cmFindLibraryCommand::cmFindLibraryCommand() { diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 68a6558..9b9071d 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1378,7 +1378,7 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir, cmFindPackageCommandHoldFile holdFile(fname.c_str()); // Load the file. - cmsys::ifstream fin(fname.c_str(), std::ios::in | cmsys_ios_binary); + cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary); std::string fentry; if(fin && cmSystemTools::GetLineFromStream(fin, fentry) && this->CheckPackageRegistryEntry(fentry, outPaths)) diff --git a/Source/cmDependsFortranLexer.cxx b/Source/cmFortranLexer.cxx index 1eff1e4..b727f0e 100644 --- a/Source/cmDependsFortranLexer.cxx +++ b/Source/cmFortranLexer.cxx @@ -9,9 +9,9 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ -#line 2 "cmDependsFortranLexer.cxx" +#line 2 "cmFortranLexer.cxx" -#line 4 "cmDependsFortranLexer.cxx" +#line 4 "cmFortranLexer.cxx" #define YY_INT_ALIGNED short int @@ -164,7 +164,7 @@ typedef void* yyscan_t; #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE cmDependsFortran_yyrestart(yyin ,yyscanner ) +#define YY_NEW_FILE cmFortran_yyrestart(yyin ,yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 @@ -274,7 +274,7 @@ struct yy_buffer_state * possible backing-up. * * When we actually see the EOF, we change the status to "new" - * (via cmDependsFortran_yyrestart()), so that the user can continue scanning by + * (via cmFortran_yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 @@ -297,36 +297,36 @@ struct yy_buffer_state */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] -void cmDependsFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner ); -void cmDependsFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void cmDependsFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void cmDependsFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner ); +void cmFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void cmFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void cmFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void cmFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void cmFortran_yypop_buffer_state (yyscan_t yyscanner ); -static void cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner ); -static void cmDependsFortran_yy_load_buffer_state (yyscan_t yyscanner ); -static void cmDependsFortran_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); +static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner ); +static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner ); +static void cmFortran_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); -#define YY_FLUSH_BUFFER cmDependsFortran_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) +#define YY_FLUSH_BUFFER cmFortran_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) -YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); -void *cmDependsFortran_yyalloc (yy_size_t ,yyscan_t yyscanner ); -void *cmDependsFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); -void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner ); +void *cmFortran_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *cmFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void cmFortran_yyfree (void * ,yyscan_t yyscanner ); -#define yy_new_buffer cmDependsFortran_yy_create_buffer +#define yy_new_buffer cmFortran_yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ - cmDependsFortran_yyensure_buffer_stack (yyscanner); \ + cmFortran_yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - cmDependsFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } @@ -334,9 +334,9 @@ void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner ); #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ - cmDependsFortran_yyensure_buffer_stack (yyscanner); \ + cmFortran_yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - cmDependsFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } @@ -345,7 +345,7 @@ void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner ); /* Begin user sect3 */ -#define cmDependsFortran_yywrap(n) 1 +#define cmFortran_yywrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -622,8 +622,8 @@ static yyconst flex_int16_t yy_chk[547] = #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET -#line 1 "cmDependsFortranLexer.in.l" -#line 2 "cmDependsFortranLexer.in.l" +#line 1 "cmFortranLexer.in.l" +#line 2 "cmFortranLexer.in.l" /*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2000-2009 Kitware, Inc., Insight Software Consortium @@ -651,17 +651,17 @@ This file must be translated to C and modified to build everywhere. Run flex like this: - flex -i --prefix=cmDependsFortran_yy --header-file=cmDependsFortranLexer.h -ocmDependsFortranLexer.cxx cmDependsFortranLexer.in.l + flex -i --prefix=cmFortran_yy --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l -Modify cmDependsFortranLexer.cxx: +Modify cmFortranLexer.cxx: - remove TABs - remove "yyscanner" argument from these methods: - yy_fatal_error, cmDependsFortran_yyalloc, cmDependsFortran_yyrealloc, cmDependsFortran_yyfree - - remove "yyscanner = NULL" from end of cmDependsFortran_yylex_destroy + yy_fatal_error, cmFortran_yyalloc, cmFortran_yyrealloc, cmFortran_yyfree + - remove "yyscanner = NULL" from end of cmFortran_yylex_destroy - remove all YY_BREAK lines occurring right after return statements - change while ( 1 ) to for(;;) -Modify cmDependsFortranLexer.h: +Modify cmFortranLexer.h: - remove TABs - remove the yy_init_globals function - remove the block that includes unistd.h @@ -671,21 +671,21 @@ Modify cmDependsFortranLexer.h: #include "cmStandardLexer.h" -#define cmDependsFortranLexer_cxx -#include "cmDependsFortranParser.h" /* Interface to parser object. */ +#define cmFortranLexer_cxx +#include "cmFortranParser.h" /* Interface to parser object. */ /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmDependsFortranParser_Input(yyextra, buf, max_size); } + { result = cmFortranParser_Input(yyextra, buf, max_size); } /* Include the set of tokens from the parser. */ -#include "cmDependsFortranParserTokens.h" +#include "cmFortranParserTokens.h" /*--------------------------------------------------------------------------*/ -#line 678 "cmDependsFortranLexer.cxx" +#line 678 "cmFortranLexer.cxx" #define INITIAL 0 #define free_fmt 1 @@ -741,38 +741,38 @@ struct yyguts_t static int yy_init_globals (yyscan_t yyscanner ); -int cmDependsFortran_yylex_init (yyscan_t* scanner); +int cmFortran_yylex_init (yyscan_t* scanner); -int cmDependsFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); +int cmFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int cmDependsFortran_yylex_destroy (yyscan_t yyscanner ); +int cmFortran_yylex_destroy (yyscan_t yyscanner ); -int cmDependsFortran_yyget_debug (yyscan_t yyscanner ); +int cmFortran_yyget_debug (yyscan_t yyscanner ); -void cmDependsFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner ); +void cmFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner ); -YY_EXTRA_TYPE cmDependsFortran_yyget_extra (yyscan_t yyscanner ); +YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner ); -void cmDependsFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); +void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); -FILE *cmDependsFortran_yyget_in (yyscan_t yyscanner ); +FILE *cmFortran_yyget_in (yyscan_t yyscanner ); -void cmDependsFortran_yyset_in (FILE * in_str ,yyscan_t yyscanner ); +void cmFortran_yyset_in (FILE * in_str ,yyscan_t yyscanner ); -FILE *cmDependsFortran_yyget_out (yyscan_t yyscanner ); +FILE *cmFortran_yyget_out (yyscan_t yyscanner ); -void cmDependsFortran_yyset_out (FILE * out_str ,yyscan_t yyscanner ); +void cmFortran_yyset_out (FILE * out_str ,yyscan_t yyscanner ); -int cmDependsFortran_yyget_leng (yyscan_t yyscanner ); +int cmFortran_yyget_leng (yyscan_t yyscanner ); -char *cmDependsFortran_yyget_text (yyscan_t yyscanner ); +char *cmFortran_yyget_text (yyscan_t yyscanner ); -int cmDependsFortran_yyget_lineno (yyscan_t yyscanner ); +int cmFortran_yyget_lineno (yyscan_t yyscanner ); -void cmDependsFortran_yyset_lineno (int line_number ,yyscan_t yyscanner ); +void cmFortran_yyset_lineno (int line_number ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -780,9 +780,9 @@ void cmDependsFortran_yyset_lineno (int line_number ,yyscan_t yyscanner ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int cmDependsFortran_yywrap (yyscan_t yyscanner ); +extern "C" int cmFortran_yywrap (yyscan_t yyscanner ); #else -extern int cmDependsFortran_yywrap (yyscan_t yyscanner ); +extern int cmFortran_yywrap (yyscan_t yyscanner ); #endif #endif @@ -886,9 +886,9 @@ static int input (yyscan_t yyscanner ); #ifndef YY_DECL #define YY_DECL_IS_OURS 1 -extern int cmDependsFortran_yylex (yyscan_t yyscanner); +extern int cmFortran_yylex (yyscan_t yyscanner); -#define YY_DECL int cmDependsFortran_yylex (yyscan_t yyscanner) +#define YY_DECL int cmFortran_yylex (yyscan_t yyscanner) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng @@ -918,10 +918,10 @@ YY_DECL int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 71 "cmDependsFortranLexer.in.l" +#line 71 "cmFortranLexer.in.l" -#line 914 "cmDependsFortranLexer.cxx" +#line 914 "cmFortranLexer.cxx" if ( !yyg->yy_init ) { @@ -941,12 +941,12 @@ YY_DECL yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { - cmDependsFortran_yyensure_buffer_stack (yyscanner); + cmFortran_yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - cmDependsFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } - cmDependsFortran_yy_load_buffer_state(yyscanner ); + cmFortran_yy_load_buffer_state(yyscanner ); } for(;;) /* loops until end-of-file is reached */ @@ -1007,47 +1007,47 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 73 "cmDependsFortranLexer.in.l" +#line 73 "cmFortranLexer.in.l" { - cmDependsFortranParser_StringStart(yyextra); - cmDependsFortranParser_SetOldStartcond(yyextra, YY_START); + cmFortranParser_StringStart(yyextra); + cmFortranParser_SetOldStartcond(yyextra, YY_START); BEGIN(str_dq); } YY_BREAK case 2: YY_RULE_SETUP -#line 79 "cmDependsFortranLexer.in.l" +#line 79 "cmFortranLexer.in.l" { - cmDependsFortranParser_StringStart(yyextra); - cmDependsFortranParser_SetOldStartcond(yyextra, YY_START); + cmFortranParser_StringStart(yyextra); + cmFortranParser_SetOldStartcond(yyextra, YY_START); BEGIN(str_sq); } YY_BREAK case 3: -#line 86 "cmDependsFortranLexer.in.l" +#line 86 "cmFortranLexer.in.l" case 4: YY_RULE_SETUP -#line 86 "cmDependsFortranLexer.in.l" +#line 86 "cmFortranLexer.in.l" { - BEGIN(cmDependsFortranParser_GetOldStartcond(yyextra) ); - yylvalp->string = strdup(cmDependsFortranParser_StringEnd(yyextra)); + BEGIN(cmFortranParser_GetOldStartcond(yyextra) ); + yylvalp->string = strdup(cmFortranParser_StringEnd(yyextra)); return STRING; } case 5: /* rule 5 can match eol */ -#line 93 "cmDependsFortranLexer.in.l" +#line 93 "cmFortranLexer.in.l" case 6: /* rule 6 can match eol */ YY_RULE_SETUP -#line 93 "cmDependsFortranLexer.in.l" +#line 93 "cmFortranLexer.in.l" /* Ignore (continued strings, free fmt) */ YY_BREAK case 7: /* rule 7 can match eol */ YY_RULE_SETUP -#line 95 "cmDependsFortranLexer.in.l" +#line 95 "cmFortranLexer.in.l" { - if (cmDependsFortranParser_GetOldStartcond(yyextra) == fixed_fmt) + if (cmFortranParser_GetOldStartcond(yyextra) == fixed_fmt) ; /* Ignore (cont. strings, fixed fmt) */ else { @@ -1058,7 +1058,7 @@ YY_RULE_SETUP case 8: /* rule 8 can match eol */ YY_RULE_SETUP -#line 105 "cmDependsFortranLexer.in.l" +#line 105 "cmFortranLexer.in.l" { unput ('\n'); BEGIN(INITIAL); @@ -1066,25 +1066,25 @@ YY_RULE_SETUP } case 9: YY_RULE_SETUP -#line 111 "cmDependsFortranLexer.in.l" +#line 111 "cmFortranLexer.in.l" { - cmDependsFortranParser_StringAppend(yyextra, yytext[0]); + cmFortranParser_StringAppend(yyextra, yytext[0]); } YY_BREAK case 10: /* rule 10 can match eol */ YY_RULE_SETUP -#line 115 "cmDependsFortranLexer.in.l" +#line 115 "cmFortranLexer.in.l" { return EOSTMT; } /* Treat comments like */ case 11: /* rule 11 can match eol */ YY_RULE_SETUP -#line 116 "cmDependsFortranLexer.in.l" +#line 116 "cmFortranLexer.in.l" { return EOSTMT; } /* empty lines */ case 12: /* rule 12 can match eol */ YY_RULE_SETUP -#line 118 "cmDependsFortranLexer.in.l" +#line 118 "cmFortranLexer.in.l" { yytext[yyleng-1] = 0; yylvalp->string = strdup(strchr(yytext, '<')+1); @@ -1092,149 +1092,149 @@ YY_RULE_SETUP } case 13: YY_RULE_SETUP -#line 123 "cmDependsFortranLexer.in.l" +#line 123 "cmFortranLexer.in.l" { return CPP_INCLUDE; } case 14: YY_RULE_SETUP -#line 124 "cmDependsFortranLexer.in.l" +#line 124 "cmFortranLexer.in.l" { return F90PPR_INCLUDE; } case 15: YY_RULE_SETUP -#line 125 "cmDependsFortranLexer.in.l" +#line 125 "cmFortranLexer.in.l" { return COCO_INCLUDE; } case 16: YY_RULE_SETUP -#line 127 "cmDependsFortranLexer.in.l" +#line 127 "cmFortranLexer.in.l" { return CPP_DEFINE; } case 17: YY_RULE_SETUP -#line 128 "cmDependsFortranLexer.in.l" +#line 128 "cmFortranLexer.in.l" { return F90PPR_DEFINE; } case 18: YY_RULE_SETUP -#line 130 "cmDependsFortranLexer.in.l" +#line 130 "cmFortranLexer.in.l" { return CPP_UNDEF; } case 19: YY_RULE_SETUP -#line 131 "cmDependsFortranLexer.in.l" +#line 131 "cmFortranLexer.in.l" { return F90PPR_UNDEF; } case 20: YY_RULE_SETUP -#line 133 "cmDependsFortranLexer.in.l" +#line 133 "cmFortranLexer.in.l" { return CPP_IFDEF; } case 21: YY_RULE_SETUP -#line 134 "cmDependsFortranLexer.in.l" +#line 134 "cmFortranLexer.in.l" { return CPP_IFNDEF; } case 22: YY_RULE_SETUP -#line 135 "cmDependsFortranLexer.in.l" +#line 135 "cmFortranLexer.in.l" { return CPP_IF; } case 23: YY_RULE_SETUP -#line 136 "cmDependsFortranLexer.in.l" +#line 136 "cmFortranLexer.in.l" { return CPP_ELIF; } case 24: YY_RULE_SETUP -#line 137 "cmDependsFortranLexer.in.l" +#line 137 "cmFortranLexer.in.l" { return CPP_ELSE; } case 25: YY_RULE_SETUP -#line 138 "cmDependsFortranLexer.in.l" +#line 138 "cmFortranLexer.in.l" { return CPP_ENDIF; } case 26: YY_RULE_SETUP -#line 140 "cmDependsFortranLexer.in.l" +#line 140 "cmFortranLexer.in.l" { return F90PPR_IFDEF; } case 27: YY_RULE_SETUP -#line 141 "cmDependsFortranLexer.in.l" +#line 141 "cmFortranLexer.in.l" { return F90PPR_IFNDEF; } case 28: YY_RULE_SETUP -#line 142 "cmDependsFortranLexer.in.l" +#line 142 "cmFortranLexer.in.l" { return F90PPR_IF; } case 29: YY_RULE_SETUP -#line 143 "cmDependsFortranLexer.in.l" +#line 143 "cmFortranLexer.in.l" { return F90PPR_ELIF; } case 30: YY_RULE_SETUP -#line 144 "cmDependsFortranLexer.in.l" +#line 144 "cmFortranLexer.in.l" { return F90PPR_ELSE; } case 31: YY_RULE_SETUP -#line 145 "cmDependsFortranLexer.in.l" +#line 145 "cmFortranLexer.in.l" { return F90PPR_ENDIF; } /* Line continuations, possible involving comments. */ case 32: /* rule 32 can match eol */ YY_RULE_SETUP -#line 148 "cmDependsFortranLexer.in.l" +#line 148 "cmFortranLexer.in.l" YY_BREAK case 33: /* rule 33 can match eol */ YY_RULE_SETUP -#line 149 "cmDependsFortranLexer.in.l" +#line 149 "cmFortranLexer.in.l" YY_BREAK case 34: YY_RULE_SETUP -#line 151 "cmDependsFortranLexer.in.l" +#line 151 "cmFortranLexer.in.l" { return COMMA; } case 35: YY_RULE_SETUP -#line 153 "cmDependsFortranLexer.in.l" +#line 153 "cmFortranLexer.in.l" { return DCOLON; } case 36: /* rule 36 can match eol */ YY_RULE_SETUP -#line 155 "cmDependsFortranLexer.in.l" +#line 155 "cmFortranLexer.in.l" { return GARBAGE; } case 37: YY_RULE_SETUP -#line 157 "cmDependsFortranLexer.in.l" +#line 157 "cmFortranLexer.in.l" { return ASSIGNMENT_OP; } case 38: YY_RULE_SETUP -#line 159 "cmDependsFortranLexer.in.l" +#line 159 "cmFortranLexer.in.l" { yylvalp->string = strdup(yytext); return WORD; } case 39: YY_RULE_SETUP -#line 164 "cmDependsFortranLexer.in.l" +#line 164 "cmFortranLexer.in.l" { return GARBAGE; } case 40: /* rule 40 can match eol */ YY_RULE_SETUP -#line 166 "cmDependsFortranLexer.in.l" +#line 166 "cmFortranLexer.in.l" { return EOSTMT; } case 41: YY_RULE_SETUP -#line 169 "cmDependsFortranLexer.in.l" +#line 169 "cmFortranLexer.in.l" /* Ignore */ YY_BREAK case 42: /* rule 42 can match eol */ YY_RULE_SETUP -#line 170 "cmDependsFortranLexer.in.l" +#line 170 "cmFortranLexer.in.l" /* Ignore line-endings preceeded by \ */ YY_BREAK case 43: YY_RULE_SETUP -#line 172 "cmDependsFortranLexer.in.l" +#line 172 "cmFortranLexer.in.l" { return *yytext; } case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(free_fmt): case YY_STATE_EOF(fixed_fmt): case YY_STATE_EOF(str_sq): case YY_STATE_EOF(str_dq): -#line 174 "cmDependsFortranLexer.in.l" +#line 174 "cmFortranLexer.in.l" { - if(!cmDependsFortranParser_FilePop(yyextra) ) + if(!cmFortranParser_FilePop(yyextra) ) { return YY_NULL; } @@ -1242,10 +1242,10 @@ case YY_STATE_EOF(str_dq): YY_BREAK case 44: YY_RULE_SETUP -#line 181 "cmDependsFortranLexer.in.l" +#line 181 "cmFortranLexer.in.l" ECHO; YY_BREAK -#line 1270 "cmDependsFortranLexer.cxx" +#line 1270 "cmFortranLexer.cxx" case YY_END_OF_BUFFER: { @@ -1261,7 +1261,7 @@ ECHO; /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called - * cmDependsFortran_yylex(). If so, then we have to assure + * cmFortran_yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a @@ -1321,7 +1321,7 @@ ECHO; { yyg->yy_did_buffer_switch_on_eof = 0; - if ( cmDependsFortran_yywrap(yyscanner ) ) + if ( cmFortran_yywrap(yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -1374,7 +1374,7 @@ ECHO; "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ -} /* end of cmDependsFortran_yylex */ +} /* end of cmFortran_yylex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -1453,7 +1453,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - cmDependsFortran_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + cmFortran_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); } else /* Can't grow it, we don't own it. */ @@ -1485,7 +1485,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - cmDependsFortran_yyrestart(yyin ,yyscanner); + cmFortran_yyrestart(yyin ,yyscanner); } else @@ -1502,7 +1502,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmDependsFortran_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmFortran_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } @@ -1656,13 +1656,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ /* Reset buffer status. */ - cmDependsFortran_yyrestart(yyin ,yyscanner); + cmFortran_yyrestart(yyin ,yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( cmDependsFortran_yywrap(yyscanner ) ) + if ( cmFortran_yywrap(yyscanner ) ) return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) @@ -1696,34 +1696,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner) * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ - void cmDependsFortran_yyrestart (FILE * input_file , yyscan_t yyscanner) + void cmFortran_yyrestart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ - cmDependsFortran_yyensure_buffer_stack (yyscanner); + cmFortran_yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - cmDependsFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } - cmDependsFortran_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - cmDependsFortran_yy_load_buffer_state(yyscanner ); + cmFortran_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + cmFortran_yy_load_buffer_state(yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ - void cmDependsFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) + void cmFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with - * cmDependsFortran_yypop_buffer_state(); - * cmDependsFortran_yypush_buffer_state(new_buffer); + * cmFortran_yypop_buffer_state(); + * cmFortran_yypush_buffer_state(new_buffer); */ - cmDependsFortran_yyensure_buffer_stack (yyscanner); + cmFortran_yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; @@ -1736,17 +1736,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner) } YY_CURRENT_BUFFER_LVALUE = new_buffer; - cmDependsFortran_yy_load_buffer_state(yyscanner ); + cmFortran_yy_load_buffer_state(yyscanner ); /* We don't actually know whether we did this switch during - * EOF (cmDependsFortran_yywrap()) processing, but the only time this flag - * is looked at is after cmDependsFortran_yywrap() is called, so it's safe + * EOF (cmFortran_yywrap()) processing, but the only time this flag + * is looked at is after cmFortran_yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } -static void cmDependsFortran_yy_load_buffer_state (yyscan_t yyscanner) +static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; @@ -1761,35 +1761,35 @@ static void cmDependsFortran_yy_load_buffer_state (yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the allocated buffer state. */ - YY_BUFFER_STATE cmDependsFortran_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) + YY_BUFFER_STATE cmFortran_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; - b = (YY_BUFFER_STATE) cmDependsFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) cmFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yy_create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) cmDependsFortran_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + b->yy_ch_buf = (char *) cmFortran_yyalloc(b->yy_buf_size + 2 ,yyscanner ); if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yy_create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_create_buffer()" ); b->yy_is_our_buffer = 1; - cmDependsFortran_yy_init_buffer(b,file ,yyscanner); + cmFortran_yy_init_buffer(b,file ,yyscanner); return b; } /** Destroy the buffer. - * @param b a buffer created with cmDependsFortran_yy_create_buffer() + * @param b a buffer created with cmFortran_yy_create_buffer() * @param yyscanner The scanner object. */ - void cmDependsFortran_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void cmFortran_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -1800,9 +1800,9 @@ static void cmDependsFortran_yy_load_buffer_state (yyscan_t yyscanner) YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - cmDependsFortran_yyfree((void *) b->yy_ch_buf ,yyscanner ); + cmFortran_yyfree((void *) b->yy_ch_buf ,yyscanner ); - cmDependsFortran_yyfree((void *) b ,yyscanner ); + cmFortran_yyfree((void *) b ,yyscanner ); } #ifndef __cplusplus @@ -1811,21 +1811,21 @@ extern int isatty (int ); /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, - * such as during a cmDependsFortran_yyrestart() or at EOF. + * such as during a cmFortran_yyrestart() or at EOF. */ - static void cmDependsFortran_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + static void cmFortran_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - cmDependsFortran_yy_flush_buffer(b ,yyscanner); + cmFortran_yy_flush_buffer(b ,yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; - /* If b is the current buffer, then cmDependsFortran_yy_init_buffer was _probably_ - * called from cmDependsFortran_yyrestart() or through yy_get_next_buffer. + /* If b is the current buffer, then cmFortran_yy_init_buffer was _probably_ + * called from cmFortran_yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ @@ -1842,7 +1842,7 @@ extern int isatty (int ); * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ - void cmDependsFortran_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void cmFortran_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) @@ -1863,7 +1863,7 @@ extern int isatty (int ); b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) - cmDependsFortran_yy_load_buffer_state(yyscanner ); + cmFortran_yy_load_buffer_state(yyscanner ); } /** Pushes the new state onto the stack. The new state becomes @@ -1872,15 +1872,15 @@ extern int isatty (int ); * @param new_buffer The new state. * @param yyscanner The scanner object. */ -void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; - cmDependsFortran_yyensure_buffer_stack(yyscanner); + cmFortran_yyensure_buffer_stack(yyscanner); - /* This block is copied from cmDependsFortran_yy_switch_to_buffer. */ + /* This block is copied from cmFortran_yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ @@ -1894,8 +1894,8 @@ void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; - /* copied from cmDependsFortran_yy_switch_to_buffer. */ - cmDependsFortran_yy_load_buffer_state(yyscanner ); + /* copied from cmFortran_yy_switch_to_buffer. */ + cmFortran_yy_load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } @@ -1903,19 +1903,19 @@ void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t * The next element becomes the new top. * @param yyscanner The scanner object. */ -void cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner) +void cmFortran_yypop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; - cmDependsFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + cmFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { - cmDependsFortran_yy_load_buffer_state(yyscanner ); + cmFortran_yy_load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } @@ -1923,7 +1923,7 @@ void cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner) /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ -static void cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner) +static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner) { int num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -1935,11 +1935,11 @@ static void cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner) * immediate realloc on the next call. */ num_to_alloc = 1; - yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsFortran_yyalloc + yyg->yy_buffer_stack = (struct yy_buffer_state**)cmFortran_yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yyensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yyensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); @@ -1954,12 +1954,12 @@ static void cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner) int grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsFortran_yyrealloc + yyg->yy_buffer_stack = (struct yy_buffer_state**)cmFortran_yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yyensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); @@ -1973,7 +1973,7 @@ static void cmDependsFortran_yyensure_buffer_stack (yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +YY_BUFFER_STATE cmFortran_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; @@ -1983,9 +1983,9 @@ YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char * base, yy_size_t size , /* They forgot to leave room for the EOB's. */ return 0; - b = (YY_BUFFER_STATE) cmDependsFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) cmFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yy_scan_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; @@ -1997,33 +1997,33 @@ YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char * base, yy_size_t size , b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - cmDependsFortran_yy_switch_to_buffer(b ,yyscanner ); + cmFortran_yy_switch_to_buffer(b ,yyscanner ); return b; } -/** Setup the input buffer state to scan a string. The next call to cmDependsFortran_yylex() will +/** Setup the input buffer state to scan a string. The next call to cmFortran_yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use - * cmDependsFortran_yy_scan_bytes() instead. + * cmFortran_yy_scan_bytes() instead. */ -YY_BUFFER_STATE cmDependsFortran_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +YY_BUFFER_STATE cmFortran_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) { - return cmDependsFortran_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); + return cmFortran_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); } -/** Setup the input buffer state to scan the given bytes. The next call to cmDependsFortran_yylex() will +/** Setup the input buffer state to scan the given bytes. The next call to cmFortran_yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE cmDependsFortran_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; @@ -2032,18 +2032,18 @@ YY_BUFFER_STATE cmDependsFortran_yy_scan_bytes (yyconst char * yybytes, int _y /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; - buf = (char *) cmDependsFortran_yyalloc(n ,yyscanner ); + buf = (char *) cmFortran_yyalloc(n ,yyscanner ); if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in cmDependsFortran_yy_scan_bytes()" ); + YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = cmDependsFortran_yy_scan_buffer(buf,n ,yyscanner); + b = cmFortran_yy_scan_buffer(buf,n ,yyscanner); if ( ! b ) - YY_FATAL_ERROR( "bad buffer in cmDependsFortran_yy_scan_bytes()" ); + YY_FATAL_ERROR( "bad buffer in cmFortran_yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -2085,7 +2085,7 @@ static void yy_fatal_error (yyconst char* msg , yyscan_t) /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ -YY_EXTRA_TYPE cmDependsFortran_yyget_extra (yyscan_t yyscanner) +YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; @@ -2094,7 +2094,7 @@ YY_EXTRA_TYPE cmDependsFortran_yyget_extra (yyscan_t yyscanner) /** Get the current line number. * @param yyscanner The scanner object. */ -int cmDependsFortran_yyget_lineno (yyscan_t yyscanner) +int cmFortran_yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -2107,7 +2107,7 @@ int cmDependsFortran_yyget_lineno (yyscan_t yyscanner) /** Get the current column number. * @param yyscanner The scanner object. */ -int cmDependsFortran_yyget_column (yyscan_t yyscanner) +int cmFortran_yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -2120,7 +2120,7 @@ int cmDependsFortran_yyget_column (yyscan_t yyscanner) /** Get the input stream. * @param yyscanner The scanner object. */ -FILE *cmDependsFortran_yyget_in (yyscan_t yyscanner) +FILE *cmFortran_yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; @@ -2129,7 +2129,7 @@ FILE *cmDependsFortran_yyget_in (yyscan_t yyscanner) /** Get the output stream. * @param yyscanner The scanner object. */ -FILE *cmDependsFortran_yyget_out (yyscan_t yyscanner) +FILE *cmFortran_yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; @@ -2138,7 +2138,7 @@ FILE *cmDependsFortran_yyget_out (yyscan_t yyscanner) /** Get the length of the current token. * @param yyscanner The scanner object. */ -int cmDependsFortran_yyget_leng (yyscan_t yyscanner) +int cmFortran_yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; @@ -2148,7 +2148,7 @@ int cmDependsFortran_yyget_leng (yyscan_t yyscanner) * @param yyscanner The scanner object. */ -char *cmDependsFortran_yyget_text (yyscan_t yyscanner) +char *cmFortran_yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; @@ -2158,7 +2158,7 @@ char *cmDependsFortran_yyget_text (yyscan_t yyscanner) * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ -void cmDependsFortran_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; @@ -2168,13 +2168,13 @@ void cmDependsFortran_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscan * @param line_number The line number to set. * @param yyscanner The scanner object. */ -void cmDependsFortran_yyset_lineno (int line_number , yyscan_t yyscanner) +void cmFortran_yyset_lineno (int line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "cmDependsFortran_yyset_lineno called with no buffer" , yyscanner); + yy_fatal_error( "cmFortran_yyset_lineno called with no buffer" , yyscanner); yylineno = line_number; } @@ -2183,13 +2183,13 @@ void cmDependsFortran_yyset_lineno (int line_number , yyscan_t yyscanner) * @param column_no The column number to set. * @param yyscanner The scanner object. */ -void cmDependsFortran_yyset_column (int column_no , yyscan_t yyscanner) +void cmFortran_yyset_column (int column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "cmDependsFortran_yyset_column called with no buffer" , yyscanner); + yy_fatal_error( "cmFortran_yyset_column called with no buffer" , yyscanner); yycolumn = column_no; } @@ -2198,27 +2198,27 @@ void cmDependsFortran_yyset_column (int column_no , yyscan_t yyscanner) * input buffer. * @param in_str A readable stream. * @param yyscanner The scanner object. - * @see cmDependsFortran_yy_switch_to_buffer + * @see cmFortran_yy_switch_to_buffer */ -void cmDependsFortran_yyset_in (FILE * in_str , yyscan_t yyscanner) +void cmFortran_yyset_in (FILE * in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = in_str ; } -void cmDependsFortran_yyset_out (FILE * out_str , yyscan_t yyscanner) +void cmFortran_yyset_out (FILE * out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = out_str ; } -int cmDependsFortran_yyget_debug (yyscan_t yyscanner) +int cmFortran_yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } -void cmDependsFortran_yyset_debug (int bdebug , yyscan_t yyscanner) +void cmFortran_yyset_debug (int bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = bdebug ; @@ -2228,12 +2228,12 @@ void cmDependsFortran_yyset_debug (int bdebug , yyscan_t yyscanner) /* User-visible API */ -/* cmDependsFortran_yylex_init is special because it creates the scanner itself, so it is +/* cmFortran_yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ -int cmDependsFortran_yylex_init(yyscan_t* ptr_yy_globals) +int cmFortran_yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ @@ -2241,7 +2241,7 @@ int cmDependsFortran_yylex_init(yyscan_t* ptr_yy_globals) return 1; } - *ptr_yy_globals = (yyscan_t) cmDependsFortran_yyalloc ( sizeof( struct yyguts_t ), NULL ); + *ptr_yy_globals = (yyscan_t) cmFortran_yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; @@ -2254,27 +2254,27 @@ int cmDependsFortran_yylex_init(yyscan_t* ptr_yy_globals) return yy_init_globals ( *ptr_yy_globals ); } -/* cmDependsFortran_yylex_init_extra has the same functionality as cmDependsFortran_yylex_init, but follows the +/* cmFortran_yylex_init_extra has the same functionality as cmFortran_yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to cmDependsFortran_yyalloc in + * The user defined value in the first argument will be available to cmFortran_yyalloc in * the yyextra field. */ -int cmDependsFortran_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) +int cmFortran_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; - cmDependsFortran_yyset_extra (yy_user_defined, &dummy_yyguts); + cmFortran_yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } - *ptr_yy_globals = (yyscan_t) cmDependsFortran_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + *ptr_yy_globals = (yyscan_t) cmFortran_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; @@ -2285,7 +2285,7 @@ int cmDependsFortran_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* pt yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - cmDependsFortran_yyset_extra (yy_user_defined, *ptr_yy_globals); + cmFortran_yyset_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } @@ -2294,7 +2294,7 @@ static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. - * This function is called from cmDependsFortran_yylex_destroy(), so don't allocate here. + * This function is called from cmFortran_yylex_destroy(), so don't allocate here. */ yyg->yy_buffer_stack = 0; @@ -2318,37 +2318,37 @@ static int yy_init_globals (yyscan_t yyscanner) #endif /* For future reference: Set errno on error, since we are called by - * cmDependsFortran_yylex_init() + * cmFortran_yylex_init() */ return 0; } -/* cmDependsFortran_yylex_destroy is for both reentrant and non-reentrant scanners. */ -int cmDependsFortran_yylex_destroy (yyscan_t yyscanner) +/* cmFortran_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int cmFortran_yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ - cmDependsFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + cmFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; - cmDependsFortran_yypop_buffer_state(yyscanner); + cmFortran_yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ - cmDependsFortran_yyfree(yyg->yy_buffer_stack ,yyscanner); + cmFortran_yyfree(yyg->yy_buffer_stack ,yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ - cmDependsFortran_yyfree(yyg->yy_start_stack ,yyscanner ); + cmFortran_yyfree(yyg->yy_start_stack ,yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time - * cmDependsFortran_yylex() is called, initialization will occur. */ + * cmFortran_yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ - cmDependsFortran_yyfree ( yyscanner , yyscanner ); + cmFortran_yyfree ( yyscanner , yyscanner ); return 0; } @@ -2376,12 +2376,12 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) } #endif -void *cmDependsFortran_yyalloc (yy_size_t size , yyscan_t) +void *cmFortran_yyalloc (yy_size_t size , yyscan_t) { return (void *) malloc( size ); } -void *cmDependsFortran_yyrealloc (void * ptr, yy_size_t size , yyscan_t) +void *cmFortran_yyrealloc (void * ptr, yy_size_t size , yyscan_t) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those @@ -2393,22 +2393,21 @@ void *cmDependsFortran_yyrealloc (void * ptr, yy_size_t size , yyscan_t) return (void *) realloc( (char *) ptr, size ); } -void cmDependsFortran_yyfree (void * ptr , yyscan_t) +void cmFortran_yyfree (void * ptr , yyscan_t) { - free( (char *) ptr ); /* see cmDependsFortran_yyrealloc() for (char *) cast */ + free( (char *) ptr ); /* see cmFortran_yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" -#line 181 "cmDependsFortranLexer.in.l" +#line 181 "cmFortranLexer.in.l" /*--------------------------------------------------------------------------*/ -YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) +YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) { /* Hack into the internal flex-generated scanner to get the buffer. */ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return YY_CURRENT_BUFFER; } - diff --git a/Source/cmDependsFortranLexer.h b/Source/cmFortranLexer.h index 8e24cfd..c67e332 100644 --- a/Source/cmDependsFortranLexer.h +++ b/Source/cmFortranLexer.h @@ -9,9 +9,9 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ -#ifndef cmDependsFortran_yyHEADER_H -#define cmDependsFortran_yyHEADER_H 1 -#define cmDependsFortran_yyIN_HEADER 1 +#ifndef cmFortran_yyHEADER_H +#define cmFortran_yyHEADER_H 1 +#define cmFortran_yyIN_HEADER 1 #define YY_INT_ALIGNED short int @@ -211,25 +211,25 @@ struct yy_buffer_state }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ -void cmDependsFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner ); -void cmDependsFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void cmDependsFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void cmDependsFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void cmDependsFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void cmDependsFortran_yypop_buffer_state (yyscan_t yyscanner ); +void cmFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void cmFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void cmFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void cmFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void cmFortran_yypop_buffer_state (yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE cmDependsFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); -void *cmDependsFortran_yyalloc (yy_size_t ,yyscan_t yyscanner ); -void *cmDependsFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); -void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner ); +void *cmFortran_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *cmFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void cmFortran_yyfree (void * ,yyscan_t yyscanner ); /* Begin user sect3 */ -#define cmDependsFortran_yywrap(n) 1 +#define cmFortran_yywrap(n) 1 #define YY_SKIP_YYWRAP #define yytext_ptr yytext_r @@ -247,38 +247,38 @@ void cmDependsFortran_yyfree (void * ,yyscan_t yyscanner ); #define YY_EXTRA_TYPE void * #endif -int cmDependsFortran_yylex_init (yyscan_t* scanner); +int cmFortran_yylex_init (yyscan_t* scanner); -int cmDependsFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); +int cmFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int cmDependsFortran_yylex_destroy (yyscan_t yyscanner ); +int cmFortran_yylex_destroy (yyscan_t yyscanner ); -int cmDependsFortran_yyget_debug (yyscan_t yyscanner ); +int cmFortran_yyget_debug (yyscan_t yyscanner ); -void cmDependsFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner ); +void cmFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner ); -YY_EXTRA_TYPE cmDependsFortran_yyget_extra (yyscan_t yyscanner ); +YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner ); -void cmDependsFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); +void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); -FILE *cmDependsFortran_yyget_in (yyscan_t yyscanner ); +FILE *cmFortran_yyget_in (yyscan_t yyscanner ); -void cmDependsFortran_yyset_in (FILE * in_str ,yyscan_t yyscanner ); +void cmFortran_yyset_in (FILE * in_str ,yyscan_t yyscanner ); -FILE *cmDependsFortran_yyget_out (yyscan_t yyscanner ); +FILE *cmFortran_yyget_out (yyscan_t yyscanner ); -void cmDependsFortran_yyset_out (FILE * out_str ,yyscan_t yyscanner ); +void cmFortran_yyset_out (FILE * out_str ,yyscan_t yyscanner ); -int cmDependsFortran_yyget_leng (yyscan_t yyscanner ); +int cmFortran_yyget_leng (yyscan_t yyscanner ); -char *cmDependsFortran_yyget_text (yyscan_t yyscanner ); +char *cmFortran_yyget_text (yyscan_t yyscanner ); -int cmDependsFortran_yyget_lineno (yyscan_t yyscanner ); +int cmFortran_yyget_lineno (yyscan_t yyscanner ); -void cmDependsFortran_yyset_lineno (int line_number ,yyscan_t yyscanner ); +void cmFortran_yyset_lineno (int line_number ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -286,9 +286,9 @@ void cmDependsFortran_yyset_lineno (int line_number ,yyscan_t yyscanner ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int cmDependsFortran_yywrap (yyscan_t yyscanner ); +extern "C" int cmFortran_yywrap (yyscan_t yyscanner ); #else -extern int cmDependsFortran_yywrap (yyscan_t yyscanner ); +extern int cmFortran_yywrap (yyscan_t yyscanner ); #endif #endif @@ -325,9 +325,9 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); #ifndef YY_DECL #define YY_DECL_IS_OURS 1 -extern int cmDependsFortran_yylex (yyscan_t yyscanner); +extern int cmFortran_yylex (yyscan_t yyscanner); -#define YY_DECL int cmDependsFortran_yylex (yyscan_t yyscanner) +#define YY_DECL int cmFortran_yylex (yyscan_t yyscanner) #endif /* !YY_DECL */ /* yy_get_previous_state - get the state just before the EOB char was reached */ @@ -344,5 +344,5 @@ extern int cmDependsFortran_yylex (yyscan_t yyscanner); #undef YY_DECL #endif -#undef cmDependsFortran_yyIN_HEADER -#endif /* cmDependsFortran_yyHEADER_H */ +#undef cmFortran_yyIN_HEADER +#endif /* cmFortran_yyHEADER_H */ diff --git a/Source/cmDependsFortranLexer.in.l b/Source/cmFortranLexer.in.l index 0148802..03fa90c 100644 --- a/Source/cmDependsFortranLexer.in.l +++ b/Source/cmFortranLexer.in.l @@ -26,18 +26,18 @@ This file must be translated to C and modified to build everywhere. Run flex like this: - flex -i --prefix=cmDependsFortran_yy --header-file=cmDependsFortranLexer.h -ocmDependsFortranLexer.cxx cmDependsFortranLexer.in.l + flex -i --prefix=cmFortran_yy --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l -Modify cmDependsFortranLexer.cxx: +Modify cmFortranLexer.cxx: - remove TABs - remove use of the 'register' storage class specifier - remove "yyscanner" argument from these methods: - yy_fatal_error, cmDependsFortran_yyalloc, cmDependsFortran_yyrealloc, cmDependsFortran_yyfree - - remove "yyscanner = NULL" from end of cmDependsFortran_yylex_destroy + yy_fatal_error, cmFortran_yyalloc, cmFortran_yyrealloc, cmFortran_yyfree + - remove "yyscanner = NULL" from end of cmFortran_yylex_destroy - remove all YY_BREAK lines occurring right after return statements - change while ( 1 ) to for(;;) -Modify cmDependsFortranLexer.h: +Modify cmFortranLexer.h: - remove TABs - remove the yy_init_globals function - remove the block that includes unistd.h @@ -47,16 +47,16 @@ Modify cmDependsFortranLexer.h: #include "cmStandardLexer.h" -#define cmDependsFortranLexer_cxx -#include "cmDependsFortranParser.h" /* Interface to parser object. */ +#define cmFortranLexer_cxx +#include "cmFortranParser.h" /* Interface to parser object. */ /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmDependsFortranParser_Input(yyextra, buf, max_size); } + { result = cmFortranParser_Input(yyextra, buf, max_size); } /* Include the set of tokens from the parser. */ -#include "cmDependsFortranParserTokens.h" +#include "cmFortranParserTokens.h" /*--------------------------------------------------------------------------*/ %} @@ -72,21 +72,21 @@ Modify cmDependsFortranLexer.h: %% \" { - cmDependsFortranParser_StringStart(yyextra); - cmDependsFortranParser_SetOldStartcond(yyextra, YY_START); + cmFortranParser_StringStart(yyextra); + cmFortranParser_SetOldStartcond(yyextra, YY_START); BEGIN(str_dq); } ' { - cmDependsFortranParser_StringStart(yyextra); - cmDependsFortranParser_SetOldStartcond(yyextra, YY_START); + cmFortranParser_StringStart(yyextra); + cmFortranParser_SetOldStartcond(yyextra, YY_START); BEGIN(str_sq); } <str_dq>\" | <str_sq>' { - BEGIN(cmDependsFortranParser_GetOldStartcond(yyextra) ); - yylvalp->string = strdup(cmDependsFortranParser_StringEnd(yyextra)); + BEGIN(cmFortranParser_GetOldStartcond(yyextra) ); + yylvalp->string = strdup(cmFortranParser_StringEnd(yyextra)); return STRING; } @@ -94,7 +94,7 @@ Modify cmDependsFortranLexer.h: <str_dq,str_sq>&[ \t]*\n[ \t]*& /* Ignore (continued strings, free fmt) */ <fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] { - if (cmDependsFortranParser_GetOldStartcond(yyextra) == fixed_fmt) + if (cmFortranParser_GetOldStartcond(yyextra) == fixed_fmt) ; /* Ignore (cont. strings, fixed fmt) */ else { @@ -110,7 +110,7 @@ Modify cmDependsFortranLexer.h: } <str_sq,str_dq>. { - cmDependsFortranParser_StringAppend(yyextra, yytext[0]); + cmFortranParser_StringAppend(yyextra, yytext[0]); } !.*\n { return EOSTMT; } /* Treat comments like */ @@ -173,7 +173,7 @@ $[ \t]*endif { return F90PPR_ENDIF; } . { return *yytext; } <<EOF>> { - if(!cmDependsFortranParser_FilePop(yyextra) ) + if(!cmFortranParser_FilePop(yyextra) ) { return YY_NULL; } @@ -182,7 +182,7 @@ $[ \t]*endif { return F90PPR_ENDIF; } %% /*--------------------------------------------------------------------------*/ -YY_BUFFER_STATE cmDependsFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) +YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) { /* Hack into the internal flex-generated scanner to get the buffer. */ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; diff --git a/Source/cmDependsFortranParser.cxx b/Source/cmFortranParser.cxx index 9d51025..0230f02 100644 --- a/Source/cmDependsFortranParser.cxx +++ b/Source/cmFortranParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 3.0.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "3.0.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -58,23 +58,17 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ -#define yyparse cmDependsFortran_yyparse -#define yylex cmDependsFortran_yylex -#define yyerror cmDependsFortran_yyerror -#define yylval cmDependsFortran_yylval -#define yychar cmDependsFortran_yychar -#define yydebug cmDependsFortran_yydebug -#define yynerrs cmDependsFortran_yynerrs +#define yyparse cmFortran_yyparse +#define yylex cmFortran_yylex +#define yyerror cmFortran_yyerror +#define yydebug cmFortran_yydebug +#define yynerrs cmFortran_yynerrs /* Copy the first part of user declarations. */ - -/* Line 268 of yacc.c */ -#line 1 "cmDependsFortranParser.y" +#line 1 "cmFortranParser.y" /* yacc.c:339 */ /*============================================================================ CMake - Cross Platform Makefile Generator @@ -103,41 +97,33 @@ This file must be translated to C and modified to build everywhere. Run bison like this: - bison --yacc --name-prefix=cmDependsFortran_yy - --defines=cmDependsFortranParserTokens.h - -ocmDependsFortranParser.cxx - cmDependsFortranParser.y + bison --yacc --name-prefix=cmFortran_yy + --defines=cmFortranParserTokens.h + -ocmFortranParser.cxx + cmFortranParser.y -Modify cmDependsFortranParser.cxx: - - remove TABs - - Remove the yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] +Modify cmFortranParser.cxx: + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ /*-------------------------------------------------------------------------*/ -#define cmDependsFortranParser_cxx -#include "cmDependsFortranParser.h" /* Interface to parser object. */ -#include "cmDependsFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ +#define cmFortranParser_cxx +#include "cmFortranParser.h" /* Interface to parser object. */ +#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ #include <cmsys/String.h> -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmDependsFortran_yyerror(x) \ - cmDependsFortranError(yyscanner, x) - /* Forward declare the lexer entry point. */ YY_DECL; -/* Helper function to forward error callback. */ -static void cmDependsFortranError(yyscan_t yyscanner, const char* message) +/* Helper function to forward error callback from parser. */ +static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_Error(parser, message); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_Error(parser, message); } -static bool cmDependsFortranParserIsKeyword(const char* word, +static bool cmFortranParserIsKeyword(const char* word, const char* keyword) { return cmsysString_strcasecmp(word, keyword) == 0; @@ -153,65 +139,71 @@ static bool cmDependsFortranParserIsKeyword(const char* word, # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */ #endif +#line 143 "cmFortranParser.cxx" /* yacc.c:339 */ -/* Line 268 of yacc.c */ -#line 165 "cmDependsFortranParser.cxx" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else -# define YYERROR_VERBOSE 0 +# define YYERROR_VERBOSE 1 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "cmFortranParserTokens.h". */ +#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED +# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int cmFortran_yydebug; #endif - -/* Tokens. */ +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - EOSTMT = 258, - ASSIGNMENT_OP = 259, - GARBAGE = 260, - CPP_INCLUDE = 261, - F90PPR_INCLUDE = 262, - COCO_INCLUDE = 263, - F90PPR_DEFINE = 264, - CPP_DEFINE = 265, - F90PPR_UNDEF = 266, - CPP_UNDEF = 267, - CPP_IFDEF = 268, - CPP_IFNDEF = 269, - CPP_IF = 270, - CPP_ELSE = 271, - CPP_ELIF = 272, - CPP_ENDIF = 273, - F90PPR_IFDEF = 274, - F90PPR_IFNDEF = 275, - F90PPR_IF = 276, - F90PPR_ELSE = 277, - F90PPR_ELIF = 278, - F90PPR_ENDIF = 279, - COMMA = 280, - DCOLON = 281, - CPP_TOENDL = 282, - UNTERMINATED_STRING = 283, - STRING = 284, - WORD = 285, - CPP_INCLUDE_ANGLE = 286 - }; + enum yytokentype + { + EOSTMT = 258, + ASSIGNMENT_OP = 259, + GARBAGE = 260, + CPP_INCLUDE = 261, + F90PPR_INCLUDE = 262, + COCO_INCLUDE = 263, + F90PPR_DEFINE = 264, + CPP_DEFINE = 265, + F90PPR_UNDEF = 266, + CPP_UNDEF = 267, + CPP_IFDEF = 268, + CPP_IFNDEF = 269, + CPP_IF = 270, + CPP_ELSE = 271, + CPP_ELIF = 272, + CPP_ENDIF = 273, + F90PPR_IFDEF = 274, + F90PPR_IFNDEF = 275, + F90PPR_IF = 276, + F90PPR_ELSE = 277, + F90PPR_ELIF = 278, + F90PPR_ENDIF = 279, + COMMA = 280, + DCOLON = 281, + CPP_TOENDL = 282, + UNTERMINATED_STRING = 283, + STRING = 284, + WORD = 285, + CPP_INCLUDE_ANGLE = 286 + }; #endif /* Tokens. */ #define EOSTMT 258 @@ -244,34 +236,30 @@ static bool cmDependsFortranParserIsKeyword(const char* word, #define WORD 285 #define CPP_INCLUDE_ANGLE 286 - - - +/* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE +typedef union YYSTYPE YYSTYPE; +union YYSTYPE { - -/* Line 293 of yacc.c */ -#line 89 "cmDependsFortranParser.y" +#line 81 "cmFortranParser.y" /* yacc.c:355 */ char* string; - - -/* Line 293 of yacc.c */ -#line 269 "cmDependsFortranParser.cxx" -} YYSTYPE; +#line 249 "cmFortranParser.cxx" /* yacc.c:355 */ +}; # define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif -/* Copy the second part of user declarations. */ +int cmFortran_yyparse (yyscan_t yyscanner); -/* Line 343 of yacc.c */ -#line 281 "cmDependsFortranParser.cxx" +#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 263 "cmFortranParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -285,11 +273,8 @@ typedef unsigned char yytype_uint8; #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; #else -typedef short int yytype_int8; +typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 @@ -309,8 +294,7 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# elif ! defined YYSIZE_T # include <stddef.h> /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else @@ -324,38 +308,67 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include <libintl.h> /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") #else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; +# define YY_INITIAL_VALUE(Value) Value #endif -{ - return yyi; -} +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + #if ! defined yyoverflow || YYERROR_VERBOSE @@ -374,9 +387,9 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif @@ -386,8 +399,8 @@ YYID (yyi) # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely @@ -411,15 +424,13 @@ YYID (yyi) # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif @@ -463,26 +474,26 @@ union yyalloc yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ - while (YYID (0)) + while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from FROM to TO. The source and destination do +/* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else -# define YYCOPY(To, From, Count) \ +# define YYCOPY(Dst, Src, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ + (Dst)[yyi] = (Src)[yyi]; \ } \ - while (YYID (0)) + while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ @@ -498,17 +509,19 @@ union yyalloc #define YYNNTS 16 /* YYNRULES -- Number of rules. */ #define YYNRULES 53 -/* YYNRULES -- Number of states. */ +/* YYNSTATES -- Number of states. */ #define YYNSTATES 97 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 286 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -543,52 +556,19 @@ static const yytype_uint8 yytranslate[] = }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint8 yyprhs[] = -{ - 0, 0, 3, 4, 7, 9, 11, 16, 19, 24, - 30, 38, 43, 47, 52, 57, 62, 67, 72, 76, - 80, 84, 88, 93, 97, 99, 101, 103, 105, 107, - 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, - 129, 131, 133, 135, 137, 139, 140, 143, 145, 147, - 149, 151, 153, 155 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 33, 0, -1, -1, 33, 34, -1, 36, -1, 35, - -1, 30, 4, 46, 3, -1, 30, 3, -1, 30, - 30, 46, 3, -1, 30, 26, 30, 46, 3, -1, - 30, 25, 30, 26, 30, 46, 3, -1, 30, 29, - 46, 3, -1, 31, 46, 3, -1, 37, 29, 46, - 3, -1, 38, 30, 46, 3, -1, 39, 30, 46, - 3, -1, 40, 30, 46, 3, -1, 41, 30, 46, - 3, -1, 42, 46, 3, -1, 43, 46, 3, -1, - 44, 46, 3, -1, 45, 46, 3, -1, 30, 5, - 46, 3, -1, 5, 46, 3, -1, 3, -1, 1, - -1, 6, -1, 7, -1, 8, -1, 10, -1, 9, - -1, 12, -1, 11, -1, 13, -1, 19, -1, 14, - -1, 20, -1, 15, -1, 21, -1, 17, -1, 23, - -1, 16, -1, 22, -1, 18, -1, 24, -1, -1, - 46, 47, -1, 30, -1, 29, -1, 5, -1, 4, - -1, 26, -1, 25, -1, 28, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 111, 111, 111, 113, 113, 115, 121, 131, 161, - 172, 185, 196, 203, 210, 216, 222, 228, 234, 239, - 244, 249, 254, 258, 259, 260, 265, 265, 265, 266, - 266, 267, 267, 268, 268, 269, 269, 270, 270, 271, - 271, 272, 272, 273, 273, 274, 274, 277, 278, 279, - 280, 281, 282, 283 + 0, 103, 103, 103, 105, 105, 107, 113, 123, 153, + 164, 177, 188, 195, 202, 208, 214, 220, 226, 231, + 236, 241, 246, 250, 251, 252, 257, 257, 257, 258, + 258, 259, 259, 260, 260, 261, 261, 262, 262, 263, + 263, 264, 264, 265, 265, 266, 266, 269, 270, 271, + 272, 273, 274, 275 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 1 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -601,13 +581,13 @@ static const char *const yytname[] = "F90PPR_ENDIF", "COMMA", "DCOLON", "CPP_TOENDL", "UNTERMINATED_STRING", "STRING", "WORD", "CPP_INCLUDE_ANGLE", "$accept", "code", "stmt", "assignment_stmt", "keyword_stmt", "include", "define", "undef", "ifdef", - "ifndef", "if", "elif", "else", "endif", "other", "misc_code", 0 + "ifndef", "if", "elif", "else", "endif", "other", "misc_code", YY_NULLPTR }; #endif # ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, @@ -617,31 +597,35 @@ static const yytype_uint16 yytoknum[] = }; # endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 32, 33, 33, 34, 34, 35, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 37, 37, 37, 38, - 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, - 43, 44, 44, 45, 45, 46, 46, 47, 47, 47, - 47, 47, 47, 47 -}; +#define YYPACT_NINF -29 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-29))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = { - 0, 2, 0, 2, 1, 1, 4, 2, 4, 5, - 7, 4, 3, 4, 4, 4, 4, 4, 3, 3, - 3, 3, 4, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, - 1, 1, 1, 1 + -29, 39, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, 246, -29, -29, -29, -29, + -28, -27, -22, -17, -16, -29, -29, -29, -29, 2, + -29, -29, -29, -13, -12, -29, -29, 61, -29, -29, + -29, -29, -29, 68, 74, 80, 108, -29, -29, -29, + -29, -29, -29, -29, -29, -29, 114, 120, -24, -29, + 126, 154, -29, 160, 166, 172, 200, 206, -29, -29, + -29, -29, -29, -29, -9, 212, -29, -29, -29, -29, + -29, -29, -29, -29, -29, 218, -29 }; -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 0, 1, 25, 24, 45, 26, 27, 28, 30, @@ -656,41 +640,23 @@ static const yytype_uint8 yydefact[] = 15, 16, 17, 45, 9, 0, 10 }; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int8 yydefgoto[] = -{ - -1, 1, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 65 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -29 -static const yytype_int16 yypact[] = + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = { - -29, 39, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, -29, -29, 246, -29, -29, -29, -29, - -28, -27, -22, -17, -16, -29, -29, -29, -29, 2, - -29, -29, -29, -13, -12, -29, -29, 61, -29, -29, - -29, -29, -29, 68, 74, 80, 108, -29, -29, -29, - -29, -29, -29, -29, -29, -29, 114, 120, -24, -29, - 126, 154, -29, 160, 166, 172, 200, 206, -29, -29, - -29, -29, -29, -29, -9, 212, -29, -29, -29, -29, - -29, -29, -29, -29, -29, 218, -29 + -29, -29, -29, -29, -26, -29 }; -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { - -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, -29, -26, -29 + -1, 1, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 65 }; -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1 + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { 47, 48, 84, 49, 0, 57, 58, 59, 50, 53, @@ -723,12 +689,6 @@ static const yytype_uint8 yytable[] = 0, 43, 44, 0, 0, 45, 46 }; -#define yypact_value_is_default(yystate) \ - ((yystate) == (-29)) - -#define yytable_value_is_error(yytable_value) \ - YYID (0) - static const yytype_int8 yycheck[] = { 26, 29, 26, 30, -1, 3, 4, 5, 30, 35, @@ -761,8 +721,8 @@ static const yytype_int8 yycheck[] = -1, 25, 26, -1, -1, 29, 30 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 33, 0, 1, 3, 5, 6, 7, 8, 9, @@ -777,6 +737,29 @@ static const yytype_uint8 yystos[] = 3, 3, 3, 30, 3, 46, 3 }; + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 32, 33, 33, 34, 34, 35, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 37, 37, 37, 38, + 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, + 43, 44, 44, 45, 45, 46, 46, 47, 47, 47, + 47, 47, 47, 47 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 2, 1, 1, 4, 2, 4, 5, + 7, 4, 3, 4, 4, 4, 4, 4, 3, 3, + 3, 3, 4, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, + 1, 1, 1, 1 +}; + + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) @@ -787,84 +770,30 @@ static const yytype_uint8 yystos[] = #define YYERROR goto yyerrorlab -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ - -#define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif - #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ - if (yychar == YYEMPTY && yylen == 1) \ + if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ - YYPOPSTACK (1); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ - yyerror (YY_("syntax error: cannot back up")); \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ -while (YYID (0)) - +while (0) +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* This macro is provided for backward compatibility. */ - -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval) -#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -878,7 +807,13 @@ while (YYID (0)) do { \ if (yydebug) \ YYFPRINTF Args; \ -} while (YYID (0)) +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ @@ -886,42 +821,29 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value); \ + Type, Value, yyscanner); \ YYFPRINTF (stderr, "\n"); \ } \ -} while (YYID (0)) +} while (0) -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); # endif - switch (yytype) - { - default: - break; - } + YYUSE (yytype); } @@ -929,24 +851,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) | Print this symbol on YYOUTPUT. | `--------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); YYFPRINTF (yyoutput, ")"); } @@ -955,16 +866,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) | TOP (included). | `------------------------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) @@ -979,36 +882,29 @@ yy_stack_print (yybottom, yytop) do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) +} while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { + unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) - ); + , yyscanner); YYFPRINTF (stderr, "\n"); } } @@ -1016,8 +912,8 @@ yy_reduce_print (yyvsp, yyrule) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) + yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \ +} while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -1054,15 +950,8 @@ int yydebug; # define yystrlen strlen # else /* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) @@ -1078,16 +967,8 @@ yystrlen (yystr) # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif { char *yyd = yydest; const char *yys = yysrc; @@ -1160,12 +1041,11 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = 0; + const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -1173,10 +1053,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, int yycount = 0; /* There are many possibilities here to consider: - - Assume YYFAIL is not used. It's too flawed to consider. See - <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html> - for details. YYERROR is fine as it does not invoke this - function. - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected @@ -1225,11 +1101,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, break; } yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } } } } @@ -1249,10 +1127,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, # undef YYCASE_ } - yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } if (*yymsg_alloc < yysize) { @@ -1289,81 +1169,39 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, | Release the memory associated to this symbol. | `-----------------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner) { YYUSE (yyvaluep); - + YYUSE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ /*----------. | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else int -yyparse () - -#endif -#endif +yyparse (yyscan_t yyscanner) { /* The lookahead symbol. */ int yychar; + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); /* Number of syntax errors so far. */ int yynerrs; @@ -1373,10 +1211,10 @@ YYSTYPE yylval; int yyerrstatus; /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. + 'yyss': related to states. + 'yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1394,7 +1232,7 @@ YYSTYPE yylval; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; @@ -1412,9 +1250,8 @@ YYSTYPE yylval; Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1423,14 +1260,6 @@ YYSTYPE yylval; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - goto yysetstate; /*------------------------------------------------------------. @@ -1531,7 +1360,7 @@ yybackup: if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + yychar = yylex (&yylval, yyscanner); } if (yychar <= YYEOF) @@ -1571,7 +1400,9 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1594,7 +1425,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -1608,249 +1439,228 @@ yyreduce: switch (yyn) { case 6: - -/* Line 1806 of yacc.c */ -#line 116 "cmDependsFortranParser.y" +#line 108 "cmFortranParser.y" /* yacc.c:1646 */ { - free((yyvsp[(1) - (4)].string)); + free((yyvsp[-3].string)); } +#line 1447 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 7: - -/* Line 1806 of yacc.c */ -#line 122 "cmDependsFortranParser.y" +#line 114 "cmFortranParser.y" /* yacc.c:1646 */ { - if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (2)].string), "interface")) + if (cmFortranParserIsKeyword((yyvsp[-1].string), "interface")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_SetInInterface(parser, true); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_SetInInterface(parser, true); } - free((yyvsp[(1) - (2)].string)); + free((yyvsp[-1].string)); } +#line 1461 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 8: - -/* Line 1806 of yacc.c */ -#line 132 "cmDependsFortranParser.y" +#line 124 "cmFortranParser.y" /* yacc.c:1646 */ { - if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "use")) + if (cmFortranParserIsKeyword((yyvsp[-3].string), "use")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUse(parser, (yyvsp[(2) - (4)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); } - else if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "module")) + else if (cmFortranParserIsKeyword((yyvsp[-3].string), "module")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleModule(parser, (yyvsp[(2) - (4)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleModule(parser, (yyvsp[-2].string)); } - else if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "interface")) + else if (cmFortranParserIsKeyword((yyvsp[-3].string), "interface")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_SetInInterface(parser, true); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_SetInInterface(parser, true); } - else if (cmDependsFortranParserIsKeyword((yyvsp[(2) - (4)].string), "interface") && - cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "end")) + else if (cmFortranParserIsKeyword((yyvsp[-2].string), "interface") && + cmFortranParserIsKeyword((yyvsp[-3].string), "end")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_SetInInterface(parser, false); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_SetInInterface(parser, false); } - free((yyvsp[(1) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + free((yyvsp[-3].string)); + free((yyvsp[-2].string)); } +#line 1495 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 9: - -/* Line 1806 of yacc.c */ -#line 162 "cmDependsFortranParser.y" +#line 154 "cmFortranParser.y" /* yacc.c:1646 */ { - if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (5)].string), "use")) + if (cmFortranParserIsKeyword((yyvsp[-4].string), "use")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUse(parser, (yyvsp[(3) - (5)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); } - free((yyvsp[(1) - (5)].string)); - free((yyvsp[(3) - (5)].string)); + free((yyvsp[-4].string)); + free((yyvsp[-2].string)); } +#line 1510 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 10: - -/* Line 1806 of yacc.c */ -#line 173 "cmDependsFortranParser.y" +#line 165 "cmFortranParser.y" /* yacc.c:1646 */ { - if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (7)].string), "use") && - cmDependsFortranParserIsKeyword((yyvsp[(3) - (7)].string), "non_intrinsic") ) + if (cmFortranParserIsKeyword((yyvsp[-6].string), "use") && + cmFortranParserIsKeyword((yyvsp[-4].string), "non_intrinsic") ) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUse(parser, (yyvsp[(5) - (7)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); } - free((yyvsp[(1) - (7)].string)); - free((yyvsp[(3) - (7)].string)); - free((yyvsp[(5) - (7)].string)); + free((yyvsp[-6].string)); + free((yyvsp[-4].string)); + free((yyvsp[-2].string)); } +#line 1527 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 11: - -/* Line 1806 of yacc.c */ -#line 186 "cmDependsFortranParser.y" +#line 178 "cmFortranParser.y" /* yacc.c:1646 */ { - if (cmDependsFortranParserIsKeyword((yyvsp[(1) - (4)].string), "include")) + if (cmFortranParserIsKeyword((yyvsp[-3].string), "include")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleInclude(parser, (yyvsp[(2) - (4)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); } - free((yyvsp[(1) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + free((yyvsp[-3].string)); + free((yyvsp[-2].string)); } +#line 1542 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 12: - -/* Line 1806 of yacc.c */ -#line 197 "cmDependsFortranParser.y" +#line 189 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleInclude(parser, (yyvsp[(1) - (3)].string)); - free((yyvsp[(1) - (3)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); + free((yyvsp[-2].string)); } +#line 1553 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 13: - -/* Line 1806 of yacc.c */ -#line 204 "cmDependsFortranParser.y" +#line 196 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleInclude(parser, (yyvsp[(2) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); + free((yyvsp[-2].string)); } +#line 1564 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 14: - -/* Line 1806 of yacc.c */ -#line 211 "cmDependsFortranParser.y" +#line 203 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleDefine(parser, (yyvsp[(2) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); + free((yyvsp[-2].string)); } +#line 1574 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 15: - -/* Line 1806 of yacc.c */ -#line 217 "cmDependsFortranParser.y" +#line 209 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUndef(parser, (yyvsp[(2) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); + free((yyvsp[-2].string)); } +#line 1584 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 16: - -/* Line 1806 of yacc.c */ -#line 223 "cmDependsFortranParser.y" +#line 215 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleIfdef(parser, (yyvsp[(2) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); + free((yyvsp[-2].string)); } +#line 1594 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 17: - -/* Line 1806 of yacc.c */ -#line 229 "cmDependsFortranParser.y" +#line 221 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleIfndef(parser, (yyvsp[(2) - (4)].string)); - free((yyvsp[(2) - (4)].string)); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); + free((yyvsp[-2].string)); } +#line 1604 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 18: - -/* Line 1806 of yacc.c */ -#line 235 "cmDependsFortranParser.y" +#line 227 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleIf(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleIf(parser); } +#line 1613 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 19: - -/* Line 1806 of yacc.c */ -#line 240 "cmDependsFortranParser.y" +#line 232 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleElif(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleElif(parser); } +#line 1622 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 20: - -/* Line 1806 of yacc.c */ -#line 245 "cmDependsFortranParser.y" +#line 237 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleElse(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleElse(parser); } +#line 1631 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 21: - -/* Line 1806 of yacc.c */ -#line 250 "cmDependsFortranParser.y" +#line 242 "cmFortranParser.y" /* yacc.c:1646 */ { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleEndif(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleEndif(parser); } +#line 1640 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 22: - -/* Line 1806 of yacc.c */ -#line 255 "cmDependsFortranParser.y" +#line 247 "cmFortranParser.y" /* yacc.c:1646 */ { - free((yyvsp[(1) - (4)].string)); + free((yyvsp[-3].string)); } +#line 1648 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 47: - -/* Line 1806 of yacc.c */ -#line 277 "cmDependsFortranParser.y" - { free ((yyvsp[(1) - (1)].string)); } +#line 269 "cmFortranParser.y" /* yacc.c:1646 */ + { free ((yyvsp[0].string)); } +#line 1654 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 48: - -/* Line 1806 of yacc.c */ -#line 278 "cmDependsFortranParser.y" - { free ((yyvsp[(1) - (1)].string)); } +#line 270 "cmFortranParser.y" /* yacc.c:1646 */ + { free ((yyvsp[0].string)); } +#line 1660 "cmFortranParser.cxx" /* yacc.c:1646 */ break; - -/* Line 1806 of yacc.c */ -#line 1860 "cmDependsFortranParser.cxx" +#line 1664 "cmFortranParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1872,7 +1682,7 @@ yyreduce: *++yyvsp = yyval; - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -1887,9 +1697,9 @@ yyreduce: goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ @@ -1900,7 +1710,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); + yyerror (yyscanner, YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) @@ -1927,7 +1737,7 @@ yyerrlab: yymsgp = yymsg; } } - yyerror (yymsgp); + yyerror (yyscanner, yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } @@ -1951,7 +1761,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval); + yytoken, &yylval, yyscanner); yychar = YYEMPTY; } } @@ -1973,7 +1783,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; @@ -2009,13 +1819,15 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp); + yystos[yystate], yyvsp, yyscanner); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -2039,12 +1851,12 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (YY_("memory exhausted")); + yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -2056,16 +1868,16 @@ yyreturn: user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); + yytoken, &yylval, yyscanner); } - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + yystos[*yyssp], yyvsp, yyscanner); YYPOPSTACK (1); } #ifndef yyoverflow @@ -2076,13 +1888,8 @@ yyreturn: if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif - /* Make sure YYID is used. */ - return YYID (yyresult); + return yyresult; } - - - -/* Line 2067 of yacc.c */ -#line 286 "cmDependsFortranParser.y" +#line 278 "cmFortranParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h new file mode 100644 index 0000000..156c38a --- /dev/null +++ b/Source/cmFortranParser.h @@ -0,0 +1,175 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmFortranParser_h +#define cmFortranParser_h + +#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx) +# include "cmStandardIncludes.h" +#endif + +#include <stddef.h> /* size_t */ + +/* Forward declare parser object type. */ +typedef struct cmFortranParser_s cmFortranParser; + +/* Functions to enter/exit #include'd files in order. */ +bool cmFortranParser_FilePush(cmFortranParser* parser, + const char* fname); +bool cmFortranParser_FilePop(cmFortranParser* parser); + +/* Callbacks for lexer. */ +int cmFortranParser_Input(cmFortranParser* parser, + char* buffer, size_t bufferSize); + + +void cmFortranParser_StringStart(cmFortranParser* parser); +const char* cmFortranParser_StringEnd(cmFortranParser* parser); +void cmFortranParser_StringAppend(cmFortranParser* parser, + char c); + +void cmFortranParser_SetInInterface(cmFortranParser* parser, + bool is_in); +bool cmFortranParser_GetInInterface(cmFortranParser* parser); + + +void cmFortranParser_SetInPPFalseBranch(cmFortranParser* parser, + bool is_in); +bool cmFortranParser_GetInPPFalseBranch(cmFortranParser* parser); + + +void cmFortranParser_SetOldStartcond(cmFortranParser* parser, + int arg); +int cmFortranParser_GetOldStartcond(cmFortranParser* parser); + +/* Callbacks for parser. */ +void cmFortranParser_Error(cmFortranParser* parser, + const char* message); +void cmFortranParser_RuleUse(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleInclude(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleModule(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleDefine(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleUndef(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleIfdef(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleIfndef(cmFortranParser* parser, + const char* name); +void cmFortranParser_RuleIf(cmFortranParser* parser); +void cmFortranParser_RuleElif(cmFortranParser* parser); +void cmFortranParser_RuleElse(cmFortranParser* parser); +void cmFortranParser_RuleEndif(cmFortranParser* parser); + +/* Define the parser stack element type. */ +typedef union cmFortran_yystype_u cmFortran_yystype; +union cmFortran_yystype_u +{ + char* string; +}; + +/* Setup the proper yylex interface. */ +#define YY_EXTRA_TYPE cmFortranParser* +#define YY_DECL \ +int cmFortran_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) +#define YYSTYPE cmFortran_yystype +#define YYSTYPE_IS_DECLARED 1 +#if !defined(cmFortranLexer_cxx) +# include "cmFortranLexer.h" +#endif +#if !defined(cmFortranLexer_cxx) +#if !defined(cmFortranParser_cxx) +# undef YY_EXTRA_TYPE +# undef YY_DECL +# undef YYSTYPE +# undef YYSTYPE_IS_DECLARED +#endif +#endif + +#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx) +#include <stack> + +//---------------------------------------------------------------------------- +// Information about a single source file. +class cmFortranSourceInfo +{ +public: + // The name of the source file. + std::string Source; + + // Set of provided and required modules. + std::set<std::string> Provides; + std::set<std::string> Requires; + + // Set of files included in the translation unit. + std::set<std::string> Includes; +}; + +//---------------------------------------------------------------------------- +// Parser methods not included in generated interface. + +// Get the current buffer processed by the lexer. +YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner); + +// The parser entry point. +int cmFortran_yyparse(yyscan_t); + +//---------------------------------------------------------------------------- +// Define parser object internal structure. +struct cmFortranFile +{ + cmFortranFile(FILE* file, YY_BUFFER_STATE buffer, + const std::string& dir): + File(file), Buffer(buffer), Directory(dir) {} + FILE* File; + YY_BUFFER_STATE Buffer; + std::string Directory; +}; + +struct cmFortranParser_s +{ + cmFortranParser_s(std::vector<std::string> const& includes, + std::set<std::string> const& defines, + cmFortranSourceInfo& info); + ~cmFortranParser_s(); + + bool FindIncludeFile(const char* dir, const char* includeName, + std::string& fileName); + + // The include file search path. + std::vector<std::string> IncludePath; + + // Lexical scanner instance. + yyscan_t Scanner; + + // Stack of open files in the translation unit. + std::stack<cmFortranFile> FileStack; + + // Buffer for string literals. + std::string TokenString; + + // Flag for whether lexer is reading from inside an interface. + bool InInterface; + + int OldStartcond; + std::set<std::string> PPDefinitions; + size_t InPPFalseBranch; + std::stack<bool> SkipToEnd; + + // Information about the parsed source. + cmFortranSourceInfo& Info; +}; +#endif + +#endif diff --git a/Source/cmDependsFortranParser.y b/Source/cmFortranParser.y index a987c13..996bef6 100644 --- a/Source/cmDependsFortranParser.y +++ b/Source/cmFortranParser.y @@ -26,42 +26,33 @@ This file must be translated to C and modified to build everywhere. Run bison like this: - bison --yacc --name-prefix=cmDependsFortran_yy - --defines=cmDependsFortranParserTokens.h - -ocmDependsFortranParser.cxx - cmDependsFortranParser.y + bison --yacc --name-prefix=cmFortran_yy + --defines=cmFortranParserTokens.h + -ocmFortranParser.cxx + cmFortranParser.y -Modify cmDependsFortranParser.cxx: - - remove TABs - - remove use of the 'register' storage class specifier - - Remove the yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] +Modify cmFortranParser.cxx: + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ /*-------------------------------------------------------------------------*/ -#define cmDependsFortranParser_cxx -#include "cmDependsFortranParser.h" /* Interface to parser object. */ -#include "cmDependsFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ +#define cmFortranParser_cxx +#include "cmFortranParser.h" /* Interface to parser object. */ +#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ #include <cmsys/String.h> -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmDependsFortran_yyerror(x) \ - cmDependsFortranError(yyscanner, x) - /* Forward declare the lexer entry point. */ YY_DECL; -/* Helper function to forward error callback. */ -static void cmDependsFortranError(yyscan_t yyscanner, const char* message) +/* Helper function to forward error callback from parser. */ +static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_Error(parser, message); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_Error(parser, message); } -static bool cmDependsFortranParserIsKeyword(const char* word, +static bool cmFortranParserIsKeyword(const char* word, const char* keyword) { return cmsysString_strcasecmp(word, keyword) == 0; @@ -79,7 +70,13 @@ static bool cmDependsFortranParserIsKeyword(const char* word, %} /* Generate a reentrant parser object. */ -%pure-parser +%define api.pure + +/* Configure the parser to use a lexer object. */ +%lex-param {yyscan_t yyscanner} +%parse-param {yyscan_t yyscanner} + +%define parse.error verbose %union { char* string; @@ -115,63 +112,63 @@ assignment_stmt: WORD ASSIGNMENT_OP other EOSTMT /* Ignore */ keyword_stmt: WORD EOSTMT { - if (cmDependsFortranParserIsKeyword($1, "interface")) + if (cmFortranParserIsKeyword($1, "interface")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_SetInInterface(parser, true); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_SetInInterface(parser, true); } free($1); } | WORD WORD other EOSTMT { - if (cmDependsFortranParserIsKeyword($1, "use")) + if (cmFortranParserIsKeyword($1, "use")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUse(parser, $2); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUse(parser, $2); } - else if (cmDependsFortranParserIsKeyword($1, "module")) + else if (cmFortranParserIsKeyword($1, "module")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleModule(parser, $2); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleModule(parser, $2); } - else if (cmDependsFortranParserIsKeyword($1, "interface")) + else if (cmFortranParserIsKeyword($1, "interface")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_SetInInterface(parser, true); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_SetInInterface(parser, true); } - else if (cmDependsFortranParserIsKeyword($2, "interface") && - cmDependsFortranParserIsKeyword($1, "end")) + else if (cmFortranParserIsKeyword($2, "interface") && + cmFortranParserIsKeyword($1, "end")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_SetInInterface(parser, false); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_SetInInterface(parser, false); } free($1); free($2); } | WORD DCOLON WORD other EOSTMT { - if (cmDependsFortranParserIsKeyword($1, "use")) + if (cmFortranParserIsKeyword($1, "use")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUse(parser, $3); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUse(parser, $3); } free($1); free($3); } | WORD COMMA WORD DCOLON WORD other EOSTMT { - if (cmDependsFortranParserIsKeyword($1, "use") && - cmDependsFortranParserIsKeyword($3, "non_intrinsic") ) + if (cmFortranParserIsKeyword($1, "use") && + cmFortranParserIsKeyword($3, "non_intrinsic") ) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUse(parser, $5); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUse(parser, $5); } free($1); free($3); @@ -179,72 +176,72 @@ keyword_stmt: } | WORD STRING other EOSTMT /* Ignore */ { - if (cmDependsFortranParserIsKeyword($1, "include")) + if (cmFortranParserIsKeyword($1, "include")) { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleInclude(parser, $2); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleInclude(parser, $2); } free($1); free($2); } | CPP_INCLUDE_ANGLE other EOSTMT { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleInclude(parser, $1); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleInclude(parser, $1); free($1); } | include STRING other EOSTMT { - cmDependsFortranParser* parser = - cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleInclude(parser, $2); + cmFortranParser* parser = + cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleInclude(parser, $2); free($2); } | define WORD other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleDefine(parser, $2); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleDefine(parser, $2); free($2); } | undef WORD other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleUndef(parser, $2); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUndef(parser, $2); free($2); } | ifdef WORD other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleIfdef(parser, $2); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleIfdef(parser, $2); free($2); } | ifndef WORD other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleIfndef(parser, $2); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleIfndef(parser, $2); free($2); } | if other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleIf(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleIf(parser); } | elif other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleElif(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleElif(parser); } | else other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleElse(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleElse(parser); } | endif other EOSTMT { - cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner); - cmDependsFortranParser_RuleEndif(parser); + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleEndif(parser); } | WORD GARBAGE other EOSTMT /* Ignore */ { diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx new file mode 100644 index 0000000..a09c5459 --- /dev/null +++ b/Source/cmFortranParserImpl.cxx @@ -0,0 +1,408 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmFortranParser.h" + +#include "cmSystemTools.h" +#include <assert.h> + +//---------------------------------------------------------------------------- +bool cmFortranParser_s::FindIncludeFile(const char* dir, + const char* includeName, + std::string& fileName) +{ + // If the file is a full path, include it directly. + if(cmSystemTools::FileIsFullPath(includeName)) + { + fileName = includeName; + return cmSystemTools::FileExists(fileName.c_str(), true); + } + else + { + // Check for the file in the directory containing the including + // file. + std::string fullName = dir; + fullName += "/"; + fullName += includeName; + if(cmSystemTools::FileExists(fullName.c_str(), true)) + { + fileName = fullName; + return true; + } + + // Search the include path for the file. + for(std::vector<std::string>::const_iterator i = + this->IncludePath.begin(); i != this->IncludePath.end(); ++i) + { + fullName = *i; + fullName += "/"; + fullName += includeName; + if(cmSystemTools::FileExists(fullName.c_str(), true)) + { + fileName = fullName; + return true; + } + } + } + return false; +} + +//---------------------------------------------------------------------------- +cmFortranParser_s +::cmFortranParser_s(std::vector<std::string> const& includes, + std::set<std::string> const& defines, + cmFortranSourceInfo& info): + IncludePath(includes), PPDefinitions(defines), Info(info) +{ + this->InInterface = 0; + this->InPPFalseBranch = 0; + + // Initialize the lexical scanner. + cmFortran_yylex_init(&this->Scanner); + cmFortran_yyset_extra(this, this->Scanner); + + // Create a dummy buffer that is never read but is the fallback + // buffer when the last file is popped off the stack. + YY_BUFFER_STATE buffer = + cmFortran_yy_create_buffer(0, 4, this->Scanner); + cmFortran_yy_switch_to_buffer(buffer, this->Scanner); +} + +//---------------------------------------------------------------------------- +cmFortranParser_s::~cmFortranParser_s() +{ + cmFortran_yylex_destroy(this->Scanner); +} + +//---------------------------------------------------------------------------- +bool cmFortranParser_FilePush(cmFortranParser* parser, + const char* fname) +{ + // Open the new file and push it onto the stack. Save the old + // buffer with it on the stack. + if(FILE* file = cmsys::SystemTools::Fopen(fname, "rb")) + { + YY_BUFFER_STATE current = + cmFortranLexer_GetCurrentBuffer(parser->Scanner); + std::string dir = cmSystemTools::GetParentDirectory(fname); + cmFortranFile f(file, current, dir); + YY_BUFFER_STATE buffer = + cmFortran_yy_create_buffer(0, 16384, parser->Scanner); + cmFortran_yy_switch_to_buffer(buffer, parser->Scanner); + parser->FileStack.push(f); + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +bool cmFortranParser_FilePop(cmFortranParser* parser) +{ + // Pop one file off the stack and close it. Switch the lexer back + // to the next one on the stack. + if(parser->FileStack.empty()) + { + return 0; + } + else + { + cmFortranFile f = parser->FileStack.top(); parser->FileStack.pop(); + fclose(f.File); + YY_BUFFER_STATE current = + cmFortranLexer_GetCurrentBuffer(parser->Scanner); + cmFortran_yy_delete_buffer(current, parser->Scanner); + cmFortran_yy_switch_to_buffer(f.Buffer, parser->Scanner); + return 1; + } +} + +//---------------------------------------------------------------------------- +int cmFortranParser_Input(cmFortranParser* parser, + char* buffer, size_t bufferSize) +{ + // Read from the file on top of the stack. If the stack is empty, + // the end of the translation unit has been reached. + if(!parser->FileStack.empty()) + { + FILE* file = parser->FileStack.top().File; + return (int)fread(buffer, 1, bufferSize, file); + } + return 0; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_StringStart(cmFortranParser* parser) +{ + parser->TokenString = ""; +} + +//---------------------------------------------------------------------------- +const char* cmFortranParser_StringEnd(cmFortranParser* parser) +{ + return parser->TokenString.c_str(); +} + +//---------------------------------------------------------------------------- +void cmFortranParser_StringAppend(cmFortranParser* parser, + char c) +{ + parser->TokenString += c; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_SetInInterface(cmFortranParser* parser, + bool in) +{ + if(parser->InPPFalseBranch) + { + return; + } + + parser->InInterface = in; +} + +//---------------------------------------------------------------------------- +bool cmFortranParser_GetInInterface(cmFortranParser* parser) +{ + return parser->InInterface; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_SetOldStartcond(cmFortranParser* parser, + int arg) +{ + parser->OldStartcond = arg; +} + +//---------------------------------------------------------------------------- +int cmFortranParser_GetOldStartcond(cmFortranParser* parser) +{ + return parser->OldStartcond; +} + +//---------------------------------------------------------------------------- +void cmFortranParser_Error(cmFortranParser*, const char*) +{ + // If there is a parser error just ignore it. The source will not + // compile and the user will edit it. Then dependencies will have + // to be regenerated anyway. +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleUse(cmFortranParser* parser, + const char* name) +{ + if(!parser->InPPFalseBranch) + { + parser->Info.Requires.insert(cmSystemTools::LowerCase(name) ); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleInclude(cmFortranParser* parser, + const char* name) +{ + if(parser->InPPFalseBranch) + { + return; + } + + // If processing an include statement there must be an open file. + assert(!parser->FileStack.empty()); + + // Get the directory containing the source in which the include + // statement appears. This is always the first search location for + // Fortran include files. + std::string dir = parser->FileStack.top().Directory; + + // Find the included file. If it cannot be found just ignore the + // problem because either the source will not compile or the user + // does not care about depending on this included source. + std::string fullName; + if(parser->FindIncludeFile(dir.c_str(), name, fullName)) + { + // Found the included file. Save it in the set of included files. + parser->Info.Includes.insert(fullName); + + // Parse it immediately to translate the source inline. + cmFortranParser_FilePush(parser, fullName.c_str()); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleModule(cmFortranParser* parser, + const char* name) +{ + if(!parser->InPPFalseBranch && !parser->InInterface) + { + parser->Info.Provides.insert(cmSystemTools::LowerCase(name)); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleDefine(cmFortranParser* parser, + const char* macro) +{ + if(!parser->InPPFalseBranch) + { + parser->PPDefinitions.insert(macro); + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleUndef(cmFortranParser* parser, + const char* macro) +{ + if(!parser->InPPFalseBranch) + { + std::set<std::string>::iterator match; + match = parser->PPDefinitions.find(macro); + if(match != parser->PPDefinitions.end()) + { + parser->PPDefinitions.erase(match); + } + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleIfdef(cmFortranParser* parser, + const char* macro) +{ + // A new PP branch has been opened + parser->SkipToEnd.push(false); + + if (parser->InPPFalseBranch) + { + parser->InPPFalseBranch++; + } + else if(parser->PPDefinitions.find(macro) == parser->PPDefinitions.end()) + { + parser->InPPFalseBranch=1; + } + else + { + parser->SkipToEnd.top() = true; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleIfndef(cmFortranParser* parser, + const char* macro) +{ + // A new PP branch has been opened + parser->SkipToEnd.push(false); + + if (parser->InPPFalseBranch) + { + parser->InPPFalseBranch++; + } + else if(parser->PPDefinitions.find(macro) != parser->PPDefinitions.end()) + { + parser->InPPFalseBranch = 1; + } + else + { + // ignore other branches + parser->SkipToEnd.top() = true; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleIf(cmFortranParser* parser) +{ + /* Note: The current parser is _not_ able to get statements like + * #if 0 + * #if 1 + * #if MYSMBOL + * #if defined(MYSYMBOL) + * #if defined(MYSYMBOL) && ... + * right. The same for #elif. Thus in + * #if SYMBOL_1 + * .. + * #elif SYMBOL_2 + * ... + * ... + * #elif SYMBOL_N + * .. + * #else + * .. + * #endif + * _all_ N+1 branches are considered. If you got something like this + * #if defined(MYSYMBOL) + * #if !defined(MYSYMBOL) + * use + * #ifdef MYSYMBOL + * #ifndef MYSYMBOL + * instead. + */ + + // A new PP branch has been opened + // Never skip! See note above. + parser->SkipToEnd.push(false); +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleElif(cmFortranParser* parser) +{ + /* Note: There are parser limitations. See the note at + * cmFortranParser_RuleIf(..) + */ + + // Always taken unless an #ifdef or #ifndef-branch has been taken + // already. If the second condition isn't meet already + // (parser->InPPFalseBranch == 0) correct it. + if(!parser->SkipToEnd.empty() && + parser->SkipToEnd.top() && !parser->InPPFalseBranch) + { + parser->InPPFalseBranch = 1; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleElse(cmFortranParser* parser) +{ + // if the parent branch is false do nothing! + if(parser->InPPFalseBranch > 1) + { + return; + } + + // parser->InPPFalseBranch is either 0 or 1. We change it depending on + // parser->SkipToEnd.top() + if(!parser->SkipToEnd.empty() && + parser->SkipToEnd.top()) + { + parser->InPPFalseBranch = 1; + } + else + { + parser->InPPFalseBranch = 0; + } +} + +//---------------------------------------------------------------------------- +void cmFortranParser_RuleEndif(cmFortranParser* parser) +{ + if(!parser->SkipToEnd.empty()) + { + parser->SkipToEnd.pop(); + } + + // #endif doesn't know if there was a "#else" in before, so it + // always decreases InPPFalseBranch + if(parser->InPPFalseBranch) + { + parser->InPPFalseBranch--; + } +} diff --git a/Source/cmDependsFortranParserTokens.h b/Source/cmFortranParserTokens.h index 941eda0..df1aec3 100644 --- a/Source/cmDependsFortranParserTokens.h +++ b/Source/cmFortranParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 3.0.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,43 +30,51 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED +# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int cmFortran_yydebug; +#endif -/* Tokens. */ +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - EOSTMT = 258, - ASSIGNMENT_OP = 259, - GARBAGE = 260, - CPP_INCLUDE = 261, - F90PPR_INCLUDE = 262, - COCO_INCLUDE = 263, - F90PPR_DEFINE = 264, - CPP_DEFINE = 265, - F90PPR_UNDEF = 266, - CPP_UNDEF = 267, - CPP_IFDEF = 268, - CPP_IFNDEF = 269, - CPP_IF = 270, - CPP_ELSE = 271, - CPP_ELIF = 272, - CPP_ENDIF = 273, - F90PPR_IFDEF = 274, - F90PPR_IFNDEF = 275, - F90PPR_IF = 276, - F90PPR_ELSE = 277, - F90PPR_ELIF = 278, - F90PPR_ENDIF = 279, - COMMA = 280, - DCOLON = 281, - CPP_TOENDL = 282, - UNTERMINATED_STRING = 283, - STRING = 284, - WORD = 285, - CPP_INCLUDE_ANGLE = 286 - }; + enum yytokentype + { + EOSTMT = 258, + ASSIGNMENT_OP = 259, + GARBAGE = 260, + CPP_INCLUDE = 261, + F90PPR_INCLUDE = 262, + COCO_INCLUDE = 263, + F90PPR_DEFINE = 264, + CPP_DEFINE = 265, + F90PPR_UNDEF = 266, + CPP_UNDEF = 267, + CPP_IFDEF = 268, + CPP_IFNDEF = 269, + CPP_IF = 270, + CPP_ELSE = 271, + CPP_ELIF = 272, + CPP_ENDIF = 273, + F90PPR_IFDEF = 274, + F90PPR_IFNDEF = 275, + F90PPR_IF = 276, + F90PPR_ELSE = 277, + F90PPR_ELIF = 278, + F90PPR_ENDIF = 279, + COMMA = 280, + DCOLON = 281, + CPP_TOENDL = 282, + UNTERMINATED_STRING = 283, + STRING = 284, + WORD = 285, + CPP_INCLUDE_ANGLE = 286 + }; #endif /* Tokens. */ #define EOSTMT 258 @@ -99,24 +107,23 @@ #define WORD 285 #define CPP_INCLUDE_ANGLE 286 - - - +/* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE +typedef union YYSTYPE YYSTYPE; +union YYSTYPE { - -/* Line 2068 of yacc.c */ -#line 89 "cmDependsFortranParser.y" +#line 81 "cmFortranParser.y" /* yacc.c:1909 */ char* string; - - -/* Line 2068 of yacc.c */ -#line 118 "cmDependsFortranParserTokens.h" -} YYSTYPE; +#line 120 "cmFortranParserTokens.h" /* yacc.c:1909 */ +}; # define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif + + + +int cmFortran_yyparse (yyscan_t yyscanner); + +#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */ diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 001adb1..c883ad7 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -43,6 +43,7 @@ public: newC->Args = this->Args; newC->Functions = this->Functions; newC->Policies = this->Policies; + newC->FilePath = this->FilePath; return newC; } @@ -71,9 +72,9 @@ public: std::vector<std::string> Args; std::vector<cmListFileFunction> Functions; cmPolicies::PolicyMap Policies; + std::string FilePath; }; - bool cmFunctionHelperCommand::InvokeInitialPass (const std::vector<cmListFileArgument>& args, cmExecutionStatus & inStatus) @@ -93,14 +94,9 @@ bool cmFunctionHelperCommand::InvokeInitialPass return false; } - // we push a scope on the makefile - cmMakefile::ScopePushPop varScope(this->Makefile); - cmMakefile::LexicalPushPop lexScope(this->Makefile); - static_cast<void>(varScope); - - // Push a weak policy scope which restores the policies recorded at - // function creation. - cmMakefile::PolicyPushPop polScope(this->Makefile, true, this->Policies); + cmMakefile::FunctionPushPop functionScope(this->Makefile, + this->FilePath, + this->Policies); // set the value of argc std::ostringstream strStream; @@ -129,7 +125,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass std::string argvDef = cmJoin(expandedArgs, ";"); std::vector<std::string>::const_iterator eit = expandedArgs.begin() + (this->Args.size()-1); - std::string argnDef = cmJoin(cmRange(eit, expandedArgs.end()), ";"); + std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); this->Makefile->AddDefinition("ARGV", argvDef.c_str()); this->Makefile->MarkVariableAsUsed("ARGV"); this->Makefile->AddDefinition("ARGN", argnDef.c_str()); @@ -145,8 +141,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass { // The error message should have already included the call stack // so we do not need to report an error here. - lexScope.Quiet(); - polScope.Quiet(); + functionScope.Quiet(); inStatus.SetNestedError(true); return false; } @@ -179,19 +174,9 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, cmFunctionHelperCommand *f = new cmFunctionHelperCommand(); f->Args = this->Args; f->Functions = this->Functions; + f->FilePath = this->GetStartingContext().FilePath; mf.RecordPolicies(f->Policies); - // Set the FilePath on the arguments to match the function since it is - // not stored and the original values may be freed - for (unsigned int i = 0; i < f->Functions.size(); ++i) - { - for (unsigned int j = 0; j < f->Functions[i].Arguments.size(); ++j) - { - f->Functions[i].Arguments[j].FilePath = - f->Functions[i].FilePath.c_str(); - } - } - std::string newName = "_" + this->Args[0]; mf.GetState()->RenameCommand(this->Args[0], newName); mf.GetState()->AddCommand(f); @@ -220,7 +205,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf) if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endfunction")) { std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments); + mf.ExpandArguments(lff.Arguments, expandedArguments, + this->GetStartingContext().FilePath.c_str()); // if the endfunction has arguments then make sure // they match the ones in the opening function command if ((expandedArguments.empty() || diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index a1c405b..80a4f81 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -23,7 +23,7 @@ //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( - cmListFileBacktrace const* backtrace): + const cmListFileBacktrace& backtrace): Backtrace(backtrace) { } @@ -33,9 +33,7 @@ cmsys::auto_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(std::string const& input) { return cmsys::auto_ptr<cmCompiledGeneratorExpression>( - new cmCompiledGeneratorExpression( - this->Backtrace ? *this->Backtrace : cmListFileBacktrace(NULL), - input)); + new cmCompiledGeneratorExpression(this->Backtrace, input)); } //---------------------------------------------------------------------------- diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 11c27fd..cd19bc0 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -42,7 +42,8 @@ class cmGeneratorExpression { public: /** Construct. */ - cmGeneratorExpression(cmListFileBacktrace const* backtrace = NULL); + cmGeneratorExpression( + cmListFileBacktrace const& backtrace = cmListFileBacktrace()); ~cmGeneratorExpression(); cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse( @@ -71,7 +72,7 @@ private: cmGeneratorExpression(const cmGeneratorExpression &); void operator=(const cmGeneratorExpression &); - cmListFileBacktrace const* Backtrace; + cmListFileBacktrace Backtrace; }; class cmCompiledGeneratorExpression diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index ff8790c..851aacd 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -35,7 +35,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( const GeneratorExpressionContent *content, cmGeneratorExpressionDAGChecker *parent) : Parent(parent), Target(target), Property(property), - Content(content), Backtrace(NULL), TransitivePropertiesOnly(false) + Content(content), Backtrace(), TransitivePropertiesOnly(false) { Initialize(); } diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index c726995..e4d9f10 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -25,19 +25,18 @@ cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( const std::string &input, cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr, - cmMakefile *makefile, cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent) : Input(input), OutputFileExpr(outputFileExpr), - Makefile(makefile), Condition(condition), InputIsContent(inputIsContent) { } //---------------------------------------------------------------------------- -void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config, +void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg, + const std::string& config, const std::string& lang, cmCompiledGeneratorExpression* inputExpression, std::map<std::string, std::string> &outputFiles, mode_t perm) @@ -45,7 +44,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config, std::string rawCondition = this->Condition->GetInput(); if (!rawCondition.empty()) { - std::string condResult = this->Condition->Evaluate(this->Makefile, config, + std::string condResult = this->Condition->Evaluate(lg->GetMakefile(), + config, false, 0, 0, 0, lang); if (condResult == "0") { @@ -56,16 +56,17 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config, std::ostringstream e; e << "Evaluation file condition \"" << rawCondition << "\" did " "not evaluate to valid content. Got \"" << condResult << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } } const std::string outputFileName - = this->OutputFileExpr->Evaluate(this->Makefile, config, + = this->OutputFileExpr->Evaluate(lg->GetMakefile(), config, false, 0, 0, 0, lang); const std::string outputContent - = inputExpression->Evaluate(this->Makefile, config, + = inputExpression->Evaluate(lg->GetMakefile(), + config, false, 0, 0, 0, lang); std::map<std::string, std::string>::iterator it @@ -81,11 +82,11 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config, e << "Evaluation file to be written multiple times for different " "configurations or languages with different content:\n " << outputFileName; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - this->Makefile->AddCMakeOutputFile(outputFileName.c_str()); + lg->GetMakefile()->AddCMakeOutputFile(outputFileName.c_str()); this->Files.push_back(outputFileName); outputFiles[outputFileName] = outputContent; @@ -100,18 +101,19 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config, //---------------------------------------------------------------------------- void cmGeneratorExpressionEvaluationFile::CreateOutputFile( - std::string const& config) + cmLocalGenerator *lg, std::string const& config) { std::vector<std::string> enabledLanguages; - cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator *gg = lg->GetGlobalGenerator(); gg->GetEnabledLanguages(enabledLanguages); for(std::vector<std::string>::const_iterator le = enabledLanguages.begin(); le != enabledLanguages.end(); ++le) { - std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config, + std::string name = this->OutputFileExpr->Evaluate(lg->GetMakefile(), + config, false, 0, 0, 0, *le); - cmSourceFile* sf = this->Makefile->GetOrCreateSource(name); + cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(name); sf->SetProperty("GENERATED", "1"); gg->SetFilenameTargetDepends(sf, @@ -120,7 +122,7 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile( } //---------------------------------------------------------------------------- -void cmGeneratorExpressionEvaluationFile::Generate() +void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator *lg) { mode_t perm = 0; std::string inputContent; @@ -130,14 +132,14 @@ void cmGeneratorExpressionEvaluationFile::Generate() } else { - this->Makefile->AddCMakeDependFile(this->Input.c_str()); + lg->GetMakefile()->AddCMakeDependFile(this->Input.c_str()); cmSystemTools::GetPermissions(this->Input.c_str(), perm); cmsys::ifstream fin(this->Input.c_str()); if(!fin) { std::ostringstream e; e << "Evaluation file \"" << this->Input << "\" cannot be read."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } @@ -152,14 +154,14 @@ void cmGeneratorExpressionEvaluationFile::Generate() } cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace(); - cmGeneratorExpression contentGE(&lfbt); + cmGeneratorExpression contentGE(lfbt); cmsys::auto_ptr<cmCompiledGeneratorExpression> inputExpression = contentGE.Parse(inputContent); std::map<std::string, std::string> outputFiles; std::vector<std::string> allConfigs; - this->Makefile->GetConfigurations(allConfigs); + lg->GetMakefile()->GetConfigurations(allConfigs); if (allConfigs.empty()) { @@ -167,7 +169,7 @@ void cmGeneratorExpressionEvaluationFile::Generate() } std::vector<std::string> enabledLanguages; - cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator *gg = lg->GetGlobalGenerator(); gg->GetEnabledLanguages(enabledLanguages); for(std::vector<std::string>::const_iterator le = enabledLanguages.begin(); @@ -176,7 +178,7 @@ void cmGeneratorExpressionEvaluationFile::Generate() for(std::vector<std::string>::const_iterator li = allConfigs.begin(); li != allConfigs.end(); ++li) { - this->Generate(*li, *le, inputExpression.get(), outputFiles, perm); + this->Generate(lg, *li, *le, inputExpression.get(), outputFiles, perm); if(cmSystemTools::GetFatalErrorOccured()) { return; diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index 5d8b54c..ad41274 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -18,31 +18,32 @@ #include "cmGeneratorExpression.h" +class cmLocalGenerator; + //---------------------------------------------------------------------------- class cmGeneratorExpressionEvaluationFile { public: cmGeneratorExpressionEvaluationFile(const std::string &input, cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr, - cmMakefile *makefile, cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent); - void Generate(); + void Generate(cmLocalGenerator* lg); std::vector<std::string> GetFiles() const { return this->Files; } - void CreateOutputFile(std::string const& config); + void CreateOutputFile(cmLocalGenerator* lg, std::string const& config); private: - void Generate(const std::string& config, const std::string& lang, - cmCompiledGeneratorExpression* inputExpression, - std::map<std::string, std::string> &outputFiles, mode_t perm); + void Generate(cmLocalGenerator* lg, const std::string& config, + const std::string& lang, + cmCompiledGeneratorExpression* inputExpression, + std::map<std::string, std::string> &outputFiles, mode_t perm); private: const std::string Input; const cmsys::auto_ptr<cmCompiledGeneratorExpression> OutputFileExpr; - cmMakefile *Makefile; const cmsys::auto_ptr<cmCompiledGeneratorExpression> Condition; std::vector<std::string> Files; const bool InputIsContent; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 293eb41..31b6766 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -21,7 +21,7 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression( cmTarget const* headTarget, cmTarget const* currentTarget, cmGeneratorExpressionDAGChecker *dagChecker) { - cmGeneratorExpression ge(&context->Backtrace); + cmGeneratorExpression ge(context->Backtrace); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem); std::string result = cge->Evaluate(makefile, @@ -990,6 +990,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode assert(target); + cmGeneratorTarget* gtgt = + context->Makefile->GetGlobalGenerator()->GetGeneratorTarget(target); + if (propertyName == "LINKER_LANGUAGE") { if (target->LinkLanguagePropagatesToDependents() && @@ -1001,7 +1004,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "link libraries for a static library"); return std::string(); } - return target->GetLinkerLanguage(context->Config); + return gtgt->GetLinkerLanguage(context->Config); } cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, @@ -1105,8 +1108,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if(isInterfaceProperty) { - if(cmTarget::LinkInterfaceLibraries const* iface = - target->GetLinkInterfaceLibraries(context->Config, headTarget, true)) + if(cmLinkInterfaceLibraries const* iface = + gtgt->GetLinkInterfaceLibraries(context->Config, headTarget, true)) { linkedTargetsContent = getLinkedTargetsContent(iface->Libraries, target, @@ -1117,7 +1120,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } else if(!interfacePropertyName.empty()) { - if(cmTarget::LinkImplementationLibraries const* impl = + if(cmLinkImplementationLibraries const* impl = target->GetLinkImplementationLibraries(context->Config)) { linkedTargetsContent = @@ -1135,40 +1138,40 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { return linkedTargetsContent; } - if (target->IsLinkInterfaceDependentBoolProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentBoolProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; - return target->GetLinkInterfaceDependentBoolProperty( + return gtgt->GetLinkInterfaceDependentBoolProperty( propertyName, context->Config) ? "1" : "0"; } - if (target->IsLinkInterfaceDependentStringProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentStringProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentStringProperty( + gtgt->GetLinkInterfaceDependentStringProperty( propertyName, context->Config); return propContent ? propContent : ""; } - if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMinProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMinProperty( + gtgt->GetLinkInterfaceDependentNumberMinProperty( propertyName, context->Config); return propContent ? propContent : ""; } - if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMaxProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMaxProperty( + gtgt->GetLinkInterfaceDependentNumberMaxProperty( propertyName, context->Config); return propContent ? propContent : ""; @@ -1180,22 +1183,22 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (!target->IsImported() && dagCheckerParent && !dagCheckerParent->EvaluatingLinkLibraries()) { - if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMinProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMinProperty( + gtgt->GetLinkInterfaceDependentNumberMinProperty( propertyName, context->Config); return propContent ? propContent : ""; } - if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMaxProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMaxProperty( + gtgt->GetLinkInterfaceDependentNumberMaxProperty( propertyName, context->Config); return propContent ? propContent : ""; @@ -1369,8 +1372,6 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries(); - std::string result; - for (LangMap::const_iterator lit = testedFeatures.begin(); lit != testedFeatures.end(); ++lit) { @@ -1556,7 +1557,7 @@ class ArtifactDirTag; template<typename ArtifactT> struct TargetFilesystemArtifactResultCreator { - static std::string Create(cmTarget* target, + static std::string Create(cmGeneratorTarget* target, cmGeneratorExpressionContext *context, const GeneratorExpressionContent *content); }; @@ -1565,12 +1566,12 @@ struct TargetFilesystemArtifactResultCreator template<> struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag> { - static std::string Create(cmTarget* target, + static std::string Create(cmGeneratorTarget* target, cmGeneratorExpressionContext *context, const GeneratorExpressionContent *content) { // The target soname file (.so.1). - if(target->IsDLLPlatform()) + if(target->Target->IsDLLPlatform()) { ::reportError(context, content->GetOriginalExpression(), "TARGET_SONAME_FILE is not allowed " @@ -1584,7 +1585,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag> "SHARED libraries."); return std::string(); } - std::string result = target->GetDirectory(context->Config); + std::string result = target->Target->GetDirectory(context->Config); result += "/"; result += target->GetSOName(context->Config); return result; @@ -1595,10 +1596,17 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag> template<> struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> { - static std::string Create(cmTarget* target, + static std::string Create(cmGeneratorTarget* target, cmGeneratorExpressionContext *context, const GeneratorExpressionContent *content) { + if (target->IsImported()) + { + ::reportError(context, content->GetOriginalExpression(), + "TARGET_PDB_FILE not allowed for IMPORTED targets."); + return std::string(); + } + std::string language = target->GetLinkerLanguage(context->Config); std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB"; @@ -1610,7 +1618,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> return std::string(); } - cmTarget::TargetType targetType = target->GetType(); + cmTarget::TargetType targetType = target->Target->GetType(); if(targetType != cmTarget::SHARED_LIBRARY && targetType != cmTarget::MODULE_LIBRARY && @@ -1622,7 +1630,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> return std::string(); } - std::string result = target->GetPDBDirectory(context->Config); + std::string result = target->Target->GetPDBDirectory(context->Config); result += "/"; result += target->GetPDBName(context->Config); return result; @@ -1633,12 +1641,12 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> template<> struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag> { - static std::string Create(cmTarget* target, + static std::string Create(cmGeneratorTarget* target, cmGeneratorExpressionContext *context, const GeneratorExpressionContent *content) { // The file used to link to the target (.so, .lib, .a). - if(!target->IsLinkable()) + if(!target->Target->IsLinkable()) { ::reportError(context, content->GetOriginalExpression(), "TARGET_LINKER_FILE is allowed only for libraries and " @@ -1646,7 +1654,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag> return std::string(); } return target->GetFullPath(context->Config, - target->HasImportLibrary()); + target->Target->HasImportLibrary()); } }; @@ -1654,7 +1662,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag> template<> struct TargetFilesystemArtifactResultCreator<ArtifactNameTag> { - static std::string Create(cmTarget* target, + static std::string Create(cmGeneratorTarget* target, cmGeneratorExpressionContext *context, const GeneratorExpressionContent *) { @@ -1716,7 +1724,8 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } - cmTarget* target = context->Makefile->FindTargetToUse(name); + cmGeneratorTarget* target = + context->Makefile->FindGeneratorTargetToUse(name); if(!target) { ::reportError(context, content->GetOriginalExpression(), @@ -1739,8 +1748,8 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode "be used while evaluating link libraries"); return std::string(); } - context->DependTargets.insert(target); - context->AllTargets.insert(target); + context->DependTargets.insert(target->Target); + context->AllTargets.insert(target->Target); std::string result = TargetFilesystemArtifactResultCreator<ArtifactT>::Create( diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e2b8c45..09387b7 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -24,11 +24,31 @@ #include <queue> +#include <errno.h> #include "assert.h" +#if defined(CMAKE_BUILD_WITH_CMAKE) +#include <cmsys/hash_set.hxx> +#define UNORDERED_SET cmsys::hash_set +#else +#define UNORDERED_SET std::set +#endif + +class cmGeneratorTarget::TargetPropertyEntry { + static cmLinkImplItem NoLinkImplItem; +public: + TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, + cmLinkImplItem const& item = NoLinkImplItem) + : ge(cge), LinkImplItem(item) + {} + const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; + cmLinkImplItem const& LinkImplItem; +}; +cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; + //---------------------------------------------------------------------------- void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib, - cmTarget *target, cmake *cm) + cmGeneratorTarget const* target, cmake *cm) { if(!badObjLib.empty()) { @@ -42,7 +62,7 @@ void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib, e << "but may contain only sources that compile, header files, and " "other files that would not affect linking of a normal library."; cm->IssueMessage(cmake::FATAL_ERROR, e.str(), - target->GetBacktrace()); + target->Target->GetBacktrace()); } } @@ -125,14 +145,14 @@ struct TagVisitor { DataType& Data; std::vector<cmSourceFile*> BadObjLibFiles; - cmTarget *Target; + cmGeneratorTarget const* Target; cmGlobalGenerator *GlobalGenerator; cmsys::RegularExpression Header; bool IsObjLib; - TagVisitor(cmTarget *target, DataType& data) + TagVisitor(cmGeneratorTarget const* target, DataType& data) : Data(data), Target(target), - GlobalGenerator(target->GetMakefile()->GetGlobalGenerator()), + GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator()), Header(CM_HEADER_REGEX), IsObjLib(target->GetType() == cmTarget::OBJECT_LIBRARY) { @@ -219,13 +239,71 @@ struct TagVisitor } }; +void CreatePropertyGeneratorExpressions( + cmStringRange const& entries, + cmBacktraceRange const& backtraces, + std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items, + bool evaluateForBuildsystem = false) +{ + std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin(); + for (std::vector<std::string>::const_iterator it = entries.begin(); + it != entries.end(); ++it, ++btIt) + { + cmGeneratorExpression ge(*btIt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*it); + cge->SetEvaluateForBuildsystem(evaluateForBuildsystem); + items.push_back(new cmGeneratorTarget::TargetPropertyEntry(cge)); + } +} + //---------------------------------------------------------------------------- -cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t), - SourceFileFlagsConstructed(false) +cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) + : Target(t), + SourceFileFlagsConstructed(false), + PolicyWarnedCMP0022(false), + DebugIncludesDone(false), + DebugCompileOptionsDone(false), + DebugCompileFeaturesDone(false), + DebugCompileDefinitionsDone(false) { this->Makefile = this->Target->GetMakefile(); - this->LocalGenerator = this->Makefile->GetLocalGenerator(); - this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); + this->LocalGenerator = lg; + this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); + + CreatePropertyGeneratorExpressions( + t->GetIncludeDirectoriesEntries(), + t->GetIncludeDirectoriesBacktraces(), + this->IncludeDirectoriesEntries); + + CreatePropertyGeneratorExpressions( + t->GetCompileOptionsEntries(), + t->GetCompileOptionsBacktraces(), + this->CompileOptionsEntries); + + CreatePropertyGeneratorExpressions( + t->GetCompileFeaturesEntries(), + t->GetCompileFeaturesBacktraces(), + this->CompileFeaturesEntries); + + CreatePropertyGeneratorExpressions( + t->GetCompileDefinitionsEntries(), + t->GetCompileDefinitionsBacktraces(), + this->CompileDefinitionsEntries); +} + +cmGeneratorTarget::~cmGeneratorTarget() +{ + cmDeleteAll(this->IncludeDirectoriesEntries); + cmDeleteAll(this->CompileOptionsEntries); + cmDeleteAll(this->CompileFeaturesEntries); + cmDeleteAll(this->CompileDefinitionsEntries); + cmDeleteAll(this->LinkInformation); + this->LinkInformation.clear(); +} + +cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const +{ + return this->LocalGenerator; } //---------------------------------------------------------------------------- @@ -247,6 +325,77 @@ const char *cmGeneratorTarget::GetProperty(const std::string& prop) const } //---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetOutputName(const std::string& config, + bool implib) const +{ + // Lookup/compute/cache the output name for this configuration. + OutputNameKey key(config, implib); + cmGeneratorTarget::OutputNameMapType::iterator i = + this->OutputNameMap.find(key); + if(i == this->OutputNameMap.end()) + { + // Add empty name in map to detect potential recursion. + OutputNameMapType::value_type entry(key, ""); + i = this->OutputNameMap.insert(entry).first; + + // Compute output name. + std::vector<std::string> props; + std::string type = this->Target->GetOutputTargetType(implib); + std::string configUpper = cmSystemTools::UpperCase(config); + if(!type.empty() && !configUpper.empty()) + { + // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG> + props.push_back(type + "_OUTPUT_NAME_" + configUpper); + } + if(!type.empty()) + { + // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME + props.push_back(type + "_OUTPUT_NAME"); + } + if(!configUpper.empty()) + { + // OUTPUT_NAME_<CONFIG> + props.push_back("OUTPUT_NAME_" + configUpper); + // <CONFIG>_OUTPUT_NAME + props.push_back(configUpper + "_OUTPUT_NAME"); + } + // OUTPUT_NAME + props.push_back("OUTPUT_NAME"); + + std::string outName; + for(std::vector<std::string>::const_iterator it = props.begin(); + it != props.end(); ++it) + { + if (const char* outNameProp = this->Target->GetProperty(*it)) + { + outName = outNameProp; + break; + } + } + + if(outName.empty()) + { + outName = this->GetName(); + } + + // Now evaluate genex and update the previously-prepared map entry. + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName); + i->second = cge->Evaluate(this->Makefile, config); + } + else if(i->second.empty()) + { + // An empty map entry indicates we have been called recursively + // from the above block. + this->Makefile->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.", + this->Target->GetBacktrace()); + } + return i->second; +} + +//---------------------------------------------------------------------------- std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(cmSourceFile const* sf) const { @@ -294,7 +443,7 @@ static void handleSystemIncludesDep(cmMakefile *mf, cmTarget const* depTgt, { \ std::vector<cmSourceFile*> sourceFiles; \ this->Target->GetSourceFiles(sourceFiles, config); \ - TagVisitor<DATA ## Tag DATATYPE> visitor(this->Target, data); \ + TagVisitor<DATA ## Tag DATATYPE> visitor(this, data); \ for(std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \ si != sourceFiles.end(); ++si) \ { \ @@ -353,6 +502,34 @@ void cmGeneratorTarget::ComputeObjectMapping() } //---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetFeature(const std::string& feature, + const std::string& config) const +{ + if(!config.empty()) + { + std::string featureConfig = feature; + featureConfig += "_"; + featureConfig += cmSystemTools::UpperCase(config); + if(const char* value = this->Target->GetProperty(featureConfig)) + { + return value; + } + } + if(const char* value = this->Target->GetProperty(feature)) + { + return value; + } + return this->LocalGenerator->GetFeature(feature, config); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature, + const std::string& config) const +{ + return cmSystemTools::IsOn(this->GetFeature(feature, config)); +} + +//---------------------------------------------------------------------------- const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) { this->ComputeObjectMapping(); @@ -486,6 +663,61 @@ void cmGeneratorTarget } //---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetLocation(const std::string& config) const +{ + static std::string location; + if (this->Target->IsImported()) + { + location = this->Target->ImportedGetFullPath(config, false); + } + else + { + location = this->GetFullPath(config, false); + } + return location.c_str(); +} + +bool cmGeneratorTarget::IsImported() const +{ + return this->Target->IsImported(); +} + +//---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetLocationForBuild() const +{ + static std::string location; + if(this->IsImported()) + { + location = this->Target->ImportedGetFullPath("", false); + return location.c_str(); + } + + // Now handle the deprecated build-time configuration location. + location = this->Target->GetDirectory(); + const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); + if(cfgid && strcmp(cfgid, ".") != 0) + { + location += "/"; + location += cfgid; + } + + if(this->Target->IsAppBundleOnApple()) + { + std::string macdir = this->BuildMacContentDirectory("", "", + false); + if(!macdir.empty()) + { + location += "/"; + location += macdir; + } + } + location += "/"; + location += this->GetFullName("", false); + return location.c_str(); +} + + +//---------------------------------------------------------------------------- bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, const std::string& config) const { @@ -522,7 +754,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, } std::vector<cmTarget const*> const& deps = - this->Target->GetLinkImplementationClosure(config); + this->GetLinkImplementationClosure(config); for(std::vector<cmTarget const*>::const_iterator li = deps.begin(), le = deps.end(); li != le; ++li) { @@ -562,6 +794,700 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files, //---------------------------------------------------------------------------- std::string +cmGeneratorTarget::GetCompilePDBName(const std::string& config) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // Check for a per-configuration output directory target property. + std::string configUpper = cmSystemTools::UpperCase(config); + std::string configProp = "COMPILE_PDB_NAME_"; + configProp += configUpper; + const char* config_name = this->Target->GetProperty(configProp); + if(config_name && *config_name) + { + return prefix + config_name + ".pdb"; + } + + const char* name = this->Target->GetProperty("COMPILE_PDB_NAME"); + if(name && *name) + { + return prefix + name + ".pdb"; + } + + return ""; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetCompilePDBPath(const std::string& config) const +{ + std::string dir = this->GetCompilePDBDirectory(config); + std::string name = this->GetCompilePDBName(config); + if(dir.empty() && !name.empty()) + { + dir = this->Target->GetPDBDirectory(config); + } + if(!dir.empty()) + { + dir += "/"; + } + return dir + name; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::HasSOName(const std::string& config) const +{ + // soname is supported only for shared libraries and modules, + // and then only when the platform supports an soname flag. + return ((this->GetType() == cmTarget::SHARED_LIBRARY) && + !this->GetPropertyAsBool("NO_SONAME") && + this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); +} + +//---------------------------------------------------------------------------- +bool +cmGeneratorTarget::NeedRelinkBeforeInstall(const std::string& config) const +{ + // Only executables and shared libraries can have an rpath and may + // need relinking. + if(this->GetType() != cmTarget::EXECUTABLE && + this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY) + { + return false; + } + + // If there is no install location this target will not be installed + // and therefore does not need relinking. + if(!this->Target->GetHaveInstallRule()) + { + return false; + } + + // If skipping all rpaths completely then no relinking is needed. + if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) + { + return false; + } + + // If building with the install-tree rpath no relinking is needed. + if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) + { + return false; + } + + // If chrpath is going to be used no relinking is needed. + if(this->IsChrpathUsed(config)) + { + return false; + } + + // Check for rpath support on this platform. + std::string ll = this->GetLinkerLanguage(config); + if(!ll.empty()) + { + std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; + flagVar += ll; + flagVar += "_FLAG"; + if(!this->Makefile->IsSet(flagVar)) + { + // There is no rpath support on this platform so nothing needs + // relinking. + return false; + } + } + else + { + // No linker language is known. This error will be reported by + // other code. + return false; + } + + // If either a build or install tree rpath is set then the rpath + // will likely change between the build tree and install tree and + // this target must be relinked. + return this->HaveBuildTreeRPATH(config) + || this->Target->HaveInstallTreeRPATH(); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const +{ + // Only certain target types have an rpath. + if(!(this->GetType() == cmTarget::SHARED_LIBRARY || + this->GetType() == cmTarget::MODULE_LIBRARY || + this->GetType() == cmTarget::EXECUTABLE)) + { + return false; + } + + // If the target will not be installed we do not need to change its + // rpath. + if(!this->Target->GetHaveInstallRule()) + { + return false; + } + + // Skip chrpath if skipping rpath altogether. + if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) + { + return false; + } + + // Skip chrpath if it does not need to be changed at install time. + if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) + { + return false; + } + + // Allow the user to disable builtin chrpath explicitly. + if(this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH")) + { + return false; + } + + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + return true; + } + +#if defined(CMAKE_USE_ELF_PARSER) + // Enable if the rpath flag uses a separator and the target uses ELF + // binaries. + std::string ll = this->GetLinkerLanguage(config); + if(!ll.empty()) + { + std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; + sepVar += ll; + sepVar += "_FLAG_SEP"; + const char* sep = this->Makefile->GetDefinition(sepVar); + if(sep && *sep) + { + // TODO: Add ELF check to ABI detection and get rid of + // CMAKE_EXECUTABLE_FORMAT. + if(const char* fmt = + this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) + { + return strcmp(fmt, "ELF") == 0; + } + } + } +#endif + static_cast<void>(config); + return false; +} + + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetSOName(const std::string& config) const +{ + if(this->Target->IsImported()) + { + // Lookup the imported soname. + if(cmTarget::ImportInfo const* info = this->Target->GetImportInfo(config)) + { + if(info->NoSOName) + { + // The imported library has no builtin soname so the name + // searched at runtime will be just the filename. + return cmSystemTools::GetFilenameName(info->Location); + } + else + { + // Use the soname given if any. + if(info->SOName.find("@rpath/") == 0) + { + return info->SOName.substr(6); + } + return info->SOName; + } + } + else + { + return ""; + } + } + else + { + // Compute the soname that will be built. + std::string name; + std::string soName; + std::string realName; + std::string impName; + std::string pdbName; + this->GetLibraryNames(name, soName, realName, + impName, pdbName, config); + return soName; + } +} + + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetAppBundleDirectory(const std::string& config, + bool contentOnly) const +{ + std::string fpath = this->GetFullName(config, false); + fpath += ".app"; + if(!this->Makefile->PlatformIsAppleIos()) + { + fpath += "/Contents"; + if(!contentOnly) + fpath += "/MacOS"; + } + return fpath; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsBundleOnApple() const +{ + return this->Target->IsFrameworkOnApple() + || this->Target->IsAppBundleOnApple() + || this->Target->IsCFBundleOnApple(); +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config, + bool contentOnly) const +{ + std::string fpath; + fpath += this->GetOutputName(config, false); + fpath += "."; + const char *ext = this->Target->GetProperty("BUNDLE_EXTENSION"); + if (!ext) + { + if (this->Target->IsXCTestOnApple()) + { + ext = "xctest"; + } + else + { + ext = "bundle"; + } + } + fpath += ext; + if(!this->Makefile->PlatformIsAppleIos()) + { + fpath += "/Contents"; + if(!contentOnly) + fpath += "/MacOS"; + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetFrameworkDirectory(const std::string& config, + bool rootDir) const +{ + std::string fpath; + fpath += this->GetOutputName(config, false); + fpath += ".framework"; + if(!rootDir && !this->Makefile->PlatformIsAppleIos()) + { + fpath += "/Versions/"; + fpath += this->Target->GetFrameworkVersion(); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetFullName(const std::string& config, bool implib) const +{ + if(this->Target->IsImported()) + { + return this->Target->GetFullNameImported(config, implib); + } + else + { + return this->GetFullNameInternal(config, implib); + } +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetInstallNameDirForBuildTree( + const std::string& config) const +{ + // If building directly for installation then the build tree install_name + // is the same as the install tree. + if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) + { + return this->GetInstallNameDirForInstallTree(); + } + + // Use the build tree directory for the target. + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") && + !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && + !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) + { + std::string dir; + if(this->Target->MacOSXRpathInstallNameDirDefault()) + { + dir = "@rpath"; + } + else + { + dir = this->Target->GetDirectory(config); + } + dir += "/"; + return dir; + } + else + { + return ""; + } +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const +{ + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + std::string dir; + const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); + + if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && + !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) + { + if(install_name_dir && *install_name_dir) + { + dir = install_name_dir; + dir += "/"; + } + } + if(!install_name_dir) + { + if(this->Target->MacOSXRpathInstallNameDirDefault()) + { + dir = "@rpath/"; + } + } + return dir; + } + else + { + return ""; + } +} + +//---------------------------------------------------------------------------- +class cmTargetCollectLinkLanguages +{ +public: + cmTargetCollectLinkLanguages(cmGeneratorTarget const* target, + const std::string& config, + UNORDERED_SET<std::string>& languages, + cmTarget const* head): + Config(config), Languages(languages), HeadTarget(head), + Makefile(target->Target->GetMakefile()), Target(target) + { this->Visited.insert(target->Target); } + + void Visit(cmLinkItem const& item) + { + if(!item.Target) + { + if(item.find("::") != std::string::npos) + { + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; + std::stringstream e; + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028)) + { + case cmPolicies::WARN: + { + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } + break; + case cmPolicies::OLD: + noMessage = true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; + } + + if(!noMessage) + { + e << "Target \"" << this->Target->GetName() + << "\" links to target \"" << item + << "\" but the target was not found. Perhaps a find_package() " + "call is missing for an IMPORTED target, or an ALIAS target is " + "missing?"; + this->Makefile->GetCMakeInstance()->IssueMessage( + messageType, e.str(), this->Target->Target->GetBacktrace()); + } + } + return; + } + if(!this->Visited.insert(item.Target).second) + { + return; + } + cmGeneratorTarget* gtgt = + this->Target->GetLocalGenerator()->GetGlobalGenerator() + ->GetGeneratorTarget(item.Target); + cmLinkInterface const* iface = + gtgt->GetLinkInterface(this->Config, this->HeadTarget); + if(!iface) { return; } + + for(std::vector<std::string>::const_iterator + li = iface->Languages.begin(); li != iface->Languages.end(); ++li) + { + this->Languages.insert(*li); + } + + for(std::vector<cmLinkItem>::const_iterator + li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li) + { + this->Visit(*li); + } + } +private: + std::string Config; + UNORDERED_SET<std::string>& Languages; + cmTarget const* HeadTarget; + cmMakefile* Makefile; + const cmGeneratorTarget* Target; + std::set<cmTarget const*> Visited; +}; + +//---------------------------------------------------------------------------- +cmGeneratorTarget::LinkClosure const* +cmGeneratorTarget::GetLinkClosure(const std::string& config) const +{ + std::string key(cmSystemTools::UpperCase(config)); + LinkClosureMapType::iterator + i = this->LinkClosureMap.find(key); + if(i == this->LinkClosureMap.end()) + { + LinkClosure lc; + this->ComputeLinkClosure(config, lc); + LinkClosureMapType::value_type entry(key, lc); + i = this->LinkClosureMap.insert(entry).first; + } + return &i->second; +} + +//---------------------------------------------------------------------------- +class cmTargetSelectLinker +{ + int Preference; + cmGeneratorTarget const* Target; + cmMakefile* Makefile; + cmGlobalGenerator* GG; + std::set<std::string> Preferred; +public: + cmTargetSelectLinker(cmGeneratorTarget const* target) + : Preference(0), Target(target) + { + this->Makefile = this->Target->Makefile; + this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator(); + } + void Consider(const char* lang) + { + int preference = this->GG->GetLinkerPreference(lang); + if(preference > this->Preference) + { + this->Preference = preference; + this->Preferred.clear(); + } + if(preference == this->Preference) + { + this->Preferred.insert(lang); + } + } + std::string Choose() + { + if(this->Preferred.empty()) + { + return ""; + } + else if(this->Preferred.size() > 1) + { + std::stringstream e; + e << "Target " << this->Target->GetName() + << " contains multiple languages with the highest linker preference" + << " (" << this->Preference << "):\n"; + for(std::set<std::string>::const_iterator + li = this->Preferred.begin(); li != this->Preferred.end(); ++li) + { + e << " " << *li << "\n"; + } + e << "Set the LINKER_LANGUAGE property for this target."; + cmake* cm = this->Makefile->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->Target->GetBacktrace()); + } + return *this->Preferred.begin(); + } +}; + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ComputeLinkClosure(const std::string& config, + LinkClosure& lc) const +{ + // Get languages built in this target. + UNORDERED_SET<std::string> languages; + cmLinkImplementation const* impl = + this->GetLinkImplementation(config); + assert(impl); + for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); + li != impl->Languages.end(); ++li) + { + languages.insert(*li); + } + + // Add interface languages from linked targets. + cmTargetCollectLinkLanguages cll(this, config, languages, this->Target); + for(std::vector<cmLinkImplItem>::const_iterator li = impl->Libraries.begin(); + li != impl->Libraries.end(); ++li) + { + cll.Visit(*li); + } + + // Store the transitive closure of languages. + for(UNORDERED_SET<std::string>::const_iterator li = languages.begin(); + li != languages.end(); ++li) + { + lc.Languages.push_back(*li); + } + + // Choose the language whose linker should be used. + if(this->GetProperty("HAS_CXX")) + { + lc.LinkerLanguage = "CXX"; + } + else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) + { + lc.LinkerLanguage = linkerLang; + } + else + { + // Find the language with the highest preference value. + cmTargetSelectLinker tsl(this); + + // First select from the languages compiled directly in this target. + for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); + li != impl->Languages.end(); ++li) + { + tsl.Consider(li->c_str()); + } + + // Now consider languages that propagate from linked targets. + for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin(); + sit != languages.end(); ++sit) + { + std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES"; + if(this->Makefile->IsOn(propagates)) + { + tsl.Consider(sit->c_str()); + } + } + + lc.LinkerLanguage = tsl.Choose(); + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetFullNameComponents(std::string& prefix, + std::string& base, + std::string& suffix, + const std::string& config, + bool implib) const +{ + this->GetFullNameInternal(config, implib, prefix, base, suffix); +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::BuildMacContentDirectory(const std::string& base, + const std::string& config, + bool contentOnly) const +{ + std::string fpath = base; + if(this->Target->IsAppBundleOnApple()) + { + fpath += this->GetAppBundleDirectory(config, contentOnly); + } + if(this->Target->IsFrameworkOnApple()) + { + fpath += this->GetFrameworkDirectory(config, contentOnly); + } + if(this->Target->IsCFBundleOnApple()) + { + fpath += this->GetCFBundleDirectory(config, contentOnly); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetMacContentDirectory(const std::string& config, + bool implib) const +{ + // Start with the output directory for the target. + std::string fpath = this->Target->GetDirectory(config, implib); + fpath += "/"; + bool contentOnly = true; + if(this->Target->IsFrameworkOnApple()) + { + // additional files with a framework go into the version specific + // directory + contentOnly = false; + } + fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); + return fpath; +} + + +//---------------------------------------------------------------------------- +cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( + const std::string& config) const +{ + // There is no compile information for imported targets. + if(this->IsImported()) + { + return 0; + } + + if(this->GetType() > cmTarget::OBJECT_LIBRARY) + { + std::string msg = "cmTarget::GetCompileInfo called for "; + msg += this->GetName(); + msg += " which has type "; + msg += cmTarget::GetTargetTypeName(this->Target->GetType()); + this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + return 0; + } + + // Lookup/compute/cache the compile information for this configuration. + std::string config_upper; + if(!config.empty()) + { + config_upper = cmSystemTools::UpperCase(config); + } + CompileInfoMapType::const_iterator i = + this->CompileInfoMap.find(config_upper); + if(i == this->CompileInfoMap.end()) + { + CompileInfo info; + this->Target + ->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir); + CompileInfoMapType::value_type entry(config_upper, info); + i = this->CompileInfoMap.insert(entry).first; + } + return &i->second; +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetModuleDefinitionFile(const std::string& config) const { std::string data; @@ -611,6 +1537,83 @@ cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs, } //---------------------------------------------------------------------------- +void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string> &result, + const std::string& config) const +{ + const char *prop + = this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS", + config); + if (!prop) + { + return; + } + cmGeneratorExpression ge; + + cmGeneratorExpressionDAGChecker dagChecker( + this->GetName(), + "AUTOUIC_OPTIONS", 0, 0); + cmSystemTools::ExpandListArgument(ge.Parse(prop) + ->Evaluate(this->Makefile, + config, + false, + this->Target, + &dagChecker), + result); +} + +//---------------------------------------------------------------------------- +void processILibs(const std::string& config, + cmTarget const* headTarget, + cmLinkItem const& item, + cmGlobalGenerator* gg, + std::vector<cmTarget const*>& tgts, + std::set<cmTarget const*>& emitted) +{ + if (item.Target && emitted.insert(item.Target).second) + { + tgts.push_back(item.Target); + cmGeneratorTarget* gt = gg->GetGeneratorTarget(item.Target); + if(cmLinkInterfaceLibraries const* iface = + gt->GetLinkInterfaceLibraries(config, headTarget, true)) + { + for(std::vector<cmLinkItem>::const_iterator + it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + processILibs(config, headTarget, *it, gg, tgts, emitted); + } + } + } +} + +//---------------------------------------------------------------------------- +const std::vector<const cmTarget*>& +cmGeneratorTarget::GetLinkImplementationClosure( + const std::string& config) const +{ + LinkImplClosure& tgts = + this->LinkImplClosureMap[config]; + if(!tgts.Done) + { + tgts.Done = true; + std::set<cmTarget const*> emitted; + + cmLinkImplementationLibraries const* impl + = this->Target->GetLinkImplementationLibraries(config); + + for(std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + processILibs(config, this->Target, *it, + this->LocalGenerator->GetGlobalGenerator(), + tgts , emitted); + } + } + return tgts; +} + +//---------------------------------------------------------------------------- class cmTargetTraceDependencies { public: @@ -647,7 +1650,7 @@ cmTargetTraceDependencies { // Convenience. this->Makefile = this->Target->GetMakefile(); - this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); + this->GlobalGenerator = target->GetLocalGenerator()->GetGlobalGenerator(); this->CurrentEntry = 0; // Queue all the source files already specified for the target. @@ -677,7 +1680,8 @@ cmTargetTraceDependencies e << "Evaluation output file\n \"" << sf->GetFullPath() << "\"\ndepends on the sources of a target it is used in. This " "is a dependency loop and is not allowed."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->GeneratorTarget + ->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } if(emitted.insert(sf).second && this->SourcesQueued.insert(sf).second) @@ -799,7 +1803,8 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep) } // Check for a target with this name. - if(cmTarget* t = this->Makefile->FindTargetToUse(util)) + if(cmGeneratorTarget* t + = this->Makefile->FindGeneratorTargetToUse(util)) { // If we find the target and the dep was given as a full path, // then make sure it was not a full path to something else, and @@ -843,7 +1848,7 @@ cmTargetTraceDependencies { // Transform command names that reference targets built in this // project to corresponding target-level dependencies. - cmGeneratorExpression ge(&cc.GetBacktrace()); + cmGeneratorExpression ge(cc.GetBacktrace()); // Add target-level dependencies referenced by generator expressions. std::set<cmTarget*> targets; @@ -903,7 +1908,8 @@ void cmTargetTraceDependencies::FollowCommandDepends(cmCustomCommand const& cc, const std::string& config, std::set<std::string>& emitted) { - cmCustomCommandGenerator ccg(cc, config, this->Makefile); + cmCustomCommandGenerator ccg(cc, config, + this->GeneratorTarget->LocalGenerator); const std::vector<std::string>& depends = ccg.GetDepends(); @@ -952,6 +1958,16 @@ void cmGeneratorTarget::TraceDependencies() tracer.Trace(); } +std::string +cmGeneratorTarget::GetCompilePDBDirectory(const std::string& config) const +{ + if(CompileInfo const* info = this->GetCompileInfo(config)) + { + return info->CompilePdbDir; + } + return ""; +} + //---------------------------------------------------------------------------- void cmGeneratorTarget::GetAppleArchs(const std::string& config, std::vector<std::string>& archVec) const @@ -983,7 +1999,7 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang, case cmTarget::STATIC_LIBRARY: { std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY"; - if(this->Target->GetFeatureAsBool( + if(this->GetFeatureAsBool( "INTERPROCEDURAL_OPTIMIZATION", config)) { std::string varIPO = var + "_IPO"; @@ -1005,25 +2021,547 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang, } return ""; } +//---------------------------------------------------------------------------- +static void processIncludeDirectories(cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries, + std::vector<std::string> &includes, + UNORDERED_SET<std::string> &uniqueIncludes, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string& config, bool debugIncludes, + const std::string& language) +{ + cmMakefile *mf = tgt->Target->GetMakefile(); + + for (std::vector<cmGeneratorTarget::TargetPropertyEntry*>::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) + { + cmLinkImplItem const& item = (*it)->LinkImplItem; + std::string const& targetName = item; + bool const fromImported = item.Target && item.Target->IsImported(); + bool const checkCMP0027 = item.FromGenex; + std::vector<std::string> entryIncludes; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt->Target, + dagChecker, language), + entryIncludes); + + std::string usedIncludes; + for(std::vector<std::string>::iterator + li = entryIncludes.begin(); li != entryIncludes.end(); ++li) + { + if (fromImported + && !cmSystemTools::FileExists(li->c_str())) + { + std::ostringstream e; + cmake::MessageType messageType = cmake::FATAL_ERROR; + if (checkCMP0027) + { + switch(tgt->Target->GetPolicyStatusCMP0027()) + { + case cmPolicies::WARN: + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n"; + case cmPolicies::OLD: + messageType = cmake::AUTHOR_WARNING; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + break; + } + } + e << "Imported target \"" << targetName << "\" includes " + "non-existent path\n \"" << *li << "\"\nin its " + "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n" + "* The path was deleted, renamed, or moved to another " + "location.\n" + "* An install or uninstall procedure did not complete " + "successfully.\n" + "* The installation package was faulty and references files it " + "does not provide.\n"; + tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); + return; + } + + if (!cmSystemTools::FileIsFullPath(li->c_str())) + { + std::ostringstream e; + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; + if (!targetName.empty()) + { + e << "Target \"" << targetName << "\" contains relative " + "path in its INTERFACE_INCLUDE_DIRECTORIES:\n" + " \"" << *li << "\""; + } + else + { + switch(tgt->Target->GetPolicyStatusCMP0021()) + { + case cmPolicies::WARN: + { + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } + break; + case cmPolicies::OLD: + noMessage = true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; + } + e << "Found relative path while evaluating include directories of " + "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n"; + } + if (!noMessage) + { + tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); + if (messageType == cmake::FATAL_ERROR) + { + return; + } + } + } + + if (!cmSystemTools::IsOff(li->c_str())) + { + cmSystemTools::ConvertToUnixSlashes(*li); + } + std::string inc = *li; + + if(uniqueIncludes.insert(inc).second) + { + includes.push_back(inc); + if (debugIncludes) + { + usedIncludes += " * " + inc + "\n"; + } + } + } + if (!usedIncludes.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used includes for target ") + + tgt->GetName() + ":\n" + + usedIncludes, (*it)->ge->GetBacktrace()); + } + } +} + + +//---------------------------------------------------------------------------- +static void AddInterfaceEntries( + cmGeneratorTarget const* thisTarget, std::string const& config, + std::string const& prop, + std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries) +{ + if(cmLinkImplementationLibraries const* impl = + thisTarget->Target->GetLinkImplementationLibraries(config)) + { + for (std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(), end = impl->Libraries.end(); + it != end; ++it) + { + if(it->Target) + { + std::string genex = + "$<TARGET_PROPERTY:" + *it + "," + prop + ">"; + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); + cge->SetEvaluateForBuildsystem(true); + entries.push_back( + new cmGeneratorTarget::TargetPropertyEntry(cge, *it)); + } + } + } +} //---------------------------------------------------------------------------- std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(const std::string& config, const std::string& lang) const { - return this->Target->GetIncludeDirectories(config, lang); + std::vector<std::string> includes; + UNORDERED_SET<std::string> uniqueIncludes; + + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), + "INCLUDE_DIRECTORIES", 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugIncludes = !this->DebugIncludesDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "INCLUDE_DIRECTORIES") + != debugProperties.end(); + + if (this->Makefile->IsConfigured()) + { + this->DebugIncludesDone = true; + } + + processIncludeDirectories(this, + this->IncludeDirectoriesEntries, + includes, + uniqueIncludes, + &dagChecker, + config, + debugIncludes, + lang); + + std::vector<cmGeneratorTarget::TargetPropertyEntry*> + linkInterfaceIncludeDirectoriesEntries; + AddInterfaceEntries( + this, config, "INTERFACE_INCLUDE_DIRECTORIES", + linkInterfaceIncludeDirectoriesEntries); + + if(this->Makefile->IsOn("APPLE")) + { + cmLinkImplementationLibraries const* impl = + this->Target->GetLinkImplementationLibraries(config); + for(std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + std::string libDir = cmSystemTools::CollapseFullPath(*it); + + static cmsys::RegularExpression + frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); + if(!frameworkCheck.find(libDir)) + { + continue; + } + + libDir = frameworkCheck.match(1); + + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(libDir.c_str()); + linkInterfaceIncludeDirectoriesEntries + .push_back(new cmGeneratorTarget::TargetPropertyEntry(cge)); + } + } + + processIncludeDirectories(this, + linkInterfaceIncludeDirectoriesEntries, + includes, + uniqueIncludes, + &dagChecker, + config, + debugIncludes, + lang); + + cmDeleteAll(linkInterfaceIncludeDirectoriesEntries); + + return includes; +} + +//---------------------------------------------------------------------------- +static void processCompileOptionsInternal(cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + UNORDERED_SET<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string& config, bool debugOptions, const char *logName, + std::string const& language) +{ + cmMakefile *mf = tgt->Target->GetMakefile(); + + for (std::vector<cmGeneratorTarget::TargetPropertyEntry*>::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) + { + std::vector<std::string> entryOptions; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt->Target, + dagChecker, + language), + entryOptions); + std::string usedOptions; + for(std::vector<std::string>::iterator + li = entryOptions.begin(); li != entryOptions.end(); ++li) + { + std::string const& opt = *li; + + if(uniqueOptions.insert(opt).second) + { + options.push_back(opt); + if (debugOptions) + { + usedOptions += " * " + opt + "\n"; + } + } + } + if (!usedOptions.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used compile ") + logName + + std::string(" for target ") + + tgt->GetName() + ":\n" + + usedOptions, (*it)->ge->GetBacktrace()); + } + } +} + +//---------------------------------------------------------------------------- +static void processCompileOptions(cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + UNORDERED_SET<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string& config, bool debugOptions, + std::string const& language) +{ + processCompileOptionsInternal(tgt, entries, options, uniqueOptions, + dagChecker, config, debugOptions, "options", + language); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetCompileOptions(std::vector<std::string> &result, + const std::string& config, + const std::string& language) const +{ + UNORDERED_SET<std::string> uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), + "COMPILE_OPTIONS", 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugOptions = !this->DebugCompileOptionsDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "COMPILE_OPTIONS") + != debugProperties.end(); + + if (this->Makefile->IsConfigured()) + { + this->DebugCompileOptionsDone = true; + } + + processCompileOptions(this, + this->CompileOptionsEntries, + result, + uniqueOptions, + &dagChecker, + config, + debugOptions, + language); + + std::vector<cmGeneratorTarget::TargetPropertyEntry*> + linkInterfaceCompileOptionsEntries; + + AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_OPTIONS", + linkInterfaceCompileOptionsEntries); + + processCompileOptions(this, + linkInterfaceCompileOptionsEntries, + result, + uniqueOptions, + &dagChecker, + config, + debugOptions, + language); + + cmDeleteAll(linkInterfaceCompileOptionsEntries); +} + +//---------------------------------------------------------------------------- +static void processCompileFeatures(cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + UNORDERED_SET<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string& config, bool debugOptions) +{ + processCompileOptionsInternal(tgt, entries, options, uniqueOptions, + dagChecker, config, debugOptions, "features", + std::string()); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string> &result, + const std::string& config) const +{ + UNORDERED_SET<std::string> uniqueFeatures; + + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), + "COMPILE_FEATURES", + 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugFeatures = !this->DebugCompileFeaturesDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "COMPILE_FEATURES") + != debugProperties.end(); + + if (this->Makefile->IsConfigured()) + { + this->DebugCompileFeaturesDone = true; + } + + processCompileFeatures(this, + this->CompileFeaturesEntries, + result, + uniqueFeatures, + &dagChecker, + config, + debugFeatures); + + std::vector<cmGeneratorTarget::TargetPropertyEntry*> + linkInterfaceCompileFeaturesEntries; + AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_FEATURES", + linkInterfaceCompileFeaturesEntries); + + processCompileFeatures(this, + linkInterfaceCompileFeaturesEntries, + result, + uniqueFeatures, + &dagChecker, + config, + debugFeatures); + + cmDeleteAll(linkInterfaceCompileFeaturesEntries); +} + +//---------------------------------------------------------------------------- +static void processCompileDefinitions(cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + UNORDERED_SET<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string& config, bool debugOptions, + std::string const& language) +{ + processCompileOptionsInternal(tgt, entries, options, uniqueOptions, + dagChecker, config, debugOptions, + "definitions", language); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetCompileDefinitions(std::vector<std::string> &list, + const std::string& config, + const std::string& language) const +{ + UNORDERED_SET<std::string> uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), + "COMPILE_DEFINITIONS", 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugDefines = !this->DebugCompileDefinitionsDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "COMPILE_DEFINITIONS") + != debugProperties.end(); + + if (this->Makefile->IsConfigured()) + { + this->DebugCompileDefinitionsDone = true; + } + + processCompileDefinitions(this, + this->CompileDefinitionsEntries, + list, + uniqueOptions, + &dagChecker, + config, + debugDefines, + language); + + std::vector<cmGeneratorTarget::TargetPropertyEntry*> + linkInterfaceCompileDefinitionsEntries; + AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_DEFINITIONS", + linkInterfaceCompileDefinitionsEntries); + if (!config.empty()) + { + std::string configPropName = "COMPILE_DEFINITIONS_" + + cmSystemTools::UpperCase(config); + const char *configProp = this->Target->GetProperty(configPropName); + if (configProp) + { + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) + { + case cmPolicies::WARN: + { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); + this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, + e.str()); + } + case cmPolicies::OLD: + { + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(configProp); + linkInterfaceCompileDefinitionsEntries + .push_back(new cmGeneratorTarget::TargetPropertyEntry(cge)); + } + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + break; + } + } + } + + processCompileDefinitions(this, + linkInterfaceCompileDefinitionsEntries, + list, + uniqueOptions, + &dagChecker, + config, + debugDefines, + language); + + cmDeleteAll(linkInterfaceCompileDefinitionsEntries); } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GenerateTargetManifest( +void cmGeneratorTarget::ComputeTargetManifest( const std::string& config) const { if (this->Target->IsImported()) { return; } - cmMakefile* mf = this->Target->GetMakefile(); - cmGlobalGenerator* gg = mf->GetGlobalGenerator(); + cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator(); // Get the names. std::string name; @@ -1033,14 +2571,13 @@ void cmGeneratorTarget::GenerateTargetManifest( std::string pdbName; if(this->GetType() == cmTarget::EXECUTABLE) { - this->Target->GetExecutableNames(name, realName, impName, pdbName, - config); + this->GetExecutableNames(name, realName, impName, pdbName, config); } else if(this->GetType() == cmTarget::STATIC_LIBRARY || this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY) { - this->Target->GetLibraryNames(name, soName, realName, impName, pdbName, + this->GetLibraryNames(name, soName, realName, impName, pdbName, config); } else @@ -1058,36 +2595,451 @@ void cmGeneratorTarget::GenerateTargetManifest( f = dir; f += "/"; f += name; - gg->AddToManifest(config, f); + gg->AddToManifest(f); } if(!soName.empty()) { f = dir; f += "/"; f += soName; - gg->AddToManifest(config, f); + gg->AddToManifest(f); } if(!realName.empty()) { f = dir; f += "/"; f += realName; - gg->AddToManifest(config, f); + gg->AddToManifest(f); } if(!pdbName.empty()) { f = dir; f += "/"; f += pdbName; - gg->AddToManifest(config, f); + gg->AddToManifest(f); } if(!impName.empty()) { f = this->Target->GetDirectory(config, true); f += "/"; f += impName; - gg->AddToManifest(config, f); + gg->AddToManifest(f); + } +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetFullPath(const std::string& config, + bool implib, bool realname) const +{ + if(this->Target->IsImported()) + { + return this->Target->ImportedGetFullPath(config, implib); + } + else + { + return this->NormalGetFullPath(config, implib, realname); + } +} + +std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config, + bool implib, + bool realname) const +{ + std::string fpath = this->Target->GetDirectory(config, implib); + fpath += "/"; + if(this->Target->IsAppBundleOnApple()) + { + fpath = this->BuildMacContentDirectory(fpath, config, false); + fpath += "/"; + } + + // Add the full name of the target. + if(implib) + { + fpath += this->GetFullName(config, true); + } + else if(realname) + { + fpath += this->NormalGetRealName(config); + } + else + { + fpath += this->GetFullName(config, false); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::NormalGetRealName(const std::string& config) const +{ + // This should not be called for imported targets. + // TODO: Split cmTarget into a class hierarchy to get compile-time + // enforcement of the limited imported target API. + if(this->Target->IsImported()) + { + std::string msg = "NormalGetRealName called on imported target: "; + msg += this->GetName(); + this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + } + + if(this->GetType() == cmTarget::EXECUTABLE) + { + // Compute the real name that will be built. + std::string name; + std::string realName; + std::string impName; + std::string pdbName; + this->GetExecutableNames(name, realName, impName, pdbName, config); + return realName; + } + else + { + // Compute the real name that will be built. + std::string name; + std::string soName; + std::string realName; + std::string impName; + std::string pdbName; + this->GetLibraryNames(name, soName, realName, + impName, pdbName, config); + return realName; + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetLibraryNames(std::string& name, + std::string& soName, + std::string& realName, + std::string& impName, + std::string& pdbName, + const std::string& config) const +{ + // This should not be called for imported targets. + // TODO: Split cmTarget into a class hierarchy to get compile-time + // enforcement of the limited imported target API. + if(this->Target->IsImported()) + { + std::string msg = "GetLibraryNames called on imported target: "; + msg += this->GetName(); + this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, + msg); + return; + } + + // Check for library version properties. + const char* version = this->GetProperty("VERSION"); + const char* soversion = this->GetProperty("SOVERSION"); + if(!this->HasSOName(config) || + this->Target->IsFrameworkOnApple()) + { + // Versioning is supported only for shared libraries and modules, + // and then only when the platform supports an soname flag. + version = 0; + soversion = 0; + } + if(version && !soversion) + { + // The soversion must be set if the library version is set. Use + // the library version as the soversion. + soversion = version; + } + if(!version && soversion) + { + // Use the soversion as the library version. + version = soversion; + } + + // Get the components of the library name. + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // The library name. + name = prefix+base+suffix; + + if(this->Target->IsFrameworkOnApple()) + { + realName = prefix; + if(!this->Makefile->PlatformIsAppleIos()) + { + realName += "Versions/"; + realName += this->Target->GetFrameworkVersion(); + realName += "/"; + } + realName += base; + soName = realName; + } + else + { + // The library's soname. + this->Target->ComputeVersionedName(soName, prefix, base, suffix, + name, soversion); + + // The library's real name on disk. + this->Target->ComputeVersionedName(realName, prefix, base, suffix, + name, version); + } + + // The import library name. + if(this->GetType() == cmTarget::SHARED_LIBRARY || + this->GetType() == cmTarget::MODULE_LIBRARY) + { + impName = this->GetFullNameInternal(config, true); + } + else + { + impName = ""; + } + + // The program database file name. + pdbName = this->GetPDBName(config); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetExecutableNames(std::string& name, + std::string& realName, + std::string& impName, + std::string& pdbName, + const std::string& config) const +{ + // This should not be called for imported targets. + // TODO: Split cmTarget into a class hierarchy to get compile-time + // enforcement of the limited imported target API. + if(this->Target->IsImported()) + { + std::string msg = + "GetExecutableNames called on imported target: "; + msg += this->GetName(); + this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + } + + // This versioning is supported only for executables and then only + // when the platform supports symbolic links. +#if defined(_WIN32) && !defined(__CYGWIN__) + const char* version = 0; +#else + // Check for executable version properties. + const char* version = this->GetProperty("VERSION"); + if(this->GetType() != cmTarget::EXECUTABLE || this->Makefile->IsOn("XCODE")) + { + version = 0; + } +#endif + + // Get the components of the executable name. + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // The executable name. + name = prefix+base+suffix; + + // The executable's real name on disk. +#if defined(__CYGWIN__) + realName = prefix+base; +#else + realName = name; +#endif + if(version) + { + realName += "-"; + realName += version; + } +#if defined(__CYGWIN__) + realName += suffix; +#endif + + // The import library name. + impName = this->GetFullNameInternal(config, true); + + // The program database file name. + pdbName = this->GetPDBName(config); +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetFullNameInternal(const std::string& config, + bool implib) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, implib, prefix, base, suffix); + return prefix+base+suffix; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetFullNameInternal(const std::string& config, + bool implib, + std::string& outPrefix, + std::string& outBase, + std::string& outSuffix) const +{ + // Use just the target name for non-main target types. + if(this->GetType() != cmTarget::STATIC_LIBRARY && + this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY && + this->GetType() != cmTarget::EXECUTABLE) + { + outPrefix = ""; + outBase = this->GetName(); + outSuffix = ""; + return; + } + + // Return an empty name for the import library if this platform + // does not support import libraries. + if(implib && + !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) + { + outPrefix = ""; + outBase = ""; + outSuffix = ""; + return; + } + + // The implib option is only allowed for shared libraries, module + // libraries, and executables. + if(this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY && + this->GetType() != cmTarget::EXECUTABLE) + { + implib = false; + } + + // Compute the full name for main target types. + const char* targetPrefix = (implib + ? this->GetProperty("IMPORT_PREFIX") + : this->GetProperty("PREFIX")); + const char* targetSuffix = (implib + ? this->GetProperty("IMPORT_SUFFIX") + : this->GetProperty("SUFFIX")); + const char* configPostfix = 0; + if(!config.empty()) + { + std::string configProp = cmSystemTools::UpperCase(config); + configProp += "_POSTFIX"; + configPostfix = this->GetProperty(configProp); + // Mac application bundles and frameworks have no postfix. + if(configPostfix && + (this->Target->IsAppBundleOnApple() + || this->Target->IsFrameworkOnApple())) + { + configPostfix = 0; + } + } + const char* prefixVar = this->Target->GetPrefixVariableInternal(implib); + const char* suffixVar = this->Target->GetSuffixVariableInternal(implib); + + // Check for language-specific default prefix and suffix. + std::string ll = this->GetLinkerLanguage(config); + if(!ll.empty()) + { + if(!targetSuffix && suffixVar && *suffixVar) + { + std::string langSuff = suffixVar + std::string("_") + ll; + targetSuffix = this->Makefile->GetDefinition(langSuff); + } + if(!targetPrefix && prefixVar && *prefixVar) + { + std::string langPrefix = prefixVar + std::string("_") + ll; + targetPrefix = this->Makefile->GetDefinition(langPrefix); + } + } + + // if there is no prefix on the target use the cmake definition + if(!targetPrefix && prefixVar) + { + targetPrefix = this->Makefile->GetSafeDefinition(prefixVar); + } + // if there is no suffix on the target use the cmake definition + if(!targetSuffix && suffixVar) + { + targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); + } + + // frameworks have directory prefix but no suffix + std::string fw_prefix; + if(this->Target->IsFrameworkOnApple()) + { + fw_prefix = this->GetOutputName(config, false); + fw_prefix += ".framework/"; + targetPrefix = fw_prefix.c_str(); + targetSuffix = 0; + } + + if(this->Target->IsCFBundleOnApple()) + { + fw_prefix = this->GetCFBundleDirectory(config, false); + fw_prefix += "/"; + targetPrefix = fw_prefix.c_str(); + targetSuffix = 0; } + + // Begin the final name with the prefix. + outPrefix = targetPrefix?targetPrefix:""; + + // Append the target name or property-specified name. + outBase += this->GetOutputName(config, implib); + + // Append the per-configuration postfix. + outBase += configPostfix?configPostfix:""; + + // Name shared libraries with their version number on some platforms. + if(const char* soversion = this->GetProperty("SOVERSION")) + { + if(this->GetType() == cmTarget::SHARED_LIBRARY && !implib && + this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) + { + outBase += "-"; + outBase += soversion; + } + } + + // Append the suffix. + outSuffix = targetSuffix?targetSuffix:""; +} + + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetLinkerLanguage(const std::string& config) const +{ + return this->GetLinkClosure(config)->LinkerLanguage; +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetPDBName(const std::string& config) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + std::vector<std::string> props; + std::string configUpper = + cmSystemTools::UpperCase(config); + if(!configUpper.empty()) + { + // PDB_NAME_<CONFIG> + props.push_back("PDB_NAME_" + configUpper); + } + + // PDB_NAME + props.push_back("PDB_NAME"); + + for(std::vector<std::string>::const_iterator i = props.begin(); + i != props.end(); ++i) + { + if(const char* outName = this->GetProperty(*i)) + { + base = outName; + break; + } + } + return prefix+base+".pdb"; } bool cmStrictTargetComparison::operator()(cmTarget const* t1, @@ -1195,3 +3147,1407 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const } } } + +//---------------------------------------------------------------------------- +const cmGeneratorTarget::CompatibleInterfacesBase& +cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const +{ + cmGeneratorTarget::CompatibleInterfaces& compat = + this->CompatibleInterfacesMap[config]; + if(!compat.Done) + { + compat.Done = true; + compat.PropsBool.insert("POSITION_INDEPENDENT_CODE"); + compat.PropsString.insert("AUTOUIC_OPTIONS"); + std::vector<cmTarget const*> const& deps = + this->GetLinkImplementationClosure(config); + for(std::vector<cmTarget const*>::const_iterator li = deps.begin(); + li != deps.end(); ++li) + { +#define CM_READ_COMPATIBLE_INTERFACE(X, x) \ + if(const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) \ + { \ + std::vector<std::string> props; \ + cmSystemTools::ExpandListArgument(prop, props); \ + compat.Props##x.insert(props.begin(), props.end()); \ + } + CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) + CM_READ_COMPATIBLE_INTERFACE(STRING, String) + CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin) + CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax) +#undef CM_READ_COMPATIBLE_INTERFACE + } + } + return compat; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentBoolProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentStringProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMinProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMaxProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0; +} + +enum CompatibleType +{ + BoolType, + StringType, + NumberMinType, + NumberMaxType +}; + +template<typename PropertyType> +PropertyType getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt, + const std::string& prop, + const std::string& config, + CompatibleType, + PropertyType *); + +template<> +bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt, + const std::string& prop, + const std::string& config, + CompatibleType, bool *) +{ + return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); +} + +template<> +const char * getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt, + const std::string& prop, + const std::string& config, + CompatibleType t, + const char **) +{ + switch(t) + { + case BoolType: + assert(0 && "String compatibility check function called for boolean"); + return 0; + case StringType: + return tgt->GetLinkInterfaceDependentStringProperty(prop, config); + case NumberMinType: + return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config); + case NumberMaxType: + return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config); + } + assert(0 && "Unreachable!"); + return 0; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +void checkPropertyConsistency(cmGeneratorTarget const* depender, + cmTarget const* dependee, + const std::string& propName, + std::set<std::string> &emitted, + const std::string& config, + CompatibleType t, + PropertyType *) +{ + const char *prop = dependee->GetProperty(propName); + if (!prop) + { + return; + } + + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(prop, props); + std::string pdir = + dependee->GetMakefile()->GetRequiredDefinition("CMAKE_ROOT"); + pdir += "/Help/prop_tgt/"; + + for(std::vector<std::string>::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + std::string pname = cmSystemTools::HelpFileName(*pi); + std::string pfile = pdir + pname + ".rst"; + if(cmSystemTools::FileExists(pfile.c_str(), true)) + { + std::ostringstream e; + e << "Target \"" << dependee->GetName() << "\" has property \"" + << *pi << "\" listed in its " << propName << " property. " + "This is not allowed. Only user-defined properties may appear " + "listed in the " << propName << " property."; + depender->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if(emitted.insert(*pi).second) + { + getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, + t, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + } +} + +static std::string intersect(const std::set<std::string> &s1, + const std::set<std::string> &s2) +{ + std::set<std::string> intersect; + std::set_intersection(s1.begin(),s1.end(), + s2.begin(),s2.end(), + std::inserter(intersect,intersect.begin())); + if (!intersect.empty()) + { + return *intersect.begin(); + } + return ""; +} + +static std::string intersect(const std::set<std::string> &s1, + const std::set<std::string> &s2, + const std::set<std::string> &s3) +{ + std::string result; + result = intersect(s1, s2); + if (!result.empty()) + return result; + result = intersect(s1, s3); + if (!result.empty()) + return result; + return intersect(s2, s3); +} + +static std::string intersect(const std::set<std::string> &s1, + const std::set<std::string> &s2, + const std::set<std::string> &s3, + const std::set<std::string> &s4) +{ + std::string result; + result = intersect(s1, s2); + if (!result.empty()) + return result; + result = intersect(s1, s3); + if (!result.empty()) + return result; + result = intersect(s1, s4); + if (!result.empty()) + return result; + return intersect(s2, s3, s4); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::CheckPropertyCompatibility( + cmComputeLinkInformation *info, const std::string& config) const +{ + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + + std::set<std::string> emittedBools; + static std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; + std::set<std::string> emittedStrings; + static std::string strString = "COMPATIBLE_INTERFACE_STRING"; + std::set<std::string> emittedMinNumbers; + static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; + std::set<std::string> emittedMaxNumbers; + static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); li != deps.end(); ++li) + { + if (!li->Target) + { + continue; + } + + checkPropertyConsistency<bool>(this, li->Target, + strBool, + emittedBools, config, BoolType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + strString, + emittedStrings, config, + StringType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + strNumMin, + emittedMinNumbers, config, + NumberMinType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + strNumMax, + emittedMaxNumbers, config, + NumberMaxType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + + std::string prop = intersect(emittedBools, + emittedStrings, + emittedMinNumbers, + emittedMaxNumbers); + + if (!prop.empty()) + { + // Use a sorted std::vector to keep the error message sorted. + std::vector<std::string> props; + std::set<std::string>::const_iterator i = emittedBools.find(prop); + if (i != emittedBools.end()) + { + props.push_back(strBool); + } + i = emittedStrings.find(prop); + if (i != emittedStrings.end()) + { + props.push_back(strString); + } + i = emittedMinNumbers.find(prop); + if (i != emittedMinNumbers.end()) + { + props.push_back(strNumMin); + } + i = emittedMaxNumbers.find(prop); + if (i != emittedMaxNumbers.end()) + { + props.push_back(strNumMax); + } + std::sort(props.begin(), props.end()); + + std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", "); + propsString += " and the " + props.back(); + + std::ostringstream e; + e << "Property \"" << prop << "\" appears in both the " + << propsString << + " property in the dependencies of target \"" << this->GetName() << + "\". This is not allowed. A property may only require compatibility " + "in a boolean interpretation, a numeric minimum, a numeric maximum or a " + "string interpretation, but not a mixture."; + this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + } +} + +//---------------------------------------------------------------------------- +std::string compatibilityType(CompatibleType t) +{ + switch(t) + { + case BoolType: + return "Boolean compatibility"; + case StringType: + return "String compatibility"; + case NumberMaxType: + return "Numeric maximum compatibility"; + case NumberMinType: + return "Numeric minimum compatibility"; + } + assert(0 && "Unreachable!"); + return ""; +} + +//---------------------------------------------------------------------------- +std::string compatibilityAgree(CompatibleType t, bool dominant) +{ + switch(t) + { + case BoolType: + case StringType: + return dominant ? "(Disagree)\n" : "(Agree)\n"; + case NumberMaxType: + case NumberMinType: + return dominant ? "(Dominant)\n" : "(Ignored)\n"; + } + assert(0 && "Unreachable!"); + return ""; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop); + +//---------------------------------------------------------------------------- +template<> +bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop) +{ + return tgt->GetPropertyAsBool(prop); +} + +//---------------------------------------------------------------------------- +template<> +const char *getTypedProperty<const char *>(cmTarget const* tgt, + const std::string& prop) +{ + return tgt->GetProperty(prop); +} + +template<typename PropertyType> +std::string valueAsString(PropertyType); +template<> +std::string valueAsString<bool>(bool value) +{ + return value ? "TRUE" : "FALSE"; +} +template<> +std::string valueAsString<const char*>(const char* value) +{ + return value ? value : "(unset)"; +} + +template<typename PropertyType> +PropertyType impliedValue(PropertyType); +template<> +bool impliedValue<bool>(bool) +{ + return false; +} +template<> +const char* impliedValue<const char*>(const char*) +{ + return ""; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +std::pair<bool, PropertyType> consistentProperty(PropertyType lhs, + PropertyType rhs, + CompatibleType t); + +//---------------------------------------------------------------------------- +template<> +std::pair<bool, bool> consistentProperty(bool lhs, bool rhs, + CompatibleType) +{ + return std::make_pair(lhs == rhs, lhs); +} + +//---------------------------------------------------------------------------- +std::pair<bool, const char*> consistentStringProperty(const char *lhs, + const char *rhs) +{ + const bool b = strcmp(lhs, rhs) == 0; + return std::make_pair(b, b ? lhs : 0); +} + +//---------------------------------------------------------------------------- +std::pair<bool, const char*> consistentNumberProperty(const char *lhs, + const char *rhs, + CompatibleType t) +{ + char *pEnd; + + const char* const null_ptr = 0; + + long lnum = strtol(lhs, &pEnd, 0); + if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) + { + return std::pair<bool, const char*>(false, null_ptr); + } + + long rnum = strtol(rhs, &pEnd, 0); + if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) + { + return std::pair<bool, const char*>(false, null_ptr); + } + + if (t == NumberMaxType) + { + return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs); + } + else + { + return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs); + } +} + +//---------------------------------------------------------------------------- +template<> +std::pair<bool, const char*> consistentProperty(const char *lhs, + const char *rhs, + CompatibleType t) +{ + if (!lhs && !rhs) + { + return std::make_pair(true, lhs); + } + if (!lhs) + { + return std::make_pair(true, rhs); + } + if (!rhs) + { + return std::make_pair(true, lhs); + } + + const char* const null_ptr = 0; + + switch(t) + { + case BoolType: + assert(0 && "consistentProperty for strings called with BoolType"); + return std::pair<bool, const char*>(false, null_ptr); + case StringType: + return consistentStringProperty(lhs, rhs); + case NumberMinType: + case NumberMaxType: + return consistentNumberProperty(lhs, rhs, t); + } + assert(0 && "Unreachable!"); + return std::pair<bool, const char*>(false, null_ptr); +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, + const std::string &p, + const std::string& config, + const char *defaultValue, + CompatibleType t, + PropertyType *) +{ + PropertyType propContent = getTypedProperty<PropertyType>(tgt->Target, p); + const bool explicitlySet = tgt->Target->GetProperties() + .find(p) + != tgt->Target->GetProperties().end(); + const bool impliedByUse = + tgt->Target->IsNullImpliedByLinkLibraries(p); + assert((impliedByUse ^ explicitlySet) + || (!impliedByUse && !explicitlySet)); + + std::vector<cmTarget const*> const& deps = + tgt->GetLinkImplementationClosure(config); + + if(deps.empty()) + { + return propContent; + } + bool propInitialized = explicitlySet; + + std::string report = " * Target \""; + report += tgt->GetName(); + if (explicitlySet) + { + report += "\" has property content \""; + report += valueAsString<PropertyType>(propContent); + report += "\"\n"; + } + else if (impliedByUse) + { + report += "\" property is implied by use.\n"; + } + else + { + report += "\" property not set.\n"; + } + + std::string interfaceProperty = "INTERFACE_" + p; + for(std::vector<cmTarget const*>::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + // An error should be reported if one dependency + // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other + // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the + // target itself has a POSITION_INDEPENDENT_CODE which disagrees + // with a dependency. + + cmTarget const* theTarget = *li; + + const bool ifaceIsSet = theTarget->GetProperties() + .find(interfaceProperty) + != theTarget->GetProperties().end(); + PropertyType ifacePropContent = + getTypedProperty<PropertyType>(theTarget, + interfaceProperty); + + std::string reportEntry; + if (ifaceIsSet) + { + reportEntry += " * Target \""; + reportEntry += theTarget->GetName(); + reportEntry += "\" property value \""; + reportEntry += valueAsString<PropertyType>(ifacePropContent); + reportEntry += "\" "; + } + + if (explicitlySet) + { + if (ifaceIsSet) + { + std::pair<bool, PropertyType> consistent = + consistentProperty(propContent, + ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) + { + std::ostringstream e; + e << "Property " << p << " on target \"" + << tgt->GetName() << "\" does\nnot match the " + "INTERFACE_" << p << " property requirement\nof " + "dependency \"" << theTarget->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + break; + } + else + { + propContent = consistent.second; + continue; + } + } + else + { + // Explicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else if (impliedByUse) + { + propContent = impliedValue<PropertyType>(propContent); + + if (ifaceIsSet) + { + std::pair<bool, PropertyType> consistent = + consistentProperty(propContent, + ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) + { + std::ostringstream e; + e << "Property " << p << " on target \"" + << tgt->GetName() << "\" is\nimplied to be " << defaultValue + << " because it was used to determine the link libraries\n" + "already. The INTERFACE_" << p << " property on\ndependency \"" + << theTarget->GetName() << "\" is in conflict.\n"; + cmSystemTools::Error(e.str().c_str()); + break; + } + else + { + propContent = consistent.second; + continue; + } + } + else + { + // Implicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else + { + if (ifaceIsSet) + { + if (propInitialized) + { + std::pair<bool, PropertyType> consistent = + consistentProperty(propContent, + ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) + { + std::ostringstream e; + e << "The INTERFACE_" << p << " property of \"" + << theTarget->GetName() << "\" does\nnot agree with the value " + "of " << p << " already determined\nfor \"" + << tgt->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + break; + } + else + { + propContent = consistent.second; + continue; + } + } + else + { + report += reportEntry + "(Interface set)\n"; + propContent = ifacePropContent; + propInitialized = true; + } + } + else + { + // Not set. Nothing to agree on. + continue; + } + } + } + + tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent), + report, compatibilityType(t)); + return propContent; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty( + const std::string &p, const std::string& config) const +{ + return checkInterfacePropertyCompatibility<bool>(this, p, config, + "FALSE", + BoolType, 0); +} + +//---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty( + const std::string &p, + const std::string& config) const +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + StringType, 0); +} + +//---------------------------------------------------------------------------- +const char * cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty( + const std::string &p, + const std::string& config) const +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + NumberMinType, 0); +} + +//---------------------------------------------------------------------------- +const char * cmGeneratorTarget::GetLinkInterfaceDependentNumberMaxProperty( + const std::string &p, + const std::string& config) const +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + NumberMaxType, 0); +} + +//---------------------------------------------------------------------------- +cmComputeLinkInformation* +cmGeneratorTarget::GetLinkInformation(const std::string& config) const +{ + // Lookup any existing information for this configuration. + std::string key(cmSystemTools::UpperCase(config)); + cmTargetLinkInformationMap::iterator + i = this->LinkInformation.find(key); + if(i == this->LinkInformation.end()) + { + // Compute information for this configuration. + cmComputeLinkInformation* info = + new cmComputeLinkInformation(this, config); + if(!info || !info->Compute()) + { + delete info; + info = 0; + } + + // Store the information for this configuration. + cmTargetLinkInformationMap::value_type entry(key, info); + i = this->LinkInformation.insert(entry).first; + + if (info) + { + this->CheckPropertyCompatibility(info, config); + } + } + return i->second; +} + +//---------------------------------------------------------------------------- +void +cmGeneratorTarget::ReportPropertyOrigin(const std::string &p, + const std::string &result, + const std::string &report, + const std::string &compatibilityType) const +{ + std::vector<std::string> debugProperties; + const char *debugProp = this->Target->GetMakefile() + ->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] + && std::find(debugProperties.begin(), + debugProperties.end(), + p) + != debugProperties.end(); + + if (this->Target->GetMakefile()->IsConfigured()) + { + this->DebugCompatiblePropertiesDone[p] = true; + } + if (!debugOrigin) + { + return; + } + + std::string areport = compatibilityType; + areport += std::string(" of property \"") + p + "\" for target \""; + areport += std::string(this->GetName()); + areport += "\" (result: \""; + areport += result; + areport += "\"):\n" + report; + + this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, + std::vector<cmLinkItem>& items) const +{ + for(std::vector<std::string>::const_iterator i = names.begin(); + i != names.end(); ++i) + { + std::string name = this->Target->CheckCMP0004(*i); + if(name == this->GetName() || name.empty()) + { + continue; + } + items.push_back(cmLinkItem(name, this->Target->FindTargetToLink(name))); + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ExpandLinkItems(std::string const& prop, + std::string const& value, + std::string const& config, + cmTarget const* headTarget, + bool usage_requirements_only, + std::vector<cmLinkItem>& items, + bool& hadHeadSensitiveCondition) const +{ + cmGeneratorExpression ge; + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0); + // The $<LINK_ONLY> expression may be in a link interface to specify private + // link dependencies that are otherwise excluded from usage requirements. + if(usage_requirements_only) + { + dagChecker.SetTransitivePropertiesOnly(); + } + std::vector<std::string> libs; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + cmSystemTools::ExpandListArgument(cge->Evaluate( + this->Makefile, + config, + false, + headTarget, + this->Target, &dagChecker), libs); + this->LookupLinkItems(libs, items); + hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); +} + +//---------------------------------------------------------------------------- +cmLinkInterface const* +cmGeneratorTarget::GetLinkInterface(const std::string& config, + cmTarget const* head) const +{ + // Imported targets have their own link interface. + if(this->IsImported()) + { + return this->GetImportLinkInterface(config, head, false); + } + + // Link interfaces are not supported for executables that do not + // export symbols. + if(this->GetType() == cmTarget::EXECUTABLE && + !this->Target->IsExecutableWithExports()) + { + return 0; + } + + // Lookup any existing link interface for this configuration. + cmHeadToLinkInterfaceMap& hm = + this->GetHeadToLinkInterfaceMap(config); + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + + cmOptionalLinkInterface& iface = hm[head]; + if(!iface.LibrariesDone) + { + iface.LibrariesDone = true; + this->ComputeLinkInterfaceLibraries( + config, iface, head, false); + } + if(!iface.AllDone) + { + iface.AllDone = true; + if(iface.Exists) + { + this->ComputeLinkInterface(config, iface, head); + } + } + + return iface.Exists? &iface : 0; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ComputeLinkInterface(const std::string& config, + cmOptionalLinkInterface &iface, + cmTarget const* headTarget) const +{ + if(iface.ExplicitLibraries) + { + if(this->GetType() == cmTarget::SHARED_LIBRARY + || this->GetType() == cmTarget::STATIC_LIBRARY + || this->GetType() == cmTarget::INTERFACE_LIBRARY) + { + // Shared libraries may have runtime implementation dependencies + // on other shared libraries that are not in the interface. + UNORDERED_SET<std::string> emitted; + for(std::vector<cmLinkItem>::const_iterator + li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) + { + emitted.insert(*li); + } + if (this->GetType() != cmTarget::INTERFACE_LIBRARY) + { + cmLinkImplementation const* impl = + this->GetLinkImplementation(config); + for(std::vector<cmLinkImplItem>::const_iterator + li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) + { + if(emitted.insert(*li).second) + { + if(li->Target) + { + // This is a runtime dependency on another shared library. + if(li->Target->GetType() == cmTarget::SHARED_LIBRARY) + { + iface.SharedDeps.push_back(*li); + } + } + else + { + // TODO: Recognize shared library file names. Perhaps this + // should be moved to cmComputeLinkInformation, but that creates + // a chicken-and-egg problem since this list is needed for its + // construction. + } + } + } + } + } + } + else if (this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN + || this->Target->GetPolicyStatusCMP0022() == cmPolicies::OLD) + { + // The link implementation is the default link interface. + cmLinkImplementationLibraries const* + impl = this->Target->GetLinkImplementationLibrariesInternal(config, + headTarget); + iface.ImplementationIsInterface = true; + iface.WrongConfigLibraries = impl->WrongConfigLibraries; + } + + if(this->Target->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + if(cmLinkImplementation const* impl = + this->GetLinkImplementation(config)) + { + iface.Languages = impl->Languages; + } + } + + if(this->GetType() == cmTarget::STATIC_LIBRARY) + { + // Construct the property name suffix for this configuration. + std::string suffix = "_"; + if(!config.empty()) + { + suffix += cmSystemTools::UpperCase(config); + } + else + { + suffix += "NOCONFIG"; + } + + // How many repetitions are needed if this library has cyclic + // dependencies? + std::string propName = "LINK_INTERFACE_MULTIPLICITY"; + propName += suffix; + if(const char* config_reps = this->GetProperty(propName)) + { + sscanf(config_reps, "%u", &iface.Multiplicity); + } + else if(const char* reps = + this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) + { + sscanf(reps, "%u", &iface.Multiplicity); + } + } +} + +//---------------------------------------------------------------------------- +const cmLinkInterfaceLibraries * +cmGeneratorTarget::GetLinkInterfaceLibraries(const std::string& config, + cmTarget const* head, + bool usage_requirements_only) const +{ + // Imported targets have their own link interface. + if(this->IsImported()) + { + return this->GetImportLinkInterface(config, head, + usage_requirements_only); + } + + // Link interfaces are not supported for executables that do not + // export symbols. + if(this->GetType() == cmTarget::EXECUTABLE && + !this->Target->IsExecutableWithExports()) + { + return 0; + } + + // Lookup any existing link interface for this configuration. + std::string CONFIG = cmSystemTools::UpperCase(config); + cmHeadToLinkInterfaceMap& hm = + (usage_requirements_only ? + this->GetHeadToLinkInterfaceUsageRequirementsMap(config) : + this->GetHeadToLinkInterfaceMap(config)); + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + + cmOptionalLinkInterface& iface = hm[head]; + if(!iface.LibrariesDone) + { + iface.LibrariesDone = true; + this->ComputeLinkInterfaceLibraries( + config, iface, head, usage_requirements_only); + } + + return iface.Exists? &iface : 0; +} + +//---------------------------------------------------------------------------- +void +cmGeneratorTarget::ComputeLinkInterfaceLibraries( + const std::string& config, + cmOptionalLinkInterface& iface, + cmTarget const* headTarget, + bool usage_requirements_only) const +{ + // Construct the property name suffix for this configuration. + std::string suffix = "_"; + if(!config.empty()) + { + suffix += cmSystemTools::UpperCase(config); + } + else + { + suffix += "NOCONFIG"; + } + + // An explicit list of interface libraries may be set for shared + // libraries and executables that export symbols. + const char* explicitLibraries = 0; + std::string linkIfaceProp; + if(this->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD && + this->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN) + { + // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. + linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; + explicitLibraries = this->GetProperty(linkIfaceProp); + } + else if(this->GetType() == cmTarget::SHARED_LIBRARY || + this->Target->IsExecutableWithExports()) + { + // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a + // shared lib or executable. + + // Lookup the per-configuration property. + linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; + linkIfaceProp += suffix; + explicitLibraries = this->GetProperty(linkIfaceProp); + + // If not set, try the generic property. + if(!explicitLibraries) + { + linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; + explicitLibraries = this->GetProperty(linkIfaceProp); + } + } + + if(explicitLibraries && + this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN && + !this->PolicyWarnedCMP0022) + { + // Compare the explicitly set old link interface properties to the + // preferred new link interface property one and warn if different. + const char* newExplicitLibraries = + this->GetProperty("INTERFACE_LINK_LIBRARIES"); + if (newExplicitLibraries + && strcmp(newExplicitLibraries, explicitLibraries) != 0) + { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n" + "Target \"" << this->GetName() << "\" has an " + "INTERFACE_LINK_LIBRARIES property which differs from its " << + linkIfaceProp << " properties." + "\n" + "INTERFACE_LINK_LIBRARIES:\n" + " " << newExplicitLibraries << "\n" << + linkIfaceProp << ":\n" + " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n"; + this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->PolicyWarnedCMP0022 = true; + } + } + + // There is no implicit link interface for executables or modules + // so if none was explicitly set then there is no link interface. + if(!explicitLibraries && + (this->GetType() == cmTarget::EXECUTABLE || + (this->GetType() == cmTarget::MODULE_LIBRARY))) + { + return; + } + iface.Exists = true; + iface.ExplicitLibraries = explicitLibraries; + + if(explicitLibraries) + { + // The interface libraries have been explicitly set. + this->ExpandLinkItems(linkIfaceProp, explicitLibraries, + config, + headTarget, usage_requirements_only, + iface.Libraries, + iface.HadHeadSensitiveCondition); + } + else if (this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN + || this->Target->GetPolicyStatusCMP0022() == cmPolicies::OLD) + // If CMP0022 is NEW then the plain tll signature sets the + // INTERFACE_LINK_LIBRARIES, so if we get here then the project + // cleared the property explicitly and we should not fall back + // to the link implementation. + { + // The link implementation is the default link interface. + cmLinkImplementationLibraries const* impl = + this->Target->GetLinkImplementationLibrariesInternal(config, + headTarget); + iface.Libraries.insert(iface.Libraries.end(), + impl->Libraries.begin(), impl->Libraries.end()); + if(this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN && + !this->PolicyWarnedCMP0022 && !usage_requirements_only) + { + // Compare the link implementation fallback link interface to the + // preferred new link interface property and warn if different. + std::vector<cmLinkItem> ifaceLibs; + static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; + if(const char* newExplicitLibraries = this->GetProperty(newProp)) + { + bool hadHeadSensitiveConditionDummy = false; + this->ExpandLinkItems(newProp, newExplicitLibraries, config, + headTarget, usage_requirements_only, + ifaceLibs, hadHeadSensitiveConditionDummy); + } + if (ifaceLibs != iface.Libraries) + { + std::string oldLibraries = cmJoin(impl->Libraries, ";"); + std::string newLibraries = cmJoin(ifaceLibs, ";"); + if(oldLibraries.empty()) + { oldLibraries = "(empty)"; } + if(newLibraries.empty()) + { newLibraries = "(empty)"; } + + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n" + "Target \"" << this->GetName() << "\" has an " + "INTERFACE_LINK_LIBRARIES property. " + "This should be preferred as the source of the link interface " + "for this library but because CMP0022 is not set CMake is " + "ignoring the property and using the link implementation " + "as the link interface instead." + "\n" + "INTERFACE_LINK_LIBRARIES:\n" + " " << newLibraries << "\n" + "Link implementation:\n" + " " << oldLibraries << "\n"; + this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->PolicyWarnedCMP0022 = true; + } + } + } +} + +//---------------------------------------------------------------------------- +const cmLinkInterface * +cmGeneratorTarget::GetImportLinkInterface(const std::string& config, + cmTarget const* headTarget, + bool usage_requirements_only) const +{ + cmTarget::ImportInfo const* info = this->Target->GetImportInfo(config); + if(!info) + { + return 0; + } + + std::string CONFIG = cmSystemTools::UpperCase(config); + cmHeadToLinkInterfaceMap& hm = + (usage_requirements_only ? + this->GetHeadToLinkInterfaceUsageRequirementsMap(config) : + this->GetHeadToLinkInterfaceMap(config)); + + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } + + cmOptionalLinkInterface& iface = hm[headTarget]; + if(!iface.AllDone) + { + iface.AllDone = true; + iface.Multiplicity = info->Multiplicity; + cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); + this->ExpandLinkItems(info->LibrariesProp, info->Libraries, + config, + headTarget, usage_requirements_only, + iface.Libraries, + iface.HadHeadSensitiveCondition); + std::vector<std::string> deps; + cmSystemTools::ExpandListArgument(info->SharedDeps, deps); + this->LookupLinkItems(deps, iface.SharedDeps); + } + + return &iface; +} + +cmHeadToLinkInterfaceMap& +cmGeneratorTarget::GetHeadToLinkInterfaceMap(const std::string &config) const +{ + std::string CONFIG = cmSystemTools::UpperCase(config); + return this->LinkInterfaceMap[CONFIG]; +} + +cmHeadToLinkInterfaceMap& +cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap( + const std::string &config) const +{ + std::string CONFIG = cmSystemTools::UpperCase(config); + return this->LinkInterfaceUsageRequirementsOnlyMap[CONFIG]; +} + +//---------------------------------------------------------------------------- +const cmLinkImplementation * +cmGeneratorTarget::GetLinkImplementation(const std::string& config) const +{ + // There is no link implementation for imported targets. + if(this->Target->IsImported()) + { + return 0; + } + + cmOptionalLinkImplementation& impl = this->Target->GetLinkImplMap(config); + if(!impl.LibrariesDone) + { + impl.LibrariesDone = true; + this->Target->ComputeLinkImplementationLibraries(config, impl, + this->Target); + } + if(!impl.LanguagesDone) + { + impl.LanguagesDone = true; + this->ComputeLinkImplementationLanguages(config, impl); + } + return &impl; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::GetConfigCommonSourceFiles( + std::vector<cmSourceFile*>& files) const +{ + std::vector<std::string> configs; + this->Makefile->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + + std::vector<std::string>::const_iterator it = configs.begin(); + const std::string& firstConfig = *it; + this->Target->GetSourceFiles(files, firstConfig); + + for ( ; it != configs.end(); ++it) + { + std::vector<cmSourceFile*> configFiles; + this->Target->GetSourceFiles(configFiles, *it); + if (configFiles != files) + { + std::string firstConfigFiles; + const char* sep = ""; + for (std::vector<cmSourceFile*>::const_iterator fi = files.begin(); + fi != files.end(); ++fi) + { + firstConfigFiles += sep; + firstConfigFiles += (*fi)->GetFullPath(); + sep = "\n "; + } + + std::string thisConfigFiles; + sep = ""; + for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin(); + fi != configFiles.end(); ++fi) + { + thisConfigFiles += sep; + thisConfigFiles += (*fi)->GetFullPath(); + sep = "\n "; + } + std::ostringstream e; + e << "Target \"" << this->GetName() + << "\" has source files which vary by " + "configuration. This is not supported by the \"" + << this->GlobalGenerator->GetName() + << "\" generator.\n" + "Config \"" << firstConfig << "\":\n" + " " << firstConfigFiles << "\n" + "Config \"" << *it << "\":\n" + " " << thisConfigFiles << "\n"; + this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, + const std::string& config) const +{ + std::vector<cmSourceFile*> sourceFiles; + this->GetSourceFiles(sourceFiles, config); + for(std::vector<cmSourceFile*>::const_iterator + i = sourceFiles.begin(); i != sourceFiles.end(); ++i) + { + const std::string& lang = (*i)->GetLanguage(); + if(!lang.empty()) + { + languages.insert(lang); + } + } + + std::vector<cmGeneratorTarget*> objectLibraries; + std::vector<cmSourceFile const*> externalObjects; + if (!this->Makefile->IsConfigured()) + { + std::vector<cmTarget*> objectTargets; + this->Target->GetObjectLibrariesCMP0026(objectTargets); + objectLibraries.reserve(objectTargets.size()); + for (std::vector<cmTarget*>::const_iterator it = objectTargets.begin(); + it != objectTargets.end(); ++it) + { + objectLibraries.push_back(this->GlobalGenerator + ->GetGeneratorTarget(*it)); + } + } + else + { + this->GetExternalObjects(externalObjects, config); + for(std::vector<cmSourceFile const*>::const_iterator + i = externalObjects.begin(); i != externalObjects.end(); ++i) + { + std::string objLib = (*i)->GetObjectLibrary(); + if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib)) + { + objectLibraries.push_back(this->GlobalGenerator + ->GetGeneratorTarget(tgt)); + } + } + } + for(std::vector<cmGeneratorTarget*>::const_iterator + i = objectLibraries.begin(); i != objectLibraries.end(); ++i) + { + (*i)->GetLanguages(languages, config); + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ComputeLinkImplementationLanguages( + const std::string& config, + cmOptionalLinkImplementation& impl) const +{ + // This target needs runtime libraries for its source languages. + std::set<std::string> languages; + // Get languages used in our source files. + this->GetLanguages(languages, config); + // Copy the set of langauges to the link implementation. + impl.Languages.insert(impl.Languages.begin(), + languages.begin(), languages.end()); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const +{ + if (this->Target->GetPropertyAsBool("SKIP_BUILD_RPATH")) + { + return false; + } + if(cmLinkImplementationLibraries const* impl = + this->Target->GetLinkImplementationLibraries(config)) + { + return !impl->Libraries.empty(); + } + return false; +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index c79aa72..06d9a1f 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -12,7 +12,7 @@ #ifndef cmGeneratorTarget_h #define cmGeneratorTarget_h -#include "cmStandardIncludes.h" +#include "cmLinkItem.h" class cmCustomCommand; class cmGlobalGenerator; @@ -20,11 +20,26 @@ class cmLocalGenerator; class cmMakefile; class cmSourceFile; class cmTarget; +class cmComputeLinkInformation; class cmGeneratorTarget { public: - cmGeneratorTarget(cmTarget*); + cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg); + ~cmGeneratorTarget(); + + cmLocalGenerator* GetLocalGenerator() const; + + bool IsImported() const; + const char *GetLocation(const std::string& config) const; + + /** Get the location of the target in the build tree with a placeholder + referencing the configuration in the native build system. This + location is suitable for use as the LOCATION target property. */ + const char* GetLocationForBuild() const; + + cmComputeLinkInformation* + GetLinkInformation(const std::string& config) const; int GetType() const; std::string GetName() const; @@ -67,6 +82,101 @@ public: void ComputeObjectMapping(); + const char* GetFeature(const std::string& feature, + const std::string& config) const; + bool GetFeatureAsBool(const std::string& feature, + const std::string& config) const; + + bool IsLinkInterfaceDependentBoolProperty(const std::string &p, + const std::string& config) const; + bool IsLinkInterfaceDependentStringProperty(const std::string &p, + const std::string& config) const; + bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p, + const std::string& config) const; + bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const std::string& config) const; + + bool GetLinkInterfaceDependentBoolProperty(const std::string &p, + const std::string& config) const; + + const char *GetLinkInterfaceDependentStringProperty(const std::string &p, + const std::string& config) const; + const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p, + const std::string& config) const; + const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const std::string& config) const; + + cmLinkInterface const* GetLinkInterface(const std::string& config, + cmTarget const* headTarget) const; + void ComputeLinkInterface(const std::string& config, + cmOptionalLinkInterface& iface, + cmTarget const* head) const; + + cmLinkInterfaceLibraries const* + GetLinkInterfaceLibraries(const std::string& config, + cmTarget const* headTarget, + bool usage_requirements_only) const; + + void ComputeLinkInterfaceLibraries(const std::string& config, + cmOptionalLinkInterface &iface, + cmTarget const* head, + bool usage_requirements_only) const; + + /** Get the full path to the target according to the settings in its + makefile and the configuration type. */ + std::string GetFullPath(const std::string& config="", bool implib = false, + bool realname = false) const; + std::string NormalGetFullPath(const std::string& config, bool implib, + bool realname) const; + std::string NormalGetRealName(const std::string& config) const; + + /** @return the Mac App directory without the base */ + std::string GetAppBundleDirectory(const std::string& config, + bool contentOnly) const; + + /** Return whether this target is an executable Bundle, a framework + or CFBundle on Apple. */ + bool IsBundleOnApple() const; + + /** Get the full name of the target according to the settings in its + makefile. */ + std::string GetFullName(const std::string& config="", + bool implib = false) const; + + /** @return the Mac framework directory without the base. */ + std::string GetFrameworkDirectory(const std::string& config, + bool rootDir) const; + + /** @return the Mac CFBundle directory without the base */ + std::string GetCFBundleDirectory(const std::string& config, + bool contentOnly) const; + + /** Return the install name directory for the target in the + * build tree. For example: "\@rpath/", "\@loader_path/", + * or "/full/path/to/library". */ + std::string GetInstallNameDirForBuildTree(const std::string& config) const; + + /** Return the install name directory for the target in the + * install tree. For example: "\@rpath/" or "\@loader_path/". */ + std::string GetInstallNameDirForInstallTree() const; + + /** Get the soname of the target. Allowed only for a shared library. */ + std::string GetSOName(const std::string& config) const; + + void GetFullNameComponents(std::string& prefix, + std::string& base, std::string& suffix, + const std::string& config="", + bool implib = false) const; + + /** Append to @a base the mac content directory and return it. */ + std::string BuildMacContentDirectory(const std::string& base, + const std::string& config = "", + bool contentOnly = true) const; + + /** @return the mac content directory for this target. */ + std::string GetMacContentDirectory(const std::string& config = 0, + bool implib = false) const; + cmTarget* Target; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; @@ -74,6 +184,39 @@ public: std::string GetModuleDefinitionFile(const std::string& config) const; + /** Link information from the transitive closure of the link + implementation and the interfaces of its dependencies. */ + struct LinkClosure + { + // The preferred linker language. + std::string LinkerLanguage; + + // Languages whose runtime libraries must be linked. + std::vector<std::string> Languages; + }; + + LinkClosure const* GetLinkClosure(const std::string& config) const; + void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; + + cmLinkImplementation const* + GetLinkImplementation(const std::string& config) const; + + void ComputeLinkImplementationLanguages(const std::string& config, + cmOptionalLinkImplementation& impl + ) const; + + // Compute the set of languages compiled by the target. This is + // computed every time it is called because the languages can change + // when source file properties are changed and we do not have enough + // information to forward these property changes to the targets + // until we have per-target object file properties. + void GetLanguages(std::set<std::string>& languages, + std::string const& config) const; + + bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const; + + bool HaveBuildTreeRPATH(const std::string& config) const; + /** Full path with trailing slash to the top-level directory holding object files for this target. Includes the build time config name placeholder if needed for the generator. */ @@ -93,11 +236,22 @@ public: std::vector<std::string> GetIncludeDirectories( const std::string& config, const std::string& lang) const; + void GetCompileOptions(std::vector<std::string> &result, + const std::string& config, + const std::string& language) const; + + void GetCompileFeatures(std::vector<std::string> &features, + const std::string& config) const; + + void GetCompileDefinitions(std::vector<std::string> &result, + const std::string& config, + const std::string& language) const; + bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config) const; /** Add the target output files to the global generator manifest. */ - void GenerateTargetManifest(const std::string& config) const; + void ComputeTargetManifest(const std::string& config) const; /** * Trace through the source files in this target and add al source files @@ -105,10 +259,41 @@ public: */ void TraceDependencies(); + /** Get the directory in which to place the target compiler .pdb file. + If the configuration name is given then the generator will add its + subdirectory for that configuration. Otherwise just the canonical + compiler pdb output directory is given. */ + std::string GetCompilePDBDirectory(const std::string& config = "") const; + /** Get sources that must be built before the given source. */ std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile const* sf) const; + /** Get the name of the pdb file for the target. */ + std::string GetPDBName(const std::string& config="") const; + + /** Whether this library has soname enabled and platform supports it. */ + bool HasSOName(const std::string& config) const; + + struct CompileInfo + { + std::string CompilePdbDir; + }; + + CompileInfo const* GetCompileInfo(const std::string& config) const; + + typedef std::map<std::string, CompileInfo> CompileInfoMapType; + mutable CompileInfoMapType CompileInfoMap; + + /** Get the name of the compiler pdb file for the target. */ + std::string GetCompilePDBName(const std::string& config="") const; + + /** Get the path for the MSVC /Fd option for this target. */ + std::string GetCompilePDBPath(const std::string& config="") const; + + // Get the target base name. + std::string GetOutputName(const std::string& config, bool implib) const; + /** * Flags for a given source file as used in this target. Typically assigned * via SET_TARGET_PROPERTIES when the property is a list of source files. @@ -130,6 +315,33 @@ public: SourceFileType Type; const char* MacFolder; // location inside Mac content folders }; + void GetAutoUicOptions(std::vector<std::string> &result, + const std::string& config) const; + + /** Get the names of the executable needed to generate a build rule + that takes into account executable version numbers. This should + be called only on an executable target. */ + void GetExecutableNames(std::string& name, std::string& realName, + std::string& impName, std::string& pdbName, + const std::string& config) const; + + /** Get the names of the library needed to generate a build rule + that takes into account shared library version numbers. This + should be called only on a library target. */ + void GetLibraryNames(std::string& name, std::string& soName, + std::string& realName, std::string& impName, + std::string& pdbName, const std::string& config) const; + + /** + * Compute whether this target must be relinked before installing. + */ + bool NeedRelinkBeforeInstall(const std::string& config) const; + + /** Return true if builtin chrpath will work for this target */ + bool IsChrpathUsed(const std::string& config) const; + + ///! Return the preferred linker language for this target + std::string GetLinkerLanguage(const std::string& config = "") const; struct SourceFileFlags GetTargetSourceFileFlags(const cmSourceFile* sf) const; @@ -145,12 +357,18 @@ public: std::vector<cmSourceFile const*> XamlSources; }; + void ReportPropertyOrigin(const std::string &p, + const std::string &result, + const std::string &report, + const std::string &compatibilityType) const; + + class TargetPropertyEntry; + private: friend class cmTargetTraceDependencies; struct SourceEntry { std::vector<cmSourceFile*> Depends; }; typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType; SourceEntriesType SourceEntries; - mutable std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache; @@ -159,8 +377,91 @@ private: mutable bool SourceFileFlagsConstructed; mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap; + mutable std::map<std::string, bool> DebugCompatiblePropertiesDone; + + std::string GetFullNameInternal(const std::string& config, + bool implib) const; + void GetFullNameInternal(const std::string& config, bool implib, + std::string& outPrefix, std::string& outBase, + std::string& outSuffix) const; + + typedef std::map<std::string, LinkClosure> LinkClosureMapType; + mutable LinkClosureMapType LinkClosureMap; + + struct CompatibleInterfacesBase + { + std::set<std::string> PropsBool; + std::set<std::string> PropsString; + std::set<std::string> PropsNumberMax; + std::set<std::string> PropsNumberMin; + }; + CompatibleInterfacesBase const& + GetCompatibleInterfaces(std::string const& config) const; + + struct CompatibleInterfaces: public CompatibleInterfacesBase + { + CompatibleInterfaces(): Done(false) {} + bool Done; + }; + mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; + + typedef std::map<std::string, cmComputeLinkInformation*> + cmTargetLinkInformationMap; + mutable cmTargetLinkInformationMap LinkInformation; + + void CheckPropertyCompatibility(cmComputeLinkInformation *info, + const std::string& config) const; + cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); + + struct LinkImplClosure: public std::vector<cmTarget const*> + { + LinkImplClosure(): Done(false) {} + bool Done; + }; + mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap; + + typedef std::map<std::string, cmHeadToLinkInterfaceMap> + LinkInterfaceMapType; + mutable LinkInterfaceMapType LinkInterfaceMap; + mutable LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap; + + cmHeadToLinkInterfaceMap& + GetHeadToLinkInterfaceMap(std::string const& config) const; + cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap( + std::string const& config) const; + + cmLinkInterface const* + GetImportLinkInterface(const std::string& config, cmTarget const* head, + bool usage_requirements_only) const; + + std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; + std::vector<TargetPropertyEntry*> CompileOptionsEntries; + std::vector<TargetPropertyEntry*> CompileFeaturesEntries; + std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; + + void ExpandLinkItems(std::string const& prop, std::string const& value, + std::string const& config, cmTarget const* headTarget, + bool usage_requirements_only, + std::vector<cmLinkItem>& items, + bool& hadHeadSensitiveCondition) const; + void LookupLinkItems(std::vector<std::string> const& names, + std::vector<cmLinkItem>& items) const; + + typedef std::pair<std::string, bool> OutputNameKey; + typedef std::map<OutputNameKey, std::string> OutputNameMapType; + mutable OutputNameMapType OutputNameMap; + mutable bool PolicyWarnedCMP0022; + mutable bool DebugIncludesDone; + mutable bool DebugCompileOptionsDone; + mutable bool DebugCompileFeaturesDone; + mutable bool DebugCompileDefinitionsDone; + +public: + std::vector<cmTarget const*> const& + GetLinkImplementationClosure(const std::string& config) const; + }; struct cmStrictTargetComparison { diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index 76803c1..248ce59 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -32,17 +32,18 @@ bool cmGetCMakePropertyCommand if ( args[1] == "VARIABLES" ) { - int cacheonly = 0; - std::vector<std::string> vars = this->Makefile->GetDefinitions(cacheonly); - if (!vars.empty()) + if (const char* varsProp = this->Makefile->GetProperty("VARIABLES")) { - output = cmJoin(vars, ";"); + output = varsProp; } } else if ( args[1] == "MACROS" ) { output.clear(); - this->Makefile->GetListOfMacros(output); + if (const char* macrosProp = this->Makefile->GetProperty("MACROS")) + { + output = macrosProp; + } } else if ( args[1] == "COMPONENTS" ) { @@ -52,9 +53,11 @@ bool cmGetCMakePropertyCommand } else { - const char *prop = - this->Makefile->GetState() - ->GetGlobalProperty(args[1]); + const char *prop = 0; + if (!args[1].empty()) + { + prop = this->Makefile->GetState()->GetGlobalProperty(args[1]); + } if (prop) { output = prop; diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 4fe3318..2558876 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -26,7 +26,6 @@ bool cmGetDirectoryPropertyCommand std::vector<std::string>::const_iterator i = args.begin(); std::string variable = *i; ++i; - std::string output = ""; // get the directory argument if there is one cmMakefile *dir = this->Makefile; @@ -52,10 +51,8 @@ bool cmGetDirectoryPropertyCommand sd = cmSystemTools::CollapseFullPath(sd); // lookup the makefile from the directory name - cmLocalGenerator *lg = - this->Makefile->GetGlobalGenerator()-> - FindLocalGenerator(sd); - if (!lg) + dir = this->Makefile->GetGlobalGenerator()->FindMakefile(sd); + if (!dir) { this->SetError ("DIRECTORY argument provided but requested directory not found. " @@ -63,7 +60,6 @@ bool cmGetDirectoryPropertyCommand "it is valid but has not been processed yet."); return false; } - dir = lg->GetMakefile(); ++i; } @@ -79,18 +75,45 @@ bool cmGetDirectoryPropertyCommand "providing the name of the variable to get."); return false; } - output = dir->GetSafeDefinition(*i); + std::string output = dir->GetSafeDefinition(*i); this->Makefile->AddDefinition(variable, output.c_str()); return true; } - const char *prop = dir->GetProperty(*i); + const char *prop = 0; + if (!i->empty()) + { + if (*i == "DEFINITIONS") + { + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0059)) + { + case cmPolicies::WARN: + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); + case cmPolicies::OLD: + this->StoreResult(variable, + this->Makefile->GetDefineFlagsCMP0059()); + return true; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + break; + } + } + prop = dir->GetProperty(*i); + } + this->StoreResult(variable, prop); + return true; +} + +void cmGetDirectoryPropertyCommand::StoreResult(std::string const& variable, + const char* prop) +{ if (prop) { this->Makefile->AddDefinition(variable, prop); - return true; + return; } this->Makefile->AddDefinition(variable, ""); - return true; } diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h index 6c5750a..f418886 100644 --- a/Source/cmGetDirectoryPropertyCommand.h +++ b/Source/cmGetDirectoryPropertyCommand.h @@ -40,8 +40,9 @@ public: virtual std::string GetName() const { return "get_directory_property";} cmTypeMacro(cmGetDirectoryPropertyCommand, cmCommand); -}; - +private: + void StoreResult(const std::string& variable, const char* prop); +}; #endif diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 67f9f2d..0f56c8e 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -24,7 +24,7 @@ bool cmGetFilenameComponentCommand // Check and see if the value has been stored in the cache // already, if so use that value - if(args.size() == 4 && args[3] == "CACHE") + if(args.size() >= 4 && args[args.size() - 1] == "CACHE") { const char* cacheValue = this->Makefile->GetDefinition(args[0]); if(cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue)) @@ -93,11 +93,23 @@ bool cmGetFilenameComponentCommand else if (args[2] == "ABSOLUTE" || args[2] == "REALPATH") { + // If the path given is relative, evaluate it relative to the + // current source directory unless the user passes a different + // base directory. + std::string baseDir = this->Makefile->GetCurrentSourceDirectory(); + for(unsigned int i=3; i < args.size(); ++i) + { + if(args[i] == "BASE_DIR") + { + ++i; + if(i < args.size()) + { + baseDir = args[i]; + } + } + } // Collapse the path to its simplest form. - // If the path given is relative evaluate it relative to the - // current source directory. - result = cmSystemTools::CollapseFullPath( - filename, this->Makefile->GetCurrentSourceDirectory()); + result = cmSystemTools::CollapseFullPath(filename, baseDir); if(args[2] == "REALPATH") { // Resolve symlinks if possible @@ -111,7 +123,7 @@ bool cmGetFilenameComponentCommand return false; } - if(args.size() == 4 && args[3] == "CACHE") + if(args.size() >= 4 && args[args.size() - 1] == "CACHE") { if(!programArgs.empty() && !storeArgs.empty()) { diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 250bd35..4c42f53 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -142,8 +142,7 @@ bool cmGetPropertyCommand { // Lookup brief documentation. std::string output; - if(cmPropertyDefinition* def = - this->Makefile->GetState()-> + if(cmPropertyDefinition const* def = this->Makefile->GetState()-> GetPropertyDefinition(this->PropertyName, scope)) { output = def->GetShortDescription(); @@ -158,8 +157,7 @@ bool cmGetPropertyCommand { // Lookup full documentation. std::string output; - if(cmPropertyDefinition* def = - this->Makefile->GetState()-> + if(cmPropertyDefinition const* def = this->Makefile->GetState()-> GetPropertyDefinition(this->PropertyName, scope)) { output = def->GetFullDescription(); @@ -264,13 +262,8 @@ bool cmGetPropertyCommand::HandleDirectoryMode() dir = cmSystemTools::CollapseFullPath(dir); // Lookup the generator. - if(cmLocalGenerator* lg = - (this->Makefile->GetGlobalGenerator()->FindLocalGenerator(dir))) - { - // Use the makefile for the directory found. - mf = lg->GetMakefile(); - } - else + mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir); + if (!mf) { // Could not find the directory. this->SetError @@ -281,6 +274,22 @@ bool cmGetPropertyCommand::HandleDirectoryMode() } } + if (this->PropertyName == "DEFINITIONS") + { + switch(mf->GetPolicyStatus(cmPolicies::CMP0059)) + { + case cmPolicies::WARN: + mf->IssueMessage(cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); + case cmPolicies::OLD: + return this->StoreResult(mf->GetDefineFlagsCMP0059()); + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + break; + } + } + // Get the property. return this->StoreResult(mf->GetProperty(this->PropertyName)); } diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index 7667a85..46daa34 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -38,7 +38,11 @@ bool cmGetSourceFilePropertyCommand this->Makefile->AddDefinition(var, sf->GetLanguage().c_str()); return true; } - const char *prop = sf->GetPropertyForUser(args[2]); + const char *prop = 0; + if (!args[2].empty()) + { + prop = sf->GetPropertyForUser(args[2]); + } if (prop) { this->Makefile->AddDefinition(var, prop); diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 315e851..ca40bd0 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -40,7 +40,11 @@ bool cmGetTargetPropertyCommand else if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName)) { cmTarget& target = *tgt; - const char* prop_cstr = target.GetProperty(args[2], this->Makefile); + const char* prop_cstr = 0; + if (!args[2].empty()) + { + prop_cstr = target.GetProperty(args[2], this->Makefile); + } if(prop_cstr) { prop = prop_cstr; diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx index b3df4c3..bf34589 100644 --- a/Source/cmGetTestPropertyCommand.cxx +++ b/Source/cmGetTestPropertyCommand.cxx @@ -29,7 +29,11 @@ bool cmGetTestPropertyCommand cmTest *test = this->Makefile->GetTest(testName); if (test) { - const char *prop = test->GetProperty(args[1]); + const char *prop = 0; + if (!args[1].empty()) + { + prop = test->GetProperty(args[1]); + } if (prop) { this->Makefile->AddDefinition(var, prop); diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 01e2011..846b6e2 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -21,23 +21,24 @@ std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic"); -cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmTarget *target) - : Target(target) +cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget *target) + : Target(target->Target) + , GeneratorTarget(target) , LocalGenerator(static_cast<cmLocalGhsMultiGenerator *>( - target->GetMakefile()->GetLocalGenerator())) - , Makefile(target->GetMakefile()) - , TargetGroup(DetermineIfTargetGroup(target)) + target->GetLocalGenerator())) + , Makefile(target->Target->GetMakefile()) + , TargetGroup(DetermineIfTargetGroup(target->Target)) , DynamicDownload(false) { - this->RelBuildFilePath = this->GetRelBuildFilePath(target); + this->RelBuildFilePath = this->GetRelBuildFilePath(target->Target); this->RelOutputFileName = this->RelBuildFilePath + this->Target->GetName() + ".a"; this->RelBuildFileName = this->RelBuildFilePath; - this->RelBuildFileName += this->GetBuildFileName(target); + this->RelBuildFileName += this->GetBuildFileName(target->Target); - std::string absPathToRoot = this->GetAbsPathToRoot(target); + std::string absPathToRoot = this->GetAbsPathToRoot(target->Target); absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot); this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath; this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName; @@ -127,7 +128,8 @@ void cmGhsMultiTargetGenerator::Generate() { config = "RELEASE"; } - const std::string language(this->Target->GetLinkerLanguage(config)); + const std::string language( + this->GeneratorTarget->GetLinkerLanguage(config)); config = cmSystemTools::UpperCase(config); this->DynamicDownload = this->DetermineIfDynamicDownload(config, language); if (this->DynamicDownload) @@ -328,7 +330,8 @@ void cmGhsMultiTargetGenerator::WriteCompilerDefinitions( const std::string &config, const std::string &language) { std::vector<std::string> compileDefinitions; - this->Target->GetCompileDefinitions(compileDefinitions, config, language); + this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, + config, language); for (std::vector<std::string>::const_iterator cdI = compileDefinitions.begin(); cdI != compileDefinitions.end(); ++cdI) @@ -341,7 +344,7 @@ void cmGhsMultiTargetGenerator::WriteIncludes(const std::string &config, const std::string &language) { std::vector<std::string> includes = - this->Target->GetIncludeDirectories(config, language); + this->GeneratorTarget->GetIncludeDirectories(config, language); for (std::vector<std::string>::const_iterator includes_i = includes.begin(); includes_i != includes.end(); ++includes_i) { @@ -354,11 +357,11 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries() { // library directories cmTargetDependSet tds = - this->GetGlobalGenerator()->GetTargetDirectDepends(*this->Target); + this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget); for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end(); ++tdsI) { - const cmTarget *tg(*tdsI); + const cmTarget *tg = (*tdsI)->Target; *this->GetFolderBuildStreams() << " -L\"" << GetAbsBuildFilePath(tg) << "\"" << std::endl; } @@ -373,7 +376,6 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries() cmTarget *tg(GetGlobalGenerator()->FindTarget(libName)); if (NULL != tg) { - cmGhsMultiTargetGenerator gmtg(tg); libName = tg->GetName() + ".a"; } *this->GetFolderBuildStreams() << " -l\"" << libName << "\"" @@ -557,7 +559,7 @@ bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const &config, { bool output; std::vector<std::string> options; - this->Target->GetCompileOptions(options, config, language); + this->GeneratorTarget->GetCompileOptions(options, config, language); output = options.end() == std::find(options.begin(), options.end(), "-kernel"); return output; @@ -586,7 +588,7 @@ bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload( { std::vector<std::string> options; bool output = false; - this->Target->GetCompileOptions(options, config, language); + this->GeneratorTarget->GetCompileOptions(options, config, language); for (std::vector<std::string>::const_iterator options_i = options.begin(); options_i != options.end(); ++options_i) { diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index 8e81db8..c29a31e 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -27,7 +27,7 @@ class cmCustomCommand; class cmGhsMultiTargetGenerator { public: - cmGhsMultiTargetGenerator(cmTarget *target); + cmGhsMultiTargetGenerator(cmGeneratorTarget* target); virtual ~cmGhsMultiTargetGenerator(); @@ -100,6 +100,7 @@ private: const std::string &language); cmTarget *Target; + cmGeneratorTarget* GeneratorTarget; cmLocalGhsMultiGenerator *LocalGenerator; cmMakefile *Makefile; std::string AbsBuildFilePath; diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 87665a0..40e8d29 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -44,10 +44,10 @@ void cmGlobalBorlandMakefileGenerator ///! Create a local generator appropriate to this Global Generator cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator( - cmLocalGenerator* parent, cmState::Snapshot snapshot) + cmMakefile *mf) { cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(this, parent, snapshot); + new cmLocalUnixMakefileGenerator3(this, mf); lg->SetMakefileVariableSize(32); lg->SetMakeCommandEscapeTargetTwice(true); lg->SetBorlandMakeCurlyHack(true); diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index 2ec510d..b59c86d 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -36,8 +36,7 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile* mf); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx new file mode 100644 index 0000000..dc8e5a7 --- /dev/null +++ b/Source/cmGlobalCommonGenerator.cxx @@ -0,0 +1,21 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGlobalCommonGenerator.h" + +cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm): + cmGlobalGenerator(cm) +{ +} + +cmGlobalCommonGenerator::~cmGlobalCommonGenerator() +{ +} diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h new file mode 100644 index 0000000..7bb0e55 --- /dev/null +++ b/Source/cmGlobalCommonGenerator.h @@ -0,0 +1,27 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGlobalCommonGenerator_h +#define cmGlobalCommonGenerator_h + +#include "cmGlobalGenerator.h" + +/** \class cmGlobalCommonGenerator + * \brief Common infrastructure for Makefile and Ninja global generators. + */ +class cmGlobalCommonGenerator : public cmGlobalGenerator +{ +public: + cmGlobalCommonGenerator(cmake* cm); + ~cmGlobalCommonGenerator(); +}; + +#endif diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index cd05c54..ec36d2a 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -14,6 +14,20 @@ #if defined(_MSC_VER) && _MSC_VER >= 1800 # define KWSYS_WINDOWS_DEPRECATED_GetVersionEx #endif +typedef struct { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + WCHAR szCSDVersion[128]; + USHORT wServicePackMajor; + USHORT wServicePackMinor; + USHORT wSuiteMask; + UCHAR wProductType; + UCHAR wReserved; +} CMRTL_OSVERSIONINFOEXW; + #endif #include "cmGlobalGenerator.h" @@ -30,10 +44,10 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGeneratorExpression.h" -#include "cmGeneratorExpressionEvaluationFile.h" #include "cmExportBuildFileGenerator.h" #include "cmCPackPropertiesGenerator.h" #include "cmAlgorithms.h" +#include "cmInstallGenerator.h" #include <cmsys/Directory.hxx> #include <cmsys/FStream.hxx> @@ -70,7 +84,7 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm) this->TryCompileTimeout = 0; this->ExtraGenerator = 0; - this->CurrentLocalGenerator = 0; + this->CurrentMakefile = 0; this->TryCompileOuterMakefile = 0; } @@ -87,18 +101,16 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, { return true; } - else - { - std::ostringstream e; - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not support platform specification, but platform\n" - " " << p << "\n" - "was specified."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } + + std::ostringstream e; + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not support platform specification, but platform\n" + " " << p << "\n" + "was specified."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; } bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, @@ -108,18 +120,15 @@ bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, { return true; } - else - { - std::ostringstream e; - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not support toolset specification, but toolset\n" - " " << ts << "\n" - "was specified."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } + std::ostringstream e; + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not support toolset specification, but toolset\n" + " " << ts << "\n" + "was specified."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; } std::string cmGlobalGenerator::SelectMakeProgram( @@ -437,23 +446,45 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, if (!mf->GetDefinition("CMAKE_SYSTEM")) { #if defined(_WIN32) && !defined(__CYGWIN__) - /* Windows version number data. */ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + CMRTL_OSVERSIONINFOEXW osviex; + ZeroMemory(&osviex, sizeof(osviex)); + osviex.dwOSVersionInfoSize = sizeof(osviex); + + typedef LONG (FAR WINAPI *cmRtlGetVersion)(CMRTL_OSVERSIONINFOEXW*); + cmRtlGetVersion rtlGetVersion = reinterpret_cast<cmRtlGetVersion>( + GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion")); + if (rtlGetVersion && rtlGetVersion(&osviex) == 0) + { + std::ostringstream windowsVersionString; + windowsVersionString << osviex.dwMajorVersion << "." + << osviex.dwMinorVersion << "." + << osviex.dwBuildNumber; + windowsVersionString.str(); + mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", + windowsVersionString.str().c_str()); + } + else + { + // RtlGetVersion failed, so use the deprecated GetVersionEx function. + /* Windows version number data. */ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # pragma warning (push) # pragma warning (disable:4996) #endif - GetVersionEx (&osvi); + GetVersionEx (&osvi); #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # pragma warning (pop) #endif - std::ostringstream windowsVersionString; - windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion; - windowsVersionString.str(); - mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", - windowsVersionString.str().c_str()); + std::ostringstream windowsVersionString; + windowsVersionString << osvi.dwMajorVersion << "." + << osvi.dwMinorVersion; + windowsVersionString.str(); + mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", + windowsVersionString.str().c_str()); + } #endif // Read the DetermineSystem file std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake"); @@ -569,6 +600,10 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, cmSystemTools::Error("Could not find cmake module file: ", determineCompiler.c_str()); } + if (cmSystemTools::GetFatalErrorOccured()) + { + return; + } needTestLanguage[lang] = true; // Some generators like visual studio should not use the env variables // So the global generator can specify that in this variable @@ -1092,37 +1127,52 @@ void cmGlobalGenerator::Configure() this->FirstTimeProgress = 0.0f; this->ClearGeneratorMembers(); - // start with this directory - cmLocalGenerator *lg = this->MakeLocalGenerator(); + cmMakefile* dirMf = + new cmMakefile(this, this->GetCMakeInstance()->GetCurrentSnapshot()); + this->Makefiles.push_back(dirMf); + cmLocalGenerator *lg = this->CreateLocalGenerator(dirMf); this->LocalGenerators.push_back(lg); // set the Start directories - lg->GetMakefile()->SetCurrentSourceDirectory + dirMf->SetCurrentSourceDirectory (this->CMakeInstance->GetHomeDirectory()); - lg->GetMakefile()->SetCurrentBinaryDirectory + dirMf->SetCurrentBinaryDirectory (this->CMakeInstance->GetHomeOutputDirectory()); this->BinaryDirectories.insert( this->CMakeInstance->GetHomeOutputDirectory()); // now do it - lg->Configure(); + dirMf->Configure(); + dirMf->EnforceDirectoryLevelRules(); + + // Put a copy of each global target in every directory. + cmTargets globalTargets; + this->CreateDefaultGlobalTargets(&globalTargets); + + for (unsigned int i = 0; i < this->Makefiles.size(); ++i) + { + cmMakefile* mf = this->Makefiles[i]; + cmTargets* targets = &(mf->GetTargets()); + cmTargets::iterator tit; + for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit ) + { + (*targets)[tit->first] = tit->second; + (*targets)[tit->first].SetMakefile(mf); + } + } // update the cache entry for the number of local generators, this is used // for progress char num[100]; - sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size())); + sprintf(num,"%d",static_cast<int>(this->Makefiles.size())); this->GetCMakeInstance()->AddCacheEntry - ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num, + ("CMAKE_NUMBER_OF_MAKEFILES", num, "number of local generators", cmState::INTERNAL); // check for link libraries and include directories containing "NOTFOUND" // and for infinite loops - this->CheckLocalGenerators(); - - // at this point this->LocalGenerators has been filled, - // so create the map from project name to vector of local generators - this->FillProjectMap(); + this->CheckTargetProperties(); if ( this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) { @@ -1151,6 +1201,13 @@ void cmGlobalGenerator::Configure() } } +void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes) +{ + cmDeleteAll(this->GeneratorTargets); + this->GeneratorTargets.clear(); + this->CreateGeneratorTargets(targetTypes); +} + cmExportBuildFileGenerator* cmGlobalGenerator::GetExportedTargetsFile(const std::string &filename) const { @@ -1186,7 +1243,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const return false; } -void cmGlobalGenerator::DoGenerate() +bool cmGlobalGenerator::Compute() { // Some generators track files replaced during the Generate. // Start with an empty vector: @@ -1195,19 +1252,19 @@ void cmGlobalGenerator::DoGenerate() // clear targets to issue warning CMP0042 for this->CMP0042WarnTargets.clear(); - this->Generate(); -} - -void cmGlobalGenerator::Generate() -{ // Check whether this generator is allowed to run. if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) { - return; + return false; } - this->FinalizeTargetCompileInfo(); + this->CreateGenerationObjects(); + + // at this point this->LocalGenerators has been filled, + // so create the map from project name to vector of local generators + this->FillProjectMap(); + #ifdef CMAKE_BUILD_WITH_CMAKE // Iterate through all targets and set up automoc for those which have // the AUTOMOC, AUTOUIC or AUTORCC property set @@ -1215,22 +1272,11 @@ void cmGlobalGenerator::Generate() this->CreateQtAutoGeneratorsTargets(autogens); #endif - // For each existing cmLocalGenerator unsigned int i; - // Put a copy of each global target in every directory. - cmTargets globalTargets; - this->CreateDefaultGlobalTargets(&globalTargets); for (i = 0; i < this->LocalGenerators.size(); ++i) { - cmMakefile* mf = this->LocalGenerators[i]->GetMakefile(); - cmTargets* targets = &(mf->GetTargets()); - cmTargets::iterator tit; - for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit ) - { - (*targets)[tit->first] = tit->second; - (*targets)[tit->first].SetMakefile(mf); - } + this->LocalGenerators[i]->ComputeObjectMaxPath(); } // Add generator specific helper commands @@ -1239,8 +1285,7 @@ void cmGlobalGenerator::Generate() this->LocalGenerators[i]->AddHelperCommands(); } - // Create per-target generator information. - this->CreateGeneratorTargets(); + this->InitGeneratorTargets(); #ifdef CMAKE_BUILD_WITH_CMAKE for (AutogensType::iterator it = autogens.begin(); it != autogens.end(); @@ -1250,6 +1295,24 @@ void cmGlobalGenerator::Generate() } #endif + for (i = 0; i < this->LocalGenerators.size(); ++i) + { + cmMakefile* mf = this->LocalGenerators[i]->GetMakefile(); + std::vector<cmInstallGenerator*>& gens = mf->GetInstallGenerators(); + for (std::vector<cmInstallGenerator*>::const_iterator git = gens.begin(); + git != gens.end(); ++git) + { + (*git)->Compute(this->LocalGenerators[i]); + } + } + + return true; +} + +void cmGlobalGenerator::Generate() +{ + unsigned int i; + // Trace the dependencies, after that no custom commands should be added // because their dependencies might not be handled correctly for (i = 0; i < this->LocalGenerators.size(); ++i) @@ -1262,11 +1325,9 @@ void cmGlobalGenerator::Generate() // Compute the manifest of main targets generated. for (i = 0; i < this->LocalGenerators.size(); ++i) { - this->LocalGenerators[i]->GenerateTargetManifest(); + this->LocalGenerators[i]->ComputeTargetManifest(); } - this->ProcessEvaluationFiles(); - // Compute the inter-target dependencies. if(!this->ComputeTargetDepends()) { @@ -1275,13 +1336,19 @@ void cmGlobalGenerator::Generate() // Create a map from local generator to the complete set of targets // it builds by default. - this->FillLocalGeneratorToTargetMap(); + this->InitializeProgressMarks(); + + this->ProcessEvaluationFiles(); + + for (i = 0; i < this->LocalGenerators.size(); ++i) + { + this->LocalGenerators[i]->ComputeHomeRelativeOutputPath(); + } // Generate project files for (i = 0; i < this->LocalGenerators.size(); ++i) { - this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem(); - this->SetCurrentLocalGenerator(this->LocalGenerators[i]); + this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile()); this->LocalGenerators[i]->Generate(); if(!this->LocalGenerators[i]->GetMakefile()->IsOn( "CMAKE_SKIP_INSTALL_RULES")) @@ -1293,7 +1360,7 @@ void cmGlobalGenerator::Generate() (static_cast<float>(i)+1.0f)/ static_cast<float>(this->LocalGenerators.size())); } - this->SetCurrentLocalGenerator(0); + this->SetCurrentMakefile(0); if(!this->GenerateCPackPropertiesFile()) { @@ -1350,9 +1417,9 @@ bool cmGlobalGenerator::ComputeTargetDepends() { return false; } - std::vector<cmTarget const*> const& targets = ctd.GetTargets(); - for(std::vector<cmTarget const*>::const_iterator ti = targets.begin(); - ti != targets.end(); ++ti) + std::vector<cmGeneratorTarget const*> const& targets = ctd.GetTargets(); + for(std::vector<cmGeneratorTarget const*>::const_iterator ti + = targets.begin(); ti != targets.end(); ++ti) { ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]); } @@ -1372,6 +1439,10 @@ void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) for(cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) { + if (ti->second.GetType() == cmTarget::GLOBAL_TARGET) + { + continue; + } targetNames.push_back(ti->second.GetName()); } for(std::vector<std::string>::iterator ti = targetNames.begin(); @@ -1391,7 +1462,8 @@ void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) && !target.IsImported()) { cmQtAutoGenerators autogen; - if(autogen.InitializeAutogenTarget(&target)) + if(autogen.InitializeAutogenTarget(this->LocalGenerators[i], + &target)) { autogens.push_back(std::make_pair(autogen, &target)); } @@ -1408,18 +1480,24 @@ void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) void cmGlobalGenerator::FinalizeTargetCompileInfo() { // Construct per-target generator information. - for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) + for(unsigned int i=0; i < this->Makefiles.size(); ++i) { - cmMakefile *mf = this->LocalGenerators[i]->GetMakefile(); + cmMakefile *mf = this->Makefiles[i]; - const std::vector<cmValueWithOrigin> noconfig_compile_definitions = + const cmStringRange noconfig_compile_definitions = mf->GetCompileDefinitionsEntries(); + const cmBacktraceRange noconfig_compile_definitions_bts = + mf->GetCompileDefinitionsBacktraces(); cmTargets& targets = mf->GetTargets(); for(cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) { cmTarget* t = &ti->second; + if (t->GetType() == cmTarget::GLOBAL_TARGET) + { + continue; + } t->AppendBuildInterfaceIncludes(); @@ -1428,11 +1506,13 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() continue; } - for (std::vector<cmValueWithOrigin>::const_iterator it + cmBacktraceRange::const_iterator btIt + = noconfig_compile_definitions_bts.begin(); + for (cmStringRange::const_iterator it = noconfig_compile_definitions.begin(); - it != noconfig_compile_definitions.end(); ++it) + it != noconfig_compile_definitions.end(); ++it, ++btIt) { - t->InsertCompileDefinition(*it); + t->InsertCompileDefinition(*it, *btIt); } cmPolicies::PolicyStatus polSt @@ -1456,25 +1536,29 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() } //---------------------------------------------------------------------------- -void cmGlobalGenerator::CreateGeneratorTargets(cmMakefile *mf) +void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes, + cmLocalGenerator *lg) { cmGeneratorTargetsType generatorTargets; - cmTargets& targets = mf->GetTargets(); - for(cmTargets::iterator ti = targets.begin(); - ti != targets.end(); ++ti) + cmMakefile* mf = lg->GetMakefile(); + if (targetTypes == AllTargets) { - cmTarget* t = &ti->second; - cmGeneratorTarget* gt = new cmGeneratorTarget(t); - this->ComputeTargetObjectDirectory(gt); - this->GeneratorTargets[t] = gt; - generatorTargets[t] = gt; + cmTargets& targets = mf->GetTargets(); + for(cmTargets::iterator ti = targets.begin(); + ti != targets.end(); ++ti) + { + cmTarget* t = &ti->second; + cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg); + this->GeneratorTargets[t] = gt; + generatorTargets[t] = gt; + } } for(std::vector<cmTarget*>::const_iterator j = mf->GetOwnedImportedTargets().begin(); j != mf->GetOwnedImportedTargets().end(); ++j) { - cmGeneratorTarget* gt = new cmGeneratorTarget(*j); + cmGeneratorTarget* gt = new cmGeneratorTarget(*j, lg); this->GeneratorTargets[*j] = gt; generatorTargets[*j] = gt; } @@ -1482,12 +1566,25 @@ void cmGlobalGenerator::CreateGeneratorTargets(cmMakefile *mf) } //---------------------------------------------------------------------------- -void cmGlobalGenerator::CreateGeneratorTargets() +void cmGlobalGenerator::InitGeneratorTargets() +{ + for(cmGeneratorTargetsType::iterator ti = + this->GeneratorTargets.begin(); ti != this->GeneratorTargets.end(); ++ti) + { + if (!ti->second->Target->IsImported()) + { + this->ComputeTargetObjectDirectory(ti->second); + } + } +} + +//---------------------------------------------------------------------------- +void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes) { // Construct per-target generator information. for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) { - this->CreateGeneratorTargets(this->LocalGenerators[i]->GetMakefile()); + this->CreateGeneratorTargets(targetTypes, this->LocalGenerators[i]); } } @@ -1498,12 +1595,12 @@ void cmGlobalGenerator::ClearGeneratorMembers() cmDeleteAll(this->GeneratorTargets); this->GeneratorTargets.clear(); - cmDeleteAll(this->EvaluationFiles); - this->EvaluationFiles.clear(); - cmDeleteAll(this->BuildExportSets); this->BuildExportSets.clear(); + cmDeleteAll(this->Makefiles); + this->Makefiles.clear(); + cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); @@ -1511,7 +1608,6 @@ void cmGlobalGenerator::ClearGeneratorMembers() this->TargetDependencies.clear(); this->TotalTargets.clear(); this->ImportedTargets.clear(); - this->LocalGeneratorToTargetMap.clear(); this->ProjectMap.clear(); this->RuleHashes.clear(); this->DirectoryContentMap.clear(); @@ -1537,17 +1633,17 @@ void cmGlobalGenerator::ComputeTargetObjectDirectory(cmGeneratorTarget*) const { } -void cmGlobalGenerator::CheckLocalGenerators() +void cmGlobalGenerator::CheckTargetProperties() { std::map<std::string, std::string> notFoundMap; // std::set<std::string> notFoundMap; // after it is all done do a ConfigureFinalPass cmState* state = this->GetCMakeInstance()->GetState(); - for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) + for (unsigned int i = 0; i < this->Makefiles.size(); ++i) { - this->LocalGenerators[i]->ConfigureFinalPass(); + this->Makefiles[i]->ConfigureFinalPass(); cmTargets &targets = - this->LocalGenerators[i]->GetMakefile()->GetTargets(); + this->Makefiles[i]->GetTargets(); for (cmTargets::iterator l = targets.begin(); l != targets.end(); l++) { @@ -1572,8 +1668,7 @@ void cmGlobalGenerator::CheckLocalGenerators() text += "\n linked by target \""; text += l->second.GetName(); text += "\" in directory "; - text+=this->LocalGenerators[i]->GetMakefile() - ->GetCurrentSourceDirectory(); + text+=this->Makefiles[i]->GetCurrentSourceDirectory(); notFoundMap[varName] = text; } } @@ -1602,15 +1697,14 @@ void cmGlobalGenerator::CheckLocalGenerators() } std::string text = notFoundMap[varName]; text += "\n used as include directory in directory "; - text += this->LocalGenerators[i] - ->GetMakefile()->GetCurrentSourceDirectory(); + text += this->Makefiles[i]->GetCurrentSourceDirectory(); notFoundMap[varName] = text; } } } this->CMakeInstance->UpdateProgress ("Configuring", 0.9f+0.1f*(static_cast<float>(i)+1.0f)/ - static_cast<float>(this->LocalGenerators.size())); + static_cast<float>(this->Makefiles.size())); } if(!notFoundMap.empty()) @@ -1644,9 +1738,9 @@ int cmGlobalGenerator::TryCompile(const std::string& srcdir, // take the bulk of the time, so try and guess some progress // by getting closer and closer to 100 without actually getting there. if (!this->CMakeInstance->GetState()->GetInitializedCacheValue - ("CMAKE_NUMBER_OF_LOCAL_GENERATORS")) + ("CMAKE_NUMBER_OF_MAKEFILES")) { - // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set + // If CMAKE_NUMBER_OF_MAKEFILES is not set // we are in the first time progress and we have no // idea how long it will be. So, just move 1/10th of the way // there each time, and don't go over 95% @@ -1834,19 +1928,19 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand( } //---------------------------------------------------------------------------- -void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg) +void cmGlobalGenerator::AddMakefile(cmMakefile *mf) { - this->LocalGenerators.push_back(lg); + this->Makefiles.push_back(mf); // update progress // estimate how many lg there will be const char *numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue - ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"); + ("CMAKE_NUMBER_OF_MAKEFILES"); if (!numGenC) { - // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set + // If CMAKE_NUMBER_OF_MAKEFILES is not set // we are in the first time progress and we have no // idea how long it will be. So, just move half way // there each time, and don't go over 95% @@ -1861,7 +1955,7 @@ void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg) } int numGen = atoi(numGenC); - float prog = 0.9f*static_cast<float>(this->LocalGenerators.size())/ + float prog = 0.9f*static_cast<float>(this->Makefiles.size())/ static_cast<float>(numGen); if (prog > 0.9f) { @@ -1870,6 +1964,12 @@ void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg) this->CMakeInstance->UpdateProgress("Configuring", prog); } +//---------------------------------------------------------------------------- +void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg) +{ + this->LocalGenerators.push_back(lg); +} + void cmGlobalGenerator::AddInstallComponent(const char* component) { if(component && *component) @@ -1883,23 +1983,10 @@ void cmGlobalGenerator::EnableInstallTarget() this->InstallTargetEnabled = true; } -cmLocalGenerator * -cmGlobalGenerator::MakeLocalGenerator(cmState::Snapshot snapshot, - cmLocalGenerator *parent) -{ - if (!snapshot.IsValid()) - { - snapshot = this->CMakeInstance->GetCurrentSnapshot(); - } - - return this->CreateLocalGenerator(parent, snapshot); -} - cmLocalGenerator* -cmGlobalGenerator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmGlobalGenerator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalGenerator(this, parent, snapshot); + return new cmLocalGenerator(this, mf); } void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen, @@ -1938,41 +2025,51 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen) } } -bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, - cmLocalGenerator* gen) const +bool cmGlobalGenerator::IsExcluded(cmState::Snapshot const& rootSnp, + cmState::Snapshot const& snp_) const { - if(!gen || gen == root) + cmState::Snapshot snp = snp_; + while (snp.IsValid()) { - // No directory excludes itself. - return false; - } + if(snp == rootSnp) + { + // No directory excludes itself. + return false; + } - if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL")) - { - // This directory is excluded from its parent. - return true; + if(snp.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) + { + // This directory is excluded from its parent. + return true; + } + snp = snp.GetBuildsystemDirectoryParent(); } + return false; +} + +bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, + cmLocalGenerator* gen) const +{ + assert(gen); - // This directory is included in its parent. Check whether the - // parent is excluded. - return this->IsExcluded(root, gen->GetParent()); + cmState::Snapshot rootSnp = root->GetStateSnapshot(); + cmState::Snapshot snp = gen->GetStateSnapshot(); + + return this->IsExcluded(rootSnp, snp); } bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, - cmTarget const& target) const + cmGeneratorTarget* target) const { - if(target.GetType() == cmTarget::INTERFACE_LIBRARY - || target.GetPropertyAsBool("EXCLUDE_FROM_ALL")) + if(target->GetType() == cmTarget::INTERFACE_LIBRARY + || target->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { // This target is excluded from its directory. return true; } - else - { - // This target is included in its directory. Check whether the - // directory is excluded. - return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator()); - } + // This target is included in its directory. Check whether the + // directory is excluded. + return this->IsExcluded(root, target->GetLocalGenerator()); } void @@ -1999,65 +2096,37 @@ void cmGlobalGenerator::FillProjectMap() for(i = 0; i < this->LocalGenerators.size(); ++i) { // for each local generator add all projects - cmLocalGenerator *lg = this->LocalGenerators[i]; + cmState::Snapshot snp = this->LocalGenerators[i]->GetStateSnapshot(); std::string name; do { - if (name != lg->GetMakefile()->GetProjectName()) + std::string snpProjName = snp.GetProjectName(); + if (name != snpProjName) { - name = lg->GetMakefile()->GetProjectName(); + name = snpProjName; this->ProjectMap[name].push_back(this->LocalGenerators[i]); } - lg = lg->GetParent(); + snp = snp.GetBuildsystemDirectoryParent(); } - while (lg); + while (snp.IsValid()); } } - -// Build a map that contains a the set of targets used by each local -// generator directory level. -void cmGlobalGenerator::FillLocalGeneratorToTargetMap() +cmMakefile* +cmGlobalGenerator::FindMakefile(const std::string& start_dir) const { - this->LocalGeneratorToTargetMap.clear(); - // Loop over all targets in all local generators. - for(std::vector<cmLocalGenerator*>::const_iterator - lgi = this->LocalGenerators.begin(); - lgi != this->LocalGenerators.end(); ++lgi) + for(std::vector<cmMakefile*>::const_iterator it = + this->Makefiles.begin(); it != this->Makefiles.end(); ++it) { - cmLocalGenerator* lg = *lgi; - cmMakefile* mf = lg->GetMakefile(); - cmTargets const& targets = mf->GetTargets(); - for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t) + std::string sd = (*it)->GetCurrentSourceDirectory(); + if (sd == start_dir) { - cmTarget const& target = t->second; - - // Consider the directory containing the target and all its - // parents until something excludes the target. - for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target); - clg = clg->GetParent()) - { - // This local generator includes the target. - std::set<cmTarget const*>& targetSet = - this->LocalGeneratorToTargetMap[clg]; - targetSet.insert(&target); - - // Add dependencies of the included target. An excluded - // target may still be included if it is a dependency of a - // non-excluded target. - TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); - for(TargetDependSet::const_iterator ti = tgtdeps.begin(); - ti != tgtdeps.end(); ++ti) - { - cmTarget const* ttt = *ti; - targetSet.insert(ttt); - } - } + return *it; } } + return 0; } - ///! Find a local generator by its startdirectory cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const std::string& start_dir) const @@ -2144,7 +2213,7 @@ inline std::string removeQuotes(const std::string& s) void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) { - cmMakefile* mf = this->LocalGenerators[0]->GetMakefile(); + cmMakefile* mf = this->Makefiles[0]; const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); // CPack @@ -2443,7 +2512,6 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget( { // Package cmTarget target; - target.GetProperties().SetCMakeInstance(this->CMakeInstance); target.SetType(cmTarget::GLOBAL_TARGET, name); target.SetProperty("EXCLUDE_FROM_ALL","TRUE"); @@ -2513,9 +2581,9 @@ void cmGlobalGenerator::AppendDirectoryForConfig(const std::string&, //---------------------------------------------------------------------------- cmGlobalGenerator::TargetDependSet const& -cmGlobalGenerator::GetTargetDirectDepends(cmTarget const& target) +cmGlobalGenerator::GetTargetDirectDepends(cmGeneratorTarget const* target) { - return this->TargetDependencies[&target]; + return this->TargetDependencies[target]; } void cmGlobalGenerator::AddTarget(cmTarget* t) @@ -2615,9 +2683,10 @@ void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets, continue; } // put the target in the set of original targets - originalTargets.insert(target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + originalTargets.insert(gt); // Get the set of targets that depend on target - this->AddTargetDepends(target, projectTargets); + this->AddTargetDepends(gt, projectTargets); } } } @@ -2630,7 +2699,7 @@ bool cmGlobalGenerator::IsRootOnlyTarget(cmTarget* target) const } //---------------------------------------------------------------------------- -void cmGlobalGenerator::AddTargetDepends(cmTarget const* target, +void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target, TargetDependSet& projectTargets) { // add the target itself @@ -2638,23 +2707,18 @@ void cmGlobalGenerator::AddTargetDepends(cmTarget const* target, { // This is the first time we have encountered the target. // Recursively follow its dependencies. - TargetDependSet const& ts = this->GetTargetDirectDepends(*target); + TargetDependSet const& ts = this->GetTargetDirectDepends(target); for(TargetDependSet::const_iterator i = ts.begin(); i != ts.end(); ++i) { - cmTarget const* dtarget = *i; - this->AddTargetDepends(dtarget, projectTargets); + this->AddTargetDepends(*i, projectTargets); } } } //---------------------------------------------------------------------------- -void cmGlobalGenerator::AddToManifest(const std::string& config, - std::string const& f) +void cmGlobalGenerator::AddToManifest(std::string const& f) { - // Add to the main manifest for this configuration. - this->TargetManifest[config].insert(f); - // Add to the content listing for the file's directory. std::string dir = cmSystemTools::GetFilenamePath(f); std::string file = cmSystemTools::GetFilenameName(f); @@ -2722,9 +2786,9 @@ cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs, } // Shorten the output name (in expected use case). - cmLocalGenerator* lg = this->GetLocalGenerators()[0]; - std::string fname = lg->Convert(outputs[0], - cmLocalGenerator::HOME_OUTPUT); + cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot()); + std::string fname = converter.Convert( + outputs[0], cmLocalGenerator::HOME_OUTPUT); // Associate the hash with this output. this->RuleHashes[fname] = hash; @@ -2974,61 +3038,21 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const { void cmGlobalGenerator::CreateEvaluationSourceFiles( std::string const& config) const { - for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator - li = this->EvaluationFiles.begin(); - li != this->EvaluationFiles.end(); - ++li) + unsigned int i; + for (i = 0; i < this->LocalGenerators.size(); ++i) { - (*li)->CreateOutputFile(config); + this->LocalGenerators[i]->CreateEvaluationFileOutputs(config); } } //---------------------------------------------------------------------------- -void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile, - cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr, - cmMakefile *makefile, - cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, - bool inputIsContent) -{ - this->EvaluationFiles.push_back( - new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr, - makefile, condition, - inputIsContent)); -} - -//---------------------------------------------------------------------------- void cmGlobalGenerator::ProcessEvaluationFiles() { std::vector<std::string> generatedFiles; - for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator - li = this->EvaluationFiles.begin(); - li != this->EvaluationFiles.end(); - ++li) + unsigned int i; + for (i = 0; i < this->LocalGenerators.size(); ++i) { - (*li)->Generate(); - if (cmSystemTools::GetFatalErrorOccured()) - { - return; - } - std::vector<std::string> files = (*li)->GetFiles(); - std::sort(files.begin(), files.end()); - - std::vector<std::string> intersection; - std::set_intersection(files.begin(), files.end(), - generatedFiles.begin(), generatedFiles.end(), - std::back_inserter(intersection)); - if (!intersection.empty()) - { - cmSystemTools::Error("Files to be generated by multiple different " - "commands: ", cmWrap('"', intersection, '"', " ").c_str()); - return; - } - - generatedFiles.insert(generatedFiles.end(), - files.begin(), files.end()); - std::vector<std::string>::iterator newIt = - generatedFiles.end() - files.size(); - std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end()); + this->LocalGenerators[i]->ProcessEvaluationFiles(generatedFiles); } } @@ -3045,7 +3069,8 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() cmake::InstalledFilesMap const& installedFiles = this->CMakeInstance->GetInstalledFiles(); - cmMakefile* mf = this->LocalGenerators[0]->GetMakefile(); + cmLocalGenerator* lg = this->LocalGenerators[0]; + cmMakefile* mf = lg->GetMakefile(); std::vector<std::string> configs; std::string config = mf->GetConfigurations(configs, false); @@ -3067,7 +3092,7 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() cmInstalledFile const& installedFile = i->second; cmCPackPropertiesGenerator cpackPropertiesGenerator( - mf, installedFile, configs); + lg, installedFile, configs); cpackPropertiesGenerator.Generate(file, config, configs); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 979e971..9fc2d45 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -34,7 +34,6 @@ class cmake; class cmGeneratorTarget; -class cmGeneratorExpressionEvaluationFile; class cmMakefile; class cmLocalGenerator; class cmExternalMakefileProjectGenerator; @@ -57,9 +56,8 @@ public: cmGlobalGenerator(cmake* cm); virtual ~cmGlobalGenerator(); - cmLocalGenerator* MakeLocalGenerator( - cmState::Snapshot snapshot = cmState::Snapshot(), - cmLocalGenerator* parent = 0); + virtual cmLocalGenerator* + CreateLocalGenerator(cmMakefile* mf); ///! Get the name for this generator virtual std::string GetName() const { return "Generic"; } @@ -86,12 +84,21 @@ public: */ virtual void Configure(); + virtual bool Compute(); + + enum TargetTypes { + AllTargets, + ImportedOnly + }; + + void CreateGenerationObjects(TargetTypes targetTypes = AllTargets); + /** * Generate the all required files for building this project/tree. This * basically creates a series of LocalGenerators for each directory and * requests that they Generate. */ - void DoGenerate(); + virtual void Generate(); /** * Set/Get and Clear the enabled languages. @@ -165,15 +172,20 @@ public: cmake *GetCMakeInstance() const { return this->CMakeInstance; } void SetConfiguredFilesPath(cmGlobalGenerator* gen); + const std::vector<cmMakefile*>& GetMakefiles() const { + return this->Makefiles;} const std::vector<cmLocalGenerator *>& GetLocalGenerators() const { return this->LocalGenerators;} - cmLocalGenerator* GetCurrentLocalGenerator() - {return this->CurrentLocalGenerator;} + cmMakefile* GetCurrentMakefile() const + { + return this->CurrentMakefile; + } - void SetCurrentLocalGenerator(cmLocalGenerator* lg) - {this->CurrentLocalGenerator = lg;} + void SetCurrentMakefile(cmMakefile* mf) + {this->CurrentMakefile = mf;} + void AddMakefile(cmMakefile *mf); void AddLocalGenerator(cmLocalGenerator *lg); ///! Set an generator for an "external makefile based project" @@ -190,7 +202,7 @@ public: cmExportSetMap& GetExportSets() {return this->ExportSets;} /** Add a file to the manifest of generated targets for a configuration. */ - void AddToManifest(const std::string& config, std::string const& f); + void AddToManifest(std::string const& f); void EnableInstallTarget(); @@ -229,7 +241,7 @@ public: #if defined(_WIN32) && !defined(__CYGWIN__) /** Is this the Visual Studio 6 generator? */ - virtual bool IsForVS6() const { return false; } + bool IsForVS6() const { return this->GetName() == "Visual Studio 6"; } #endif ///! Find a target by name by searching the local generators. @@ -243,6 +255,7 @@ public: that is a framework. */ bool NameResolvesToFramework(const std::string& libname) const; + cmMakefile* FindMakefile(const std::string& start_dir) const; ///! Find a local generator by its startdirectory cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const; @@ -254,11 +267,6 @@ public: const std::string& suffix, std::string& dir); - /** Get the manifest of all targets that will be built for each - configuration. This is valid during generation only. */ - cmTargetManifest const& GetTargetManifest() const - { return this->TargetManifest; } - /** Get the content of a directory. Directory listings are cached and re-loaded from disk only when modified. During the generation step the content will include the target files to be built even if @@ -290,11 +298,17 @@ public: // what targets does the specified target depend on directly // via a target_link_libraries or add_dependencies - TargetDependSet const& GetTargetDirectDepends(cmTarget const& target); + TargetDependSet const& GetTargetDirectDepends( + const cmGeneratorTarget* target); /** Get per-target generator information. */ cmGeneratorTarget* GetGeneratorTarget(cmTarget const*) const; + void AddGeneratorTarget(cmTarget* t, cmGeneratorTarget* gt) + { + this->GeneratorTargets[t] = gt; + } + const std::map<std::string, std::vector<cmLocalGenerator*> >& GetProjectMap() const {return this->ProjectMap;} @@ -310,8 +324,6 @@ public: { return this->BinaryDirectories.insert(dir).second; } - /** Supported systems creates a GUID for the given name */ - virtual void CreateGUID(const std::string&) {} /** Return true if the generated build tree may contain multiple builds. i.e. "Can I build Debug and Release in the same tree?" */ @@ -324,12 +336,6 @@ public: static std::string EscapeJSON(const std::string& s); - void AddEvaluationFile(const std::string &inputFile, - cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName, - cmMakefile *makefile, - cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, - bool inputIsContent); - void ProcessEvaluationFiles(); std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets() @@ -359,8 +365,6 @@ public: std::string MakeSilentFlag; protected: - virtual void Generate(); - typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend // information, and also collect all the targets @@ -368,11 +372,13 @@ protected: TargetDependSet& originalTargets, cmLocalGenerator* root, GeneratorVector const&); bool IsRootOnlyTarget(cmTarget* target) const; - void AddTargetDepends(cmTarget const* target, + void AddTargetDepends(const cmGeneratorTarget* target, TargetDependSet& projectTargets); void SetLanguageEnabledFlag(const std::string& l, cmMakefile* mf); void SetLanguageEnabledMaps(const std::string& l, cmMakefile* mf); void FillExtensionToLanguageMap(const std::string& l, cmMakefile* mf); + virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang, + const char* envVar) const; virtual bool ComputeTargetDepends(); @@ -388,42 +394,34 @@ protected: // Fill the ProjectMap, this must be called after LocalGenerators // has been populated. void FillProjectMap(); - void CheckLocalGenerators(); + void CheckTargetProperties(); + bool IsExcluded(cmState::Snapshot const& root, + cmState::Snapshot const& snp) const; bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const; - bool IsExcluded(cmLocalGenerator* root, cmTarget const& target) const; - void FillLocalGeneratorToTargetMap(); + bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const; + virtual void InitializeProgressMarks() {} void CreateDefaultGlobalTargets(cmTargets* targets); cmTarget CreateGlobalTarget(const std::string& name, const char* message, const cmCustomCommandLines* commandLines, std::vector<std::string> depends, const char* workingDir, bool uses_terminal); - bool NeedSymbolicMark; - bool UseLinkScript; - bool ForceUnixPaths; - bool ToolSupportsColor; std::string FindMakeProgramFile; std::string ConfiguredFilesPath; cmake *CMakeInstance; + std::vector<cmMakefile*> Makefiles; std::vector<cmLocalGenerator *> LocalGenerators; - cmLocalGenerator* CurrentLocalGenerator; + cmMakefile* CurrentMakefile; // map from project name to vector of local generators in that project std::map<std::string, std::vector<cmLocalGenerator*> > ProjectMap; - std::map<cmLocalGenerator*, std::set<cmTarget const*> > - LocalGeneratorToTargetMap; // Set of named installation components requested by the project. std::set<std::string> InstallComponents; - bool InstallTargetEnabled; // Sets of named target exports cmExportSetMap ExportSets; std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets; std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets; - // Manifest of all targets that will be built for each configuration. - // This is computed just before local generators generate. - cmTargetManifest TargetManifest; - // All targets in the entire project. #if defined(CMAKE_BUILD_WITH_CMAKE) #ifdef CMake_HAVE_CXX11_UNORDERED_MAP @@ -437,18 +435,12 @@ protected: TargetMap TotalTargets; TargetMap AliasTargets; TargetMap ImportedTargets; - std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; const char* GetPredefinedTargetsFolder(); virtual bool UseFolderProperty(); private: - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); - cmMakefile* TryCompileOuterMakefile; - float FirstTimeProgress; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator std::map<std::string, bool> IgnoreExtensions; @@ -472,8 +464,6 @@ private: virtual void ForceLinkerLanguages(); - virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - const char* envVar) const; void CheckCompilerIdCompatibility(cmMakefile* mf, std::string const& lang) const; @@ -483,14 +473,15 @@ private: std::vector<std::string> FilesReplacedDuringGenerate; // Store computed inter-target dependencies. - typedef std::map<cmTarget const*, TargetDependSet> TargetDependMap; + typedef std::map<cmGeneratorTarget const*, TargetDependSet> TargetDependMap; TargetDependMap TargetDependencies; // Per-target generator information. cmGeneratorTargetsType GeneratorTargets; friend class cmake; - void CreateGeneratorTargets(cmMakefile* mf); - void CreateGeneratorTargets(); + void CreateGeneratorTargets(TargetTypes targetTypes, cmLocalGenerator* lg); + void InitGeneratorTargets(); + void CreateGeneratorTargets(TargetTypes targetTypes); void ClearGeneratorMembers(); @@ -521,6 +512,14 @@ private: // Pool of file locks cmFileLockPool FileLockPool; #endif + +protected: + float FirstTimeProgress; + bool NeedSymbolicMark; + bool UseLinkScript; + bool ForceUnixPaths; + bool ToolSupportsColor; + bool InstallTargetEnabled; }; #endif diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index f764418..6dde1e3 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -33,10 +33,9 @@ cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() } cmLocalGenerator * -cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalGhsMultiGenerator(this, parent, snapshot); + return new cmLocalGhsMultiGenerator(this, mf); } void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry &entry) diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index f1a3ed7..8f88d4f 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -31,8 +31,7 @@ public: { return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>(); } ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile* mf); /// @return the name of this generator. static std::string GetActualName() { return "Green Hills MULTI"; } diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index 50e7053..3f33f91 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -36,18 +36,6 @@ void cmGlobalJOMMakefileGenerator // pick a default mf->AddDefinition("CMAKE_GENERATOR_CC", "cl"); mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl"); - if(!(cmSystemTools::GetEnv("INCLUDE") && - cmSystemTools::GetEnv("LIB")) - ) - { - std::string message = "To use the JOM generator, cmake must be run " - "from a shell that can use the compiler cl from the command line. " - "This environment does not contain INCLUDE, LIB, or LIBPATH, and " - "these must be set for the cl compiler to work. "; - mf->IssueMessage(cmake::WARNING, - message); - } - this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } @@ -58,3 +46,19 @@ void cmGlobalJOMMakefileGenerator entry.Name = cmGlobalJOMMakefileGenerator::GetActualName(); entry.Brief = "Generates JOM makefiles."; } + +//---------------------------------------------------------------------------- +void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os, + std::string const& lang, + const char* envVar) const +{ + if(lang == "CXX" || lang == "C") + { + os << + "To use the JOM generator with Visual C++, cmake must be run from a " + "shell that can use the compiler cl from the command line. This " + "environment is unable to invoke the cl compiler. To fix this problem, " + "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n"; + } + this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar); +} diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index 2185b23..1869fed 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -42,6 +42,9 @@ public: */ virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile *, bool optional); +private: + void PrintCompilerAdvice(std::ostream& os, std::string const& lang, + const char* envVar) const; }; #endif diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx index 98557cc..138ddbb 100644 --- a/Source/cmGlobalKdevelopGenerator.cxx +++ b/Source/cmGlobalKdevelopGenerator.cxx @@ -70,13 +70,13 @@ void cmGlobalKdevelopGenerator::Generate() lg!=lgs.end(); lg++) { cmMakefile* makefile=(*lg)->GetMakefile(); - cmTargets& targets=makefile->GetTargets(); - for (cmTargets::iterator ti = targets.begin(); + cmGeneratorTargetsType const& targets = makefile->GetGeneratorTargets(); + for (cmGeneratorTargetsType::const_iterator ti = targets.begin(); ti != targets.end(); ti++) { - if (ti->second.GetType()==cmTarget::EXECUTABLE) + if (ti->second->GetType()==cmTarget::EXECUTABLE) { - executable = ti->second.GetLocation(""); + executable = ti->second->GetLocation(""); break; } } diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index a84923b..9a6f3ba 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -62,19 +62,19 @@ void cmGlobalMSYSMakefileGenerator locations.push_back("c:/mingw/bin"); std::string tgcc = cmSystemTools::FindProgram("gcc", locations); std::string gcc = "gcc.exe"; - if(tgcc.size()) + if(!tgcc.empty()) { gcc = tgcc; } std::string tgxx = cmSystemTools::FindProgram("g++", locations); std::string gxx = "g++.exe"; - if(tgxx.size()) + if(!tgxx.empty()) { gxx = tgxx; } std::string trc = cmSystemTools::FindProgram("windres", locations); std::string rc = "windres.exe"; - if(trc.size()) + if(!trc.empty()) { rc = trc; } diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 4219c34..7c570a6 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -36,18 +36,6 @@ void cmGlobalNMakeMakefileGenerator // pick a default mf->AddDefinition("CMAKE_GENERATOR_CC", "cl"); mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl"); - if(!(cmSystemTools::GetEnv("INCLUDE") && - cmSystemTools::GetEnv("LIB")) - ) - { - std::string message = "To use the NMake generator, cmake must be run " - "from a shell that can use the compiler cl from the command line. " - "This environment does not contain INCLUDE, LIB, or LIBPATH, and " - "these must be set for the cl compiler to work. "; - mf->IssueMessage(cmake::WARNING, - message); - } - this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } @@ -58,3 +46,19 @@ void cmGlobalNMakeMakefileGenerator entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName(); entry.Brief = "Generates NMake makefiles."; } + +//---------------------------------------------------------------------------- +void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(std::ostream& os, + std::string const& lang, + const char* envVar) const +{ + if(lang == "CXX" || lang == "C") + { + os << + "To use the NMake generator with Visual C++, cmake must be run from a " + "shell that can use the compiler cl from the command line. This " + "environment is unable to invoke the cl compiler. To fix this problem, " + "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n"; + } + this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar); +} diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index dd72c49..3c8375a 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -40,6 +40,9 @@ public: */ virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile *, bool optional); +private: + void PrintCompilerAdvice(std::ostream& os, std::string const& lang, + const char* envVar) const; }; #endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 103d75a..120bb03 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -505,7 +505,7 @@ void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os, cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) - : cmGlobalGenerator(cm) + : cmGlobalCommonGenerator(cm) , BuildFileStream(0) , RulesFileStream(0) , CompileCommandsStream(0) @@ -528,10 +528,9 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) // Virtual public methods. cmLocalGenerator* -cmGlobalNinjaGenerator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmGlobalNinjaGenerator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalNinjaGenerator(this, parent, snapshot); + return new cmLocalNinjaGenerator(this, mf); } void cmGlobalNinjaGenerator @@ -547,6 +546,18 @@ void cmGlobalNinjaGenerator // Source/cmake.cxx void cmGlobalNinjaGenerator::Generate() { + // Check minimum Ninja version. + if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + CurrentNinjaVersion().c_str(), + RequiredNinjaVersion().c_str())) + { + std::ostringstream msg; + msg << "The detected version of Ninja (" << this->CurrentNinjaVersion(); + msg << ") is less than the version of Ninja required by CMake ("; + msg << this->RequiredNinjaVersion() << ")."; + this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str()); + return; + } this->OpenBuildFileStream(); this->OpenRulesFileStream(); @@ -910,10 +921,12 @@ cmGlobalNinjaGenerator case cmTarget::SHARED_LIBRARY: case cmTarget::STATIC_LIBRARY: case cmTarget::MODULE_LIBRARY: + { + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(target); outputs.push_back(ng->ConvertToNinjaPath( - target->GetFullPath(configName, false, realname))); + gtgt->GetFullPath(configName, false, realname))); break; - + } case cmTarget::OBJECT_LIBRARY: case cmTarget::UTILITY: { std::string path = ng->ConvertToNinjaPath( @@ -949,8 +962,8 @@ cmGlobalNinjaGenerator std::set<std::string> const& utils = target->GetUtilities(); std::copy(utils.begin(), utils.end(), std::back_inserter(outputs)); } else { - cmTargetDependSet const& targetDeps = - this->GetTargetDirectDepends(*target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(gt); for (cmTargetDependSet::const_iterator i = targetDeps.begin(); i != targetDeps.end(); ++i) { @@ -958,7 +971,7 @@ cmGlobalNinjaGenerator { continue; } - this->AppendTargetOutputs(*i, outputs); + this->AppendTargetOutputs((*i)->Target, outputs); } } } @@ -1051,23 +1064,21 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) { knownDependencies.insert( ng->ConvertToNinjaPath( *j ) ); } - } - knownDependencies.insert( "CMakeCache.txt" ); - - for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator - li = this->EvaluationFiles.begin(); - li != this->EvaluationFiles.end(); - ++li) - { - //get all the files created by generator expressions and convert them - //to ninja paths - std::vector<std::string> files = (*li)->GetFiles(); - typedef std::vector<std::string>::const_iterator vect_it; - for(vect_it j = files.begin(); j != files.end(); ++j) + std::vector<cmGeneratorExpressionEvaluationFile*> const& ef = + (*i)->GetMakefile()->GetEvaluationFiles(); + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = ef.begin(); li != ef.end(); ++li) { - knownDependencies.insert( ng->ConvertToNinjaPath( *j ) ); + //get all the files created by generator expressions and convert them + //to ninja paths + std::vector<std::string> evaluationFiles = (*li)->GetFiles(); + for(vect_it j = evaluationFiles.begin(); j != evaluationFiles.end(); ++j) + { + knownDependencies.insert( ng->ConvertToNinjaPath( *j ) ); + } } } + knownDependencies.insert( "CMakeCache.txt" ); for(TargetAliasMap::const_iterator i= this->TargetAliases.begin(); i != this->TargetAliases.end(); @@ -1256,7 +1267,7 @@ std::string cmGlobalNinjaGenerator::ninjaCmd() const return "ninja"; } -std::string cmGlobalNinjaGenerator::ninjaVersion() const +std::string cmGlobalNinjaGenerator::CurrentNinjaVersion() const { std::string version; std::string command = ninjaCmd() + " --version"; @@ -1264,13 +1275,14 @@ std::string cmGlobalNinjaGenerator::ninjaVersion() const &version, 0, 0, 0, cmSystemTools::OUTPUT_NONE); - return version; + return cmSystemTools::TrimWhitespace(version); } bool cmGlobalNinjaGenerator::SupportsConsolePool() const { return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, - ninjaVersion().c_str(), "1.5") == false; + CurrentNinjaVersion().c_str(), + RequiredNinjaVersionForConsolePool().c_str()) == false; } void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index ffd1cdc..d204a50 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -13,7 +13,7 @@ #ifndef cmGlobalNinjaGenerator_h # define cmGlobalNinjaGenerator_h -# include "cmGlobalGenerator.h" +# include "cmGlobalCommonGenerator.h" # include "cmGlobalGeneratorFactory.h" # include "cmNinjaTypes.h" @@ -42,7 +42,7 @@ class cmGeneratorTarget; * - We extensively use Ninja variable overloading system to minimize the * number of generated rules. */ -class cmGlobalNinjaGenerator : public cmGlobalGenerator +class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator { public: /// The default name of Ninja's build file. Typically: build.ninja. @@ -162,33 +162,24 @@ public: public: cmGlobalNinjaGenerator(cmake* cm); - /// Convenience method for creating an instance of this class. static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); } - /// Destructor. virtual ~cmGlobalNinjaGenerator() { } - /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator() - virtual cmLocalGenerator* CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf); - /// Overloaded methods. @see cmGlobalGenerator::GetName(). virtual std::string GetName() const { return cmGlobalNinjaGenerator::GetActualName(); } - /// @return the name of this generator. static std::string GetActualName() { return "Ninja"; } - /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() static void GetDocumentation(cmDocumentationEntry& entry); - /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage() virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile* mf, bool optional); - /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand() virtual void GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, @@ -289,7 +280,7 @@ public: const std::vector<cmLocalGenerator*>& GetLocalGenerators() const { return LocalGenerators; } - bool IsExcluded(cmLocalGenerator* root, cmTarget& target) { + bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) { return cmGlobalGenerator::IsExcluded(root, target); } int GetRuleCmdLength(const std::string& name) { @@ -299,17 +290,16 @@ public: virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; - std::string ninjaVersion() const; - + std::string CurrentNinjaVersion() const; + // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3 + static std::string RequiredNinjaVersion() { return "1.3"; } + static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; } bool SupportsConsolePool() const; protected: - /// Overloaded methods. @see cmGlobalGenerator::Generate() virtual void Generate(); - /// Overloaded methods. - /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const { return true; } diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 4fe52dd..cf4fd69 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -21,7 +21,7 @@ #include "cmAlgorithms.h" cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm) - : cmGlobalGenerator(cm) + : cmGlobalCommonGenerator(cm) { // This type of makefile always requires unix style paths this->ForceUnixPaths = true; @@ -59,11 +59,10 @@ void cmGlobalUnixMakefileGenerator3 } ///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalUnixMakefileGenerator3(this, parent, snapshot); + return new cmLocalUnixMakefileGenerator3(this, mf); } //---------------------------------------------------------------------------- @@ -482,8 +481,8 @@ cmGlobalUnixMakefileGenerator3 // Add this to the list of depends rules in this directory. if((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) && (!check_relink || - gtarget->Target - ->NeedRelinkBeforeInstall(lg->ConfigurationName))) + gtarget + ->NeedRelinkBeforeInstall(lg->GetConfigName()))) { std::string tname = lg->GetRelativeTargetDirectory(*gtarget->Target); tname += "/"; @@ -495,12 +494,12 @@ cmGlobalUnixMakefileGenerator3 // The directory-level rule should depend on the directory-level // rules of the subdirectories. - for(std::vector<cmLocalGenerator*>::iterator sdi = - lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi) + std::vector<cmState::Snapshot> children + = lg->GetMakefile()->GetStateSnapshot().GetChildren(); + for(std::vector<cmState::Snapshot>::const_iterator + ci = children.begin(); ci != children.end(); ++ci) { - cmLocalUnixMakefileGenerator3* slg = - static_cast<cmLocalUnixMakefileGenerator3*>(*sdi); - std::string subdir = slg->GetMakefile()->GetCurrentBinaryDirectory(); + std::string subdir = ci->GetDirectory().GetCurrentBinary(); subdir += "/"; subdir += pass; depends.push_back(subdir); @@ -529,7 +528,7 @@ cmGlobalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3* lg) { // Only subdirectories need these rules. - if(lg->IsRootMakefile()) + if(lg->GetMakefile()->IsRootMakefile()) { return; } @@ -578,16 +577,20 @@ void cmGlobalUnixMakefileGenerator3 makeOptions.begin(), makeOptions.end()); if (!targetName.empty()) { + cmMakefile* mf; cmLocalUnixMakefileGenerator3 *lg; if (!this->LocalGenerators.empty()) { lg = static_cast<cmLocalUnixMakefileGenerator3 *> (this->LocalGenerators[0]); + mf = lg->GetMakefile(); } else { + cmState::Snapshot snapshot = this->CMakeInstance->GetCurrentSnapshot(); + mf = new cmMakefile(this, snapshot); lg = static_cast<cmLocalUnixMakefileGenerator3 *> - (this->MakeLocalGenerator()); + (this->CreateLocalGenerator(mf)); // set the Start directories lg->GetMakefile()->SetCurrentSourceDirectory (this->CMakeInstance->GetHomeDirectory()); @@ -606,6 +609,7 @@ void cmGlobalUnixMakefileGenerator3 if (this->LocalGenerators.empty()) { delete lg; + delete mf; } } } @@ -691,8 +695,8 @@ cmGlobalUnixMakefileGenerator3 // Add a local name for the rule to relink the target before // installation. - if(gtarget->Target - ->NeedRelinkBeforeInstall(lg->ConfigurationName)) + if(gtarget + ->NeedRelinkBeforeInstall(lg->GetConfigName())) { makeTargetName = lg->GetRelativeTargetDirectory(*gtarget->Target); makeTargetName += "/preinstall"; @@ -801,15 +805,27 @@ cmGlobalUnixMakefileGenerator3 } progress.Arg = progressArg.str(); } - lg->AppendEcho(commands, "Built target " + name, - cmLocalUnixMakefileGenerator3::EchoNormal, &progress); - this->AppendGlobalTargetDepends(depends,*gtarget->Target); + bool targetMessages = true; + if (const char* tgtMsg = this->GetCMakeInstance() + ->GetState() + ->GetGlobalProperty("TARGET_MESSAGES")) + { + targetMessages = cmSystemTools::IsOn(tgtMsg); + } + + if (targetMessages) + { + lg->AppendEcho(commands, "Built target " + name, + cmLocalUnixMakefileGenerator3::EchoNormal, &progress); + } + + this->AppendGlobalTargetDepends(depends, gtarget); lg->WriteMakeRule(ruleFileStream, "All Build rule for target.", localName, depends, commands, true); // add the all/all dependency - if(!this->IsExcluded(this->LocalGenerators[0], *gtarget->Target)) + if(!this->IsExcluded(this->LocalGenerators[0], gtarget)) { depends.clear(); depends.push_back(localName); @@ -830,9 +846,9 @@ cmGlobalUnixMakefileGenerator3 cmLocalGenerator::FULL, cmLocalGenerator::SHELL); // - std::set<cmTarget const*> emitted; + std::set<cmGeneratorTarget const*> emitted; progCmd << " " - << this->CountProgressMarksInTarget(gtarget->Target, emitted); + << this->CountProgressMarksInTarget(gtarget, emitted); commands.push_back(progCmd.str()); } std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); @@ -864,8 +880,8 @@ cmGlobalUnixMakefileGenerator3 name, depends, commands, true); // Add rules to prepare the target for installation. - if(gtarget->Target - ->NeedRelinkBeforeInstall(lg->ConfigurationName)) + if(gtarget + ->NeedRelinkBeforeInstall(lg->GetConfigName())) { localName = lg->GetRelativeTargetDirectory(*gtarget->Target); localName += "/preinstall"; @@ -877,7 +893,7 @@ cmGlobalUnixMakefileGenerator3 "Pre-install relink rule for target.", localName, depends, commands, true); - if(!this->IsExcluded(this->LocalGenerators[0], *gtarget->Target)) + if(!this->IsExcluded(this->LocalGenerators[0], gtarget)) { depends.clear(); depends.push_back(localName); @@ -905,17 +921,71 @@ cmGlobalUnixMakefileGenerator3 } } +// Build a map that contains a the set of targets used by each local +// generator directory level. +void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks() +{ + this->DirectoryTargetsMap.clear(); + // Loop over all targets in all local generators. + for(std::vector<cmLocalGenerator*>::const_iterator + lgi = this->LocalGenerators.begin(); + lgi != this->LocalGenerators.end(); ++lgi) + { + cmLocalGenerator* lg = *lgi; + cmMakefile* mf = lg->GetMakefile(); + cmTargets const& targets = mf->GetTargets(); + for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t) + { + cmTarget const& target = t->second; + + cmGeneratorTarget* gt = this->GetGeneratorTarget(&target); + + cmLocalGenerator* tlg = gt->GetLocalGenerator(); + + if(gt->GetType() == cmTarget::INTERFACE_LIBRARY + || gt->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) + { + continue; + } + + cmState::Snapshot csnp = lg->GetStateSnapshot(); + cmState::Snapshot tsnp = tlg->GetStateSnapshot(); + + // Consider the directory containing the target and all its + // parents until something excludes the target. + for( ; csnp.IsValid() && !this->IsExcluded(csnp, tsnp); + csnp = csnp.GetBuildsystemDirectoryParent()) + { + // This local generator includes the target. + std::set<cmGeneratorTarget const*>& targetSet = + this->DirectoryTargetsMap[csnp]; + targetSet.insert(gt); + + // Add dependencies of the included target. An excluded + // target may still be included if it is a dependency of a + // non-excluded target. + TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(gt); + for(TargetDependSet::const_iterator ti = tgtdeps.begin(); + ti != tgtdeps.end(); ++ti) + { + targetSet.insert(*ti); + } + } + } + } +} + //---------------------------------------------------------------------------- size_t cmGlobalUnixMakefileGenerator3 -::CountProgressMarksInTarget(cmTarget const* target, - std::set<cmTarget const*>& emitted) +::CountProgressMarksInTarget(cmGeneratorTarget const* target, + std::set<cmGeneratorTarget const*>& emitted) { size_t count = 0; if(emitted.insert(target).second) { - count = this->ProgressMap[target].Marks.size(); - TargetDependSet const& depends = this->GetTargetDirectDepends(*target); + count = this->ProgressMap[target->Target].Marks.size(); + TargetDependSet const& depends = this->GetTargetDirectDepends(target); for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) { @@ -935,10 +1005,10 @@ cmGlobalUnixMakefileGenerator3 ::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg) { size_t count = 0; - std::set<cmTarget const*> emitted; - std::set<cmTarget const*> const& targets - = this->LocalGeneratorToTargetMap[lg]; - for(std::set<cmTarget const*>::const_iterator t = targets.begin(); + std::set<cmGeneratorTarget const*> emitted; + std::set<cmGeneratorTarget const*> const& targets + = this->DirectoryTargetsMap[lg->GetStateSnapshot()]; + for(std::set<cmGeneratorTarget const*>::const_iterator t = targets.begin(); t != targets.end(); ++t) { count += this->CountProgressMarksInTarget(*t, emitted); @@ -987,22 +1057,21 @@ cmGlobalUnixMakefileGenerator3::TargetProgress void cmGlobalUnixMakefileGenerator3 ::AppendGlobalTargetDepends(std::vector<std::string>& depends, - cmTarget& target) + cmGeneratorTarget* target) { TargetDependSet const& depends_set = this->GetTargetDirectDepends(target); for(TargetDependSet::const_iterator i = depends_set.begin(); i != depends_set.end(); ++i) { // Create the target-level dependency. - cmTarget const* dep = *i; + cmGeneratorTarget const* dep = *i; if (dep->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; } cmLocalUnixMakefileGenerator3* lg3 = - static_cast<cmLocalUnixMakefileGenerator3*> - (dep->GetMakefile()->GetLocalGenerator()); - std::string tgtName = lg3->GetRelativeTargetDirectory(*dep); + static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator()); + std::string tgtName = lg3->GetRelativeTargetDirectory(*(*dep).Target); tgtName += "/all"; depends.push_back(tgtName); } @@ -1034,7 +1103,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]); // for the passed in makefile or if this is the top Makefile wripte out // the targets - if (lg2 == lg || lg->IsRootMakefile()) + if (lg2 == lg || lg->GetMakefile()->IsRootMakefile()) { // for each target Generate the rule files for each target. cmTargets& targets = lg2->GetMakefile()->GetTargets(); @@ -1080,7 +1149,8 @@ bool cmGlobalUnixMakefileGenerator3 ::NeedRequiresStep(cmTarget const& target) { std::set<std::string> languages; - target.GetLanguages(languages, + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&target); + gtgt->GetLanguages(languages, target.GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); for(std::set<std::string>::const_iterator l = languages.begin(); l != languages.end(); ++l) diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index a639ff0..5f39c79 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -12,7 +12,7 @@ #ifndef cmGlobalUnixMakefileGenerator3_h #define cmGlobalUnixMakefileGenerator3_h -#include "cmGlobalGenerator.h" +#include "cmGlobalCommonGenerator.h" #include "cmGlobalGeneratorFactory.h" class cmGeneratedFileStream; @@ -51,7 +51,7 @@ class cmLocalUnixMakefileGenerator3; */ -class cmGlobalUnixMakefileGenerator3 : public cmGlobalGenerator +class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator { public: cmGlobalUnixMakefileGenerator3(cmake* cm); @@ -67,9 +67,7 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator3 - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile* mf); /** * Try to determine system information such as shared library @@ -153,7 +151,7 @@ protected: cmLocalUnixMakefileGenerator3* lg); void AppendGlobalTargetDepends(std::vector<std::string>& depends, - cmTarget& target); + cmGeneratorTarget* target); // does this generator need a requires step for any of its targets bool NeedRequiresStep(cmTarget const&); @@ -198,14 +196,19 @@ protected: cmStrictTargetComparison> ProgressMapType; ProgressMapType ProgressMap; - size_t CountProgressMarksInTarget(cmTarget const* target, - std::set<cmTarget const*>& emitted); + size_t CountProgressMarksInTarget(cmGeneratorTarget const* target, + std::set<cmGeneratorTarget const*>& emitted); size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg); cmGeneratedFileStream *CommandDatabase; private: virtual const char* GetBuildIgnoreErrorsFlag() const { return "-i"; } virtual std::string GetEditCacheCommand() const; + + std::map<cmState::Snapshot, + std::set<cmGeneratorTarget const*>, + cmState::Snapshot::StrictWeakOrder> DirectoryTargetsMap; + virtual void InitializeProgressMarks(); }; #endif diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 4e8ada4..44d632d 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -306,17 +306,25 @@ void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout) } ///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalVisualStudio10Generator(this, parent, snapshot); + return new cmLocalVisualStudio10Generator(this, mf); } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio10Generator::Generate() +bool cmGlobalVisualStudio10Generator::Compute() { + if (!cmGlobalVisualStudio8Generator::Compute()) + { + return false; + } this->LongestSource = LongestSourcePath(); + return true; +} + +void cmGlobalVisualStudio10Generator::Generate() +{ this->cmGlobalVisualStudio8Generator::Generate(); if(this->LongestSource.Length > 0) { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 74d5022..8de7b09 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -45,9 +45,10 @@ public: std::vector<std::string> const& makeOptions = std::vector<std::string>() ); + virtual bool Compute(); + ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile* mf); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 632141a..df49948 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -173,10 +173,9 @@ cmGlobalVisualStudio6Generator::GenerateBuildCommand( ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalVisualStudio6Generator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmGlobalVisualStudio6Generator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalVisualStudio6Generator(this, parent, snapshot); + return new cmLocalVisualStudio6Generator(this, mf); } @@ -224,7 +223,7 @@ void cmGlobalVisualStudio6Generator tt = orderedProjectTargets.begin(); tt != orderedProjectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -255,7 +254,7 @@ void cmGlobalVisualStudio6Generator ::OutputDSWFile(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { - if(generators.size() == 0) + if(generators.empty()) { return; } diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 2460158..e9b24ea 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -39,8 +39,7 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile* mf); /** * Try to determine system information such as shared library @@ -85,8 +84,6 @@ public: virtual void FindMakeProgram(cmMakefile*); - virtual bool IsForVS6() const { return true; } - protected: virtual void Generate(); virtual const char* GetIDEVersion() { return "6.0"; } diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 1ab4c9c..607642c 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -212,7 +212,7 @@ cmGlobalVisualStudio71Generator { const char* name = di->c_str(); std::string guid = this->GetGUID(name); - if(guid.size() == 0) + if(guid.empty()) { std::string m = "Target: "; m += target.GetName(); @@ -250,7 +250,7 @@ void cmGlobalVisualStudio71Generator std::set<std::string>::const_iterator it; for(it = depends.begin(); it != depends.end(); ++it) { - if(it->size() > 0) + if(!it->empty()) { fout << "\t\t{" << this->GetGUID(it->c_str()) diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 4dd54d0..0175062 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -15,6 +15,7 @@ #include "cmGeneratedFileStream.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmUuid.h" #include "cmake.h" #include <cmsys/Encoding.hxx> @@ -278,12 +279,11 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand( } ///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator( + cmMakefile* mf) { cmLocalVisualStudio7Generator *lg = - new cmLocalVisualStudio7Generator(this, parent, snapshot); + new cmLocalVisualStudio7Generator(this, mf); return lg; } @@ -358,7 +358,7 @@ void cmGlobalVisualStudio7Generator ::OutputSLNFile(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { - if(generators.size() == 0) + if(generators.empty()) { return; } @@ -401,7 +401,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( for(OrderedTargetDependSet::const_iterator tt = projectTargets.begin(); tt != projectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -441,7 +441,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( for(OrderedTargetDependSet::const_iterator tt = projectTargets.begin(); tt != projectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -513,8 +513,6 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( cumulativePath = cumulativePath + "/" + *iter; } - - this->CreateGUID(cumulativePath.c_str()); } if (!cumulativePath.empty()) @@ -535,7 +533,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends( for(OrderedTargetDependSet::const_iterator tt = projectTargets.begin(); tt != projectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -737,7 +735,7 @@ cmGlobalVisualStudio7Generator { const char* name = di->c_str(); std::string guid = this->GetGUID(name); - if(guid.size() == 0) + if(guid.empty()) { std::string m = "Target: "; m += target.GetName(); @@ -815,14 +813,15 @@ void cmGlobalVisualStudio7Generator { bool extensibilityGlobalsOverridden = false; bool extensibilityAddInsOverridden = false; - const cmPropertyMap& props = root->GetMakefile()->GetProperties(); - for(cmPropertyMap::const_iterator itProp = props.begin(); - itProp != props.end(); ++itProp) + const std::vector<std::string> propKeys = + root->GetMakefile()->GetPropertyKeys(); + for(std::vector<std::string>::const_iterator it = propKeys.begin(); + it != propKeys.end(); ++it) { - if(itProp->first.find("VS_GLOBAL_SECTION_") == 0) + if(it->find("VS_GLOBAL_SECTION_") == 0) { std::string sectionType; - std::string name = itProp->first.substr(18); + std::string name = it->substr(18); if(name.find("PRE_") == 0) { name = name.substr(4); @@ -843,8 +842,9 @@ void cmGlobalVisualStudio7Generator extensibilityAddInsOverridden = true; fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; std::vector<std::string> keyValuePairs; - cmSystemTools::ExpandListArgument(itProp->second.GetValue(), - keyValuePairs); + cmSystemTools::ExpandListArgument( + root->GetMakefile()->GetProperty(it->c_str()), + keyValuePairs); for(std::vector<std::string>::const_iterator itPair = keyValuePairs.begin(); itPair != keyValuePairs.end(); ++itPair) { @@ -899,7 +899,6 @@ cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget const* target) fname += ".vcproj"; cmGeneratedFileStream fout(fname.c_str()); fout.SetCopyIfDifferent(true); - this->CreateGUID(pname.c_str()); std::string guid = this->GetGUID(pname.c_str()); fout << @@ -943,41 +942,29 @@ cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget const* target) return pname; } -std::string cmGlobalVisualStudio7Generator::GetGUID(const std::string& name) +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name) { - std::string guidStoreName = name; - guidStoreName += "_GUID_CMAKE"; - const char* storedGUID = - this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str()); - if(storedGUID) + std::string const& guidStoreName = name + "_GUID_CMAKE"; + if (const char* storedGUID = + this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str())) { return std::string(storedGUID); } - cmSystemTools::Error("Unknown Target referenced : ", - name.c_str()); - return ""; -} + // Compute a GUID that is deterministic but unique to the build tree. + std::string input = this->CMakeInstance->GetState()->GetBinaryDirectory(); + input += "|"; + input += name; + cmUuid uuidGenerator; -void cmGlobalVisualStudio7Generator::CreateGUID(const std::string& name) -{ - std::string guidStoreName = name; - guidStoreName += "_GUID_CMAKE"; - if(this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str())) - { - return; - } - std::string ret; - UUID uid; - unsigned short *uidstr; - UuidCreate(&uid); - UuidToStringW(&uid,&uidstr); - ret = cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(uidstr)); - RpcStringFreeW(&uidstr); - ret = cmSystemTools::UpperCase(ret); - this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(), - ret.c_str(), "Stored GUID", - cmState::INTERNAL); + std::vector<unsigned char> uuidNamespace; + uuidGenerator.StringToBinary( + "ee30c4be-5192-4fb0-b335-722a2dffe760", uuidNamespace); + + std::string guid = uuidGenerator.FromMd5(uuidNamespace, input); + + return cmSystemTools::UpperCase(guid); } //---------------------------------------------------------------------------- @@ -1039,12 +1026,13 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( { return activeConfigs; } + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties for(std::vector<std::string>::const_iterator i = configs.begin(); i != configs.end(); ++i) { const char* propertyValue = - target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str()); + gt->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str()); if(cmSystemTools::IsOff(propertyValue)) { activeConfigs.insert(*i); @@ -1058,12 +1046,12 @@ cmGlobalVisualStudio7Generator ::IsDependedOn(OrderedTargetDependSet const& projectTargets, cmTarget const* targetIn) { + cmGeneratorTarget* gtIn = this->GetGeneratorTarget(targetIn); for (OrderedTargetDependSet::const_iterator l = projectTargets.begin(); l != projectTargets.end(); ++l) { - cmTarget const& target = **l; - TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); - if(tgtdeps.count(targetIn)) + TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(*l); + if(tgtdeps.count(gtIn)) { return true; } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index c98d269..35575d1 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -43,8 +43,7 @@ public: std::string const& GetPlatformName() const; ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile* mf); virtual bool SetSystemName(std::string const& s, cmMakefile* mf); @@ -80,9 +79,8 @@ public: */ virtual void OutputSLNFile(); - ///! Create a GUID or get an existing one. - void CreateGUID(const std::string& name); - std::string GetGUID(const std::string& name); + ///! Lookup a stored GUID or compute one deterministically. + std::string GetGUID(std::string const& name); /** Append the subdirectory for the given configuration. */ virtual void AppendDirectoryForConfig(const std::string& prefix, diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index a3ebc61..28f0425 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -185,7 +185,6 @@ void cmGlobalVisualStudio8Generator void cmGlobalVisualStudio8Generator::Configure() { this->cmGlobalVisualStudio7Generator::Configure(); - this->CreateGUID(CMAKE_CHECK_BUILD_SYSTEM_TARGET); } //---------------------------------------------------------------------------- @@ -256,6 +255,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() no_working_directory, no_depends, noCommandLines); + cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg); + mf->AddGeneratorTarget(tgt, gt); + // Organize in the "predefined targets" folder: // if (this->UseFolderProperty()) @@ -310,14 +312,10 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); std::string argH = "-H"; - argH += lg->Convert(mf->GetHomeDirectory(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::UNCHANGED, true); + argH += mf->GetHomeDirectory(); commandLine.push_back(argH); std::string argB = "-B"; - argB += lg->Convert(mf->GetHomeOutputDirectory(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::UNCHANGED, true); + argB += mf->GetHomeOutputDirectory(); commandLine.push_back(argB); commandLine.push_back("--check-stamp-list"); commandLine.push_back(stampList.c_str()); @@ -350,8 +348,13 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio8Generator::Generate() +bool cmGlobalVisualStudio8Generator::Compute() { + if (!cmGlobalVisualStudio7Generator::Compute()) + { + return false; + } + if(this->AddCheckTarget()) { // All targets depend on the build-system check target. @@ -365,9 +368,7 @@ void cmGlobalVisualStudio8Generator::Generate() } } } - - // Now perform the main generation. - this->cmGlobalVisualStudio7Generator::Generate(); + return true; } //---------------------------------------------------------------------------- @@ -446,7 +447,8 @@ bool cmGlobalVisualStudio8Generator::ComputeTargetDepends() void cmGlobalVisualStudio8Generator::WriteProjectDepends( std::ostream& fout, const std::string&, const char*, cmTarget const& t) { - TargetDependSet const& unordered = this->GetTargetDirectDepends(t); + cmGeneratorTarget* gt = this->GetGeneratorTarget(&t); + TargetDependSet const& unordered = this->GetTargetDirectDepends(gt); OrderedTargetDependSet depends(unordered); for(OrderedTargetDependSet::const_iterator i = depends.begin(); i != depends.end(); ++i) diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index cc02b78..1c61103 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -67,7 +67,7 @@ public: return !this->WindowsCEVersion.empty(); } protected: - virtual void Generate(); + virtual bool Compute(); virtual const char* GetIDEVersion() { return "8.0"; } virtual std::string FindDevEnvCommand(); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 585d19a..2bf04b4 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -13,12 +13,14 @@ #include "cmGlobalVisualStudioGenerator.h" #include "cmCallVisualStudioMacro.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmLocalVisualStudioGenerator.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmTarget.h" #include <cmsys/Encoding.hxx> +#include "cmAlgorithms.h" //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm) @@ -62,8 +64,13 @@ std::string cmGlobalVisualStudioGenerator::GetRegistryBase( } //---------------------------------------------------------------------------- -void cmGlobalVisualStudioGenerator::Generate() +bool cmGlobalVisualStudioGenerator::Compute() { + if (!cmGlobalGenerator::Compute()) + { + return false; + } + // Add a special target that depends on ALL projects for easy build // of one configuration only. const char* no_working_dir = 0; @@ -74,7 +81,7 @@ void cmGlobalVisualStudioGenerator::Generate() { std::vector<cmLocalGenerator*>& gen = it->second; // add the ALL_BUILD to the first local generator of each project - if(gen.size()) + if(!gen.empty()) { // Use no actual command lines so that the target itself is not // considered always out of date. @@ -84,6 +91,9 @@ void cmGlobalVisualStudioGenerator::Generate() no_depends, no_commands, false, "Build all projects"); + cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]); + allBuild->GetMakefile()->AddGeneratorTarget(allBuild, gt); + #if 0 // Can't activate this code because we want ALL_BUILD // selected as the default "startup project" when first @@ -102,13 +112,19 @@ void cmGlobalVisualStudioGenerator::Generate() for(std::vector<cmLocalGenerator*>::iterator i = gen.begin(); i != gen.end(); ++i) { - cmTargets& targets = (*i)->GetMakefile()->GetTargets(); - for(cmTargets::iterator t = targets.begin(); + cmGeneratorTargetsType targets = + (*i)->GetMakefile()->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator t = targets.begin(); t != targets.end(); ++t) { + if (t->second->GetType() == cmTarget::GLOBAL_TARGET + || t->first->IsImported()) + { + continue; + } if(!this->IsExcluded(gen[0], t->second)) { - allBuild->AddUtility(t->second.GetName()); + allBuild->AddUtility(t->second->GetName()); } } } @@ -128,9 +144,7 @@ void cmGlobalVisualStudioGenerator::Generate() static_cast<cmLocalVisualStudioGenerator*>(*lgi); lg->AddCMakeListsRules(); } - - // Run all the local generators. - this->cmGlobalGenerator::Generate(); + return true; } //---------------------------------------------------------------------------- @@ -251,7 +265,7 @@ cmGlobalVisualStudioGenerator { std::vector<std::string> filenames; this->GetFilesReplacedDuringGenerate(filenames); - if (filenames.size() > 0) + if (!filenames.empty()) { // Convert vector to semi-colon delimited string of filenames: std::string projects; @@ -299,13 +313,14 @@ void cmGlobalVisualStudioGenerator::FillLinkClosure(cmTarget const* target, { if(linked.insert(target).second) { - TargetDependSet const& depends = this->GetTargetDirectDepends(*target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + TargetDependSet const& depends = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) { if(di->IsLink()) { - this->FillLinkClosure(*di, linked); + this->FillLinkClosure((*di)->Target, linked); } } } @@ -338,13 +353,14 @@ void cmGlobalVisualStudioGenerator::FollowLinkDepends( { // Static library targets do not list their link dependencies so // we must follow them transitively now. - TargetDependSet const& depends = this->GetTargetDirectDepends(*target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + TargetDependSet const& depends = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) { if(di->IsLink()) { - this->FollowLinkDepends(*di, linked); + this->FollowLinkDepends((*di)->Target, linked); } } } @@ -413,7 +429,8 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) target.GetType() != cmTarget::MODULE_LIBRARY && target.GetType() != cmTarget::EXECUTABLE); - TargetDependSet const& depends = this->GetTargetDirectDepends(target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(&target); + TargetDependSet const& depends = this->GetTargetDirectDepends(gt); // Collect implicit link dependencies (target_link_libraries). // Static libraries cannot depend on their link implementation @@ -427,7 +444,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) cmTargetDepend dep = *di; if(dep.IsLink()) { - this->FollowLinkDepends(dep, linkDepends); + this->FollowLinkDepends(dep->Target, linkDepends); } } } @@ -440,7 +457,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) cmTargetDepend dep = *di; if(dep.IsUtil()) { - this->FollowLinkDepends(dep, utilDepends); + this->FollowLinkDepends(dep->Target, utilDepends); } } @@ -819,17 +836,19 @@ void RegisterVisualStudioMacros(const std::string& macrosFile, bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget const& target) { + cmGeneratorTarget* gt = this->GetGeneratorTarget(&target); + // check to see if this is a fortran build std::set<std::string> languages; { // Issue diagnostic if the source files depend on the config. std::vector<cmSourceFile*> sources; - if (!target.GetConfigCommonSourceFiles(sources)) + if (!gt->GetConfigCommonSourceFiles(sources)) { return false; } } - target.GetLanguages(languages, ""); + gt->GetLanguages(languages, ""); if(languages.size() == 1) { if(*languages.begin() == "Fortran") @@ -843,7 +862,7 @@ cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget const& target) //---------------------------------------------------------------------------- bool cmGlobalVisualStudioGenerator::TargetCompare -::operator()(cmTarget const* l, cmTarget const* r) const +::operator()(cmGeneratorTarget const* l, cmGeneratorTarget const* r) const { // Make sure ALL_BUILD is first so it is the default active project. if(r->GetName() == "ALL_BUILD") @@ -868,7 +887,13 @@ cmGlobalVisualStudioGenerator::OrderedTargetDependSet cmGlobalVisualStudioGenerator::OrderedTargetDependSet ::OrderedTargetDependSet(TargetSet const& targets) { - this->insert(targets.begin(), targets.end()); + for (TargetSet::const_iterator it = targets.begin(); + it != targets.end(); ++it) + { + cmGeneratorTarget* gt = + (*it)->GetMakefile()->GetGlobalGenerator()->GetGeneratorTarget(*it); + this->insert(gt); + } } std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir( @@ -887,3 +912,71 @@ std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir( } return tmp; } + +void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( + cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands, + std::string const& configName) +{ + std::vector<std::string> outputs; + std::string deffile = gt->ObjectDirectory; + deffile += "/exportall.def"; + outputs.push_back(deffile); + std::vector<std::string> empty; + std::vector<cmSourceFile const*> objectSources; + gt->GetObjectSources(objectSources, configName); + std::map<cmSourceFile const*, std::string> mapping; + for(std::vector<cmSourceFile const*>::const_iterator it + = objectSources.begin(); it != objectSources.end(); ++it) + { + mapping[*it]; + } + gt->LocalGenerator-> + ComputeObjectFilenames(mapping, gt); + std::string obj_dir = gt->ObjectDirectory; + std::string cmakeCommand = cmSystemTools::GetCMakeCommand(); + cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand); + cmCustomCommandLine cmdl; + cmdl.push_back(cmakeCommand); + cmdl.push_back("-E"); + cmdl.push_back("__create_def"); + cmdl.push_back(deffile); + std::string obj_dir_expanded = obj_dir; + cmSystemTools::ReplaceString(obj_dir_expanded, + this->GetCMakeCFGIntDir(), + configName.c_str()); + std::string objs_file = obj_dir_expanded; + cmSystemTools::MakeDirectory(objs_file.c_str()); + objs_file += "/objects.txt"; + cmdl.push_back(objs_file); + cmGeneratedFileStream fout(objs_file.c_str()); + if(!fout) + { + cmSystemTools::Error("could not open ", objs_file.c_str()); + return; + } + for(std::vector<cmSourceFile const*>::const_iterator it + = objectSources.begin(); it != objectSources.end(); ++it) + { + // Find the object file name corresponding to this source file. + std::map<cmSourceFile const*, std::string>::const_iterator + map_it = mapping.find(*it); + // It must exist because we populated the mapping just above. + assert(!map_it->second.empty()); + std::string objFile = obj_dir + map_it->second; + // replace $(ConfigurationName) in the object names + cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(), + configName.c_str()); + if(cmHasLiteralSuffix(objFile, ".obj")) + { + fout << objFile << "\n"; + } + } + cmCustomCommandLines commandLines; + commandLines.push_back(cmdl); + cmCustomCommand command(gt->Target->GetMakefile(), + outputs, empty, empty, + commandLines, + "Auto build dll exports", + "."); + commands.push_back(command); +} diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 69b4564..64440ad 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -91,7 +91,8 @@ public: class TargetSet: public std::set<cmTarget const*> {}; struct TargetCompare { - bool operator()(cmTarget const* l, cmTarget const* r) const; + bool operator()(cmGeneratorTarget const* l, + cmGeneratorTarget const* r) const; }; class OrderedTargetDependSet; @@ -102,8 +103,12 @@ public: const std::string& config) const; void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; + + void AddSymbolExportCommand( + cmGeneratorTarget*, std::vector<cmCustomCommand>& commands, + std::string const& configName); protected: - virtual void Generate(); + virtual bool Compute(); // Does this VS version link targets to each other if there are // dependencies in the SLN file? This was done for VS versions diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7464e90..33babec 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -371,15 +371,19 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( //---------------------------------------------------------------------------- ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalXCodeGenerator::CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot) +cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalXCodeGenerator(this, parent, snapshot); + return new cmLocalXCodeGenerator(this, mf); } //---------------------------------------------------------------------------- -void cmGlobalXCodeGenerator::Generate() +bool cmGlobalXCodeGenerator::Compute() { + if (!cmGlobalGenerator::Compute()) + { + return false; + } + std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it; // make sure extra targets are added before calling // the parent generate which will call trace depends @@ -390,11 +394,17 @@ void cmGlobalXCodeGenerator::Generate() // add ALL_BUILD, INSTALL, etc this->AddExtraTargets(root, it->second); } + return true; +} + +void cmGlobalXCodeGenerator::Generate() +{ this->cmGlobalGenerator::Generate(); if(cmSystemTools::GetErrorOccuredFlag()) { return; } + std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it; for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it) { cmLocalGenerator* root = it->second[0]; @@ -449,10 +459,12 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, // Add ALL_BUILD const char* no_working_directory = 0; std::vector<std::string> no_depends; - mf->AddUtilityCommand("ALL_BUILD", true, no_depends, + cmTarget* allbuild = mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory, "echo", "Build all projects"); - cmTarget* allbuild = mf->FindTarget("ALL_BUILD"); + + cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); + mf->AddGeneratorTarget(allbuild, allBuildGt); // Refer to the main build configuration file for easy editing. std::string listfile = mf->GetCurrentSourceDirectory(); @@ -481,9 +493,13 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, std::string file = this->ConvertToRelativeForMake( this->CurrentReRunCMakeMakefile.c_str()); cmSystemTools::ReplaceString(file, "\\ ", " "); - mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends, + cmTarget* check = mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, + true, no_depends, no_working_directory, "make", "-f", file.c_str()); + + cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root); + mf->AddGeneratorTarget(check, checkGt); } // now make the allbuild depend on all the non-utility targets @@ -502,6 +518,11 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, { cmTarget& target = l->second; + if (target.GetType() == cmTarget::GLOBAL_TARGET) + { + continue; + } + if (regenerate && (l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) { target.AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET); @@ -750,7 +771,7 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, sf->GetProperty("COMPILE_DEFINITIONS"), true); if (!flagsBuild.IsEmpty()) { - if (flags.size()) + if (!flags.empty()) { flags += ' '; } @@ -843,6 +864,10 @@ GetSourcecodeValueFromFileExtension(const std::string& _ext, { sourcecode += ".c.objc"; } + else if (ext == "swift") + { + sourcecode += ".swift"; + } else if(ext == "plist") { sourcecode += ".text.plist"; @@ -1098,7 +1123,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // organize the sources std::vector<cmSourceFile*> classes; - if (!cmtarget.GetConfigCommonSourceFiles(classes)) + if (!gtgt->GetConfigCommonSourceFiles(classes)) { return false; } @@ -1352,12 +1377,13 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) return; } - std::string llang = cmtarget.GetLinkerLanguage("NOCONFIG"); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&cmtarget); + std::string llang = gtgt->GetLinkerLanguage("NOCONFIG"); if(llang.empty()) { return; } // If the language is compiled as a source trust Xcode to link with it. - cmTarget::LinkImplementation const* impl = - cmtarget.GetLinkImplementation("NOCONFIG"); + cmLinkImplementation const* impl = + gtgt->GetLinkImplementation("NOCONFIG"); for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -1478,7 +1504,8 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, } std::vector<cmSourceFile*> classes; - if (!cmtarget.GetConfigCommonSourceFiles(classes)) + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget); + if (!gtgt->GetConfigCommonSourceFiles(classes)) { return; } @@ -1664,7 +1691,7 @@ void cmGlobalXCodeGenerator for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); i != commands.end(); ++i) { - cmCustomCommandGenerator ccg(*i, configName, this->CurrentMakefile); + cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator); if(ccg.GetNumberOfCommands() > 0) { const std::vector<std::string>& outputs = ccg.GetOutputs(); @@ -1690,7 +1717,7 @@ void cmGlobalXCodeGenerator for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); i != commands.end(); ++i) { - cmCustomCommandGenerator ccg(*i, configName, this->CurrentMakefile); + cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator); if(ccg.GetNumberOfCommands() > 0) { makefileStream << "\n"; @@ -1778,7 +1805,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Compute the compilation flags for each language. std::set<std::string> languages; - target.GetLanguages(languages, configName); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); + gtgt->GetLanguages(languages, configName); std::map<std::string, std::string> cflags; for (std::set<std::string>::iterator li = languages.begin(); li != languages.end(); ++li) @@ -1800,7 +1828,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, AddCompileOptions(flags, &target, lang, configName); } - std::string llang = target.GetLinkerLanguage(configName); + std::string llang = gtgt->GetLinkerLanguage(configName); if(binary && llang.empty()) { cmSystemTools::Error @@ -1826,9 +1854,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Add the export symbol definition for shared library objects. this->AppendDefines(ppDefs, exportMacro); } - cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); std::vector<std::string> targetDefines; - target.GetCompileDefinitions(targetDefines, configName, "C"); + gtgt->GetCompileDefinitions(targetDefines, configName, "C"); this->AppendDefines(ppDefs, targetDefines); buildSettings->AddAttribute ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); @@ -1847,7 +1874,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { extraLinkOptionsVar = "CMAKE_MODULE_LINKER_FLAGS"; } - if(extraLinkOptionsVar.size()) + if(!extraLinkOptionsVar.empty()) { this->CurrentLocalGenerator ->AddConfigVariableFlags(extraLinkOptions, @@ -1916,11 +1943,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string pnprefix; std::string pnbase; std::string pnsuffix; - target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); + gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); const char* version = target.GetProperty("VERSION"); const char* soversion = target.GetProperty("SOVERSION"); - if(!target.HasSOName(configName) || target.IsFrameworkOnApple()) + if(!gtgt->HasSOName(configName) || target.IsFrameworkOnApple()) { version = 0; soversion = 0; @@ -2178,7 +2205,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, } } // Add framework search paths needed for linking. - if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName)) + if(cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) { std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths(); for(std::vector<std::string>::const_iterator fdi = fwDirs.begin(); @@ -2307,7 +2334,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, if(target.GetType() == cmTarget::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = target.GetInstallNameDirForBuildTree(configName); + install_name_dir = gtgt->GetInstallNameDirForBuildTree(configName); // Xcode doesn't create the correct install_name in some cases. // That is, if the INSTALL_PATH is empty, or if we have versioning // of dylib libraries, we want to specify the install_name. @@ -2321,7 +2348,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, install_name += install_name_dir; install_name += "/"; } - install_name += target.GetSOName(configName); + install_name += gtgt->GetSOName(configName); if((realName != soName) || install_name_dir.empty()) { @@ -2334,7 +2361,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->CreateString(install_name_dir.c_str())); // Create the LD_RUNPATH_SEARCH_PATHS - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName); if(pcli) { std::string search_paths; @@ -2530,7 +2557,8 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget) if(cmtarget.GetType() == cmTarget::UTILITY) { std::vector<cmSourceFile*> sources; - if (!cmtarget.GetConfigCommonSourceFiles(sources)) + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget); + if (!gtgt->GetConfigCommonSourceFiles(sources)) { return 0; } @@ -2587,7 +2615,7 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, config->SetComment(configVector[i].c_str()); config->AddAttribute("buildSettings", buildSettings); } - if(configVector.size()) + if(!configVector.empty()) { configlist->AddAttribute("defaultConfigurationName", this->CreateString(configVector[0].c_str())); @@ -2718,7 +2746,8 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget, } else { - fullName = cmtarget.GetFullName(defConfig.c_str()); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&cmtarget); + fullName = gtgt->GetFullName(defConfig.c_str()); } fileRef->AddAttribute("path", this->CreateString(fullName.c_str())); fileRef->AddAttribute("refType", this->CreateString("0")); @@ -2895,10 +2924,11 @@ void cmGlobalXCodeGenerator } // Add dependencies on other CMake targets. - TargetDependSet const& deps = this->GetTargetDirectDepends(*cmtarget); + cmGeneratorTarget* gt = this->GetGeneratorTarget(cmtarget); + TargetDependSet const& deps = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator i = deps.begin(); i != deps.end(); ++i) { - if(cmXCodeObject* dptarget = this->FindXCodeTarget(*i)) + if(cmXCodeObject* dptarget = this->FindXCodeTarget((*i)->Target)) { this->AddDependTarget(target, dptarget); } @@ -2939,7 +2969,8 @@ void cmGlobalXCodeGenerator } // Compute the link library and directory information. - cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName); + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(cmtarget); + cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName); if(!pcli) { continue; @@ -3055,7 +3086,8 @@ bool cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, } std::vector<cmSourceFile*> classes; - if (!cmtarget.GetConfigCommonSourceFiles(classes)) + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget); + if (!gtgt->GetConfigCommonSourceFiles(classes)) { return false; } @@ -3593,6 +3625,7 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( { cmXCodeObject* target = *i; cmTarget* t =target->GetTarget(); + cmGeneratorTarget *gt = this->GetGeneratorTarget(t); if(t->GetType() == cmTarget::EXECUTABLE || // Nope - no post-build for OBJECT_LIRBRARY @@ -3610,7 +3643,7 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( t->GetType() == cmTarget::SHARED_LIBRARY || t->GetType() == cmTarget::MODULE_LIBRARY) { - std::string tfull = t->GetFullPath(configName); + std::string tfull = gt->GetFullPath(configName); std::string trel = this->ConvertToRelativeForMake(tfull.c_str()); // Add this target to the post-build phases of its dependencies. @@ -3661,7 +3694,7 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::string universalFile = universal; universalFile += *arch; universalFile += "/"; - universalFile += t->GetFullName(configName); + universalFile += gt->GetFullName(configName); makefileStream << "\t/bin/rm -f " << this->ConvertToRelativeForMake(universalFile.c_str()) @@ -3804,33 +3837,13 @@ void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry) //---------------------------------------------------------------------------- std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p) { - if ( !this->CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") ) - { - return cmSystemTools::ConvertToOutputPath(p); - } - else - { - std::string ret = - this->CurrentLocalGenerator-> - ConvertToRelativePath(this->CurrentOutputDirectoryComponents, p); - return cmSystemTools::ConvertToOutputPath(ret.c_str()); - } + return cmSystemTools::ConvertToOutputPath(p); } //---------------------------------------------------------------------------- std::string cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p) { - if ( !this->CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") ) - { - return cmSystemTools::ConvertToOutputPath(p); - } - else - { - std::string ret = - this->CurrentLocalGenerator-> - ConvertToRelativePath(this->ProjectOutputDirectoryComponents, p); - return cmSystemTools::ConvertToOutputPath(ret.c_str()); - } + return cmSystemTools::ConvertToOutputPath(p); } //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index c36e4af..102c036 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -41,8 +41,7 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, - cmState::Snapshot snapshot); + virtual cmLocalGenerator *CreateLocalGenerator(cmMakefile *mf); /** * Try to determine system information such as shared library @@ -88,6 +87,7 @@ public: virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); void AppendFlag(std::string& flags, std::string const& flag); protected: + virtual bool Compute(); virtual void Generate(); private: cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget, diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 7f4c4c9..2023697 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -48,6 +48,7 @@ cmGraphVizWriter::cmGraphVizWriter(const std::vector<cmLocalGenerator*>& ,GraphName("GG") ,GraphHeader("node [\n fontsize = \"12\"\n];") ,GraphNodePrefix("node") +,LocalGenerators(localGenerators) ,GenerateForExecutables(true) ,GenerateForStaticLibs(true) ,GenerateForSharedLibs(true) @@ -55,7 +56,6 @@ cmGraphVizWriter::cmGraphVizWriter(const std::vector<cmLocalGenerator*>& ,GenerateForExternals(true) ,GeneratePerTarget(true) ,GenerateDependers(true) -,LocalGenerators(localGenerators) ,HaveTargetsAndLibs(false) { } @@ -68,8 +68,9 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmGlobalGenerator ggi(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(ggi.MakeLocalGenerator()); - cmMakefile *mf = lg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> mf( + new cmMakefile(&ggi, cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator(mf.get())); const char* inFileName = settingsFileName; diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index a7acd0e..64de684 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -69,14 +69,6 @@ protected: std::string GraphHeader; std::string GraphNodePrefix; - bool GenerateForExecutables; - bool GenerateForStaticLibs; - bool GenerateForSharedLibs; - bool GenerateForModuleLibs; - bool GenerateForExternals; - bool GeneratePerTarget; - bool GenerateDependers; - std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex; const std::vector<cmLocalGenerator*>& LocalGenerators; @@ -85,6 +77,13 @@ protected: // maps from the actual target names to node names in dot: std::map<std::string, std::string> TargetNamesNodes; + bool GenerateForExecutables; + bool GenerateForStaticLibs; + bool GenerateForSharedLibs; + bool GenerateForModuleLibs; + bool GenerateForExternals; + bool GeneratePerTarget; + bool GenerateDependers; bool HaveTargetsAndLibs; }; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 3551f83..20448c1 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -27,7 +27,7 @@ static std::string cmIfCommandError( i != args.end(); ++i) { err += " "; - err += cmLocalGenerator::EscapeForCMake(i->GetValue()); + err += cmOutputConverter::EscapeForCMake(i->GetValue()); } err += "\n"; return err; @@ -92,10 +92,6 @@ IsFunctionBlocked(const cmListFileFunction& lff, } else { - // Place this call on the call stack. - cmMakefileCall stack_manager(&mf, this->Functions[c], status); - static_cast<void>(stack_manager); - // if trace is enabled, print the evaluated "elseif" statement if(mf.GetCMakeInstance()->GetTrace()) { @@ -119,7 +115,8 @@ IsFunctionBlocked(const cmListFileFunction& lff, { std::string err = cmIfCommandError(expandedArguments); err += errorString; - mf.IssueMessage(messType, err); + cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]); + mf.GetCMakeInstance()->IssueMessage(messType, err, bt); if (messType == cmake::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index b94ad25..8890e2b 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -125,6 +125,7 @@ bool cmIncludeCommand return false; } } + gg->CreateGenerationObjects(); gg->GenerateImportFile(fname_abs); } diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 899b088..333c2ff 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -27,7 +27,8 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target, { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(target.GetMakefile()); - return new cmInstallTargetGenerator(target, args.GetDestination().c_str(), + return new cmInstallTargetGenerator(target.GetName(), + args.GetDestination().c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), args.GetComponent().c_str(), message, @@ -41,7 +42,7 @@ static cmInstallFilesGenerator* CreateInstallFilesGenerator( { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(mf); - return new cmInstallFilesGenerator(mf, + return new cmInstallFilesGenerator( absFiles, args.GetDestination().c_str(), programs, args.GetPermissions().c_str(), args.GetConfigurations(), args.GetComponent().c_str(), @@ -752,6 +753,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) installsPublicHeader = installsPublicHeader || publicHeaderGenerator != 0; installsResource = installsResource || resourceGenerator; + if (installsArchive || installsRuntime || installsFramework + || installsLibrary || installsBundle) + { + target.SetHaveInstallRule(true); + } + this->Makefile->AddInstallGenerator(archiveGenerator); this->Makefile->AddInstallGenerator(libraryGenerator); this->Makefile->AddInstallGenerator(runtimeGenerator); @@ -1399,7 +1406,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) ica.GetDestination().c_str(), ica.GetPermissions().c_str(), ica.GetConfigurations(), ica.GetComponent().c_str(), message, fname.c_str(), - name_space.GetCString(), exportOld.IsEnabled(), this->Makefile); + name_space.GetCString(), exportOld.IsEnabled()); this->Makefile->AddInstallGenerator(exportGenerator); return true; diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 7f6aa4d..97b9405 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -34,15 +34,14 @@ cmInstallExportGenerator::cmInstallExportGenerator( const char* component, MessageLevel message, const char* filename, const char* name_space, - bool exportOld, - cmMakefile* mf) + bool exportOld) :cmInstallGenerator(destination, configurations, component, message) ,ExportSet(exportSet) ,FilePermissions(file_permissions) ,FileName(filename) ,Namespace(name_space) ,ExportOld(exportOld) - ,Makefile(mf) + ,LocalGenerator(0) { this->EFGen = new cmExportInstallFileGenerator(this); exportSet->AddInstallation(this); @@ -54,12 +53,18 @@ cmInstallExportGenerator::~cmInstallExportGenerator() delete this->EFGen; } +void cmInstallExportGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; +} + //---------------------------------------------------------------------------- void cmInstallExportGenerator::ComputeTempDir() { // Choose a temporary directory in which to generate the import // files to be installed. - this->TempDir = this->Makefile->GetCurrentBinaryDirectory(); + this->TempDir = + this->LocalGenerator->GetMakefile()->GetCurrentBinaryDirectory(); this->TempDir += cmake::GetCMakeFilesDirectory(); this->TempDir += "/Export"; if(this->Destination.empty()) diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 3e078f2..885ed05 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -32,12 +32,14 @@ public: const char* component, MessageLevel message, const char* filename, const char* name_space, - bool exportOld, cmMakefile* mf); + bool exportOld); ~cmInstallExportGenerator(); cmExportSet* GetExportSet() {return this->ExportSet;} - cmMakefile* GetMakefile() const { return this->Makefile; } + void Compute(cmLocalGenerator* lg); + + cmLocalGenerator* GetLocalGenerator() const { return this->LocalGenerator; } const std::string& GetNamespace() const { return this->Namespace; } @@ -57,7 +59,7 @@ protected: std::string FileName; std::string Namespace; bool ExportOld; - cmMakefile* Makefile; + cmLocalGenerator* LocalGenerator; std::string TempDir; std::string MainImportFile; diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index 508c373..68557bd 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -128,7 +128,7 @@ void cmInstallFilesCommand::CreateInstallGenerator() const cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(this->Makefile); this->Makefile->AddInstallGenerator( - new cmInstallFilesGenerator(this->Makefile, this->Files, + new cmInstallFilesGenerator(this->Files, destination.c_str(), false, no_permissions, no_configurations, no_component.c_str(), message, no_rename)); diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 28c27c2..c18b174 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -14,11 +14,11 @@ #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmLocalGenerator.h" //---------------------------------------------------------------------------- cmInstallFilesGenerator -::cmInstallFilesGenerator(cmMakefile* mf, - std::vector<std::string> const& files, +::cmInstallFilesGenerator(std::vector<std::string> const& files, const char* dest, bool programs, const char* file_permissions, std::vector<std::string> const& configurations, @@ -27,10 +27,12 @@ cmInstallFilesGenerator const char* rename, bool optional): cmInstallGenerator(dest, configurations, component, message), - Makefile(mf), - Files(files), Programs(programs), + LocalGenerator(0), + Files(files), FilePermissions(file_permissions), - Rename(rename), Optional(optional) + Rename(rename), + Programs(programs), + Optional(optional) { // We need per-config actions if any files have generator expressions. for(std::vector<std::string>::const_iterator i = files.begin(); @@ -49,6 +51,11 @@ cmInstallFilesGenerator { } +void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; +} + //---------------------------------------------------------------------------- void cmInstallFilesGenerator::AddFilesInstallRule( std::ostream& os, Indent const& indent, @@ -92,8 +99,8 @@ void cmInstallFilesGenerator::GenerateScriptForConfig(std::ostream& os, i != this->Files.end(); ++i) { cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*i); - cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile, config), - files); + cmSystemTools::ExpandListArgument(cge->Evaluate( + this->LocalGenerator->GetMakefile(), config), files); } this->AddFilesInstallRule(os, indent, files); } diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 0dbd712..00b3a79 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -14,16 +14,13 @@ #include "cmInstallGenerator.h" -class cmMakefile; - /** \class cmInstallFilesGenerator * \brief Generate file installation rules. */ class cmInstallFilesGenerator: public cmInstallGenerator { public: - cmInstallFilesGenerator(cmMakefile* mf, - std::vector<std::string> const& files, + cmInstallFilesGenerator(std::vector<std::string> const& files, const char* dest, bool programs, const char* file_permissions, std::vector<std::string> const& configurations, @@ -33,6 +30,8 @@ public: bool optional = false); virtual ~cmInstallFilesGenerator(); + void Compute(cmLocalGenerator* lg); + protected: virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); virtual void GenerateScriptForConfig(std::ostream& os, @@ -41,11 +40,11 @@ protected: void AddFilesInstallRule(std::ostream& os, Indent const& indent, std::vector<std::string> const& files); - cmMakefile* Makefile; + cmLocalGenerator* LocalGenerator; std::vector<std::string> Files; - bool Programs; std::string FilePermissions; std::string Rename; + bool Programs; bool Optional; }; diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index c4191e4..b8e5b53 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -62,6 +62,8 @@ public: /** Select message level from CMAKE_INSTALL_MESSAGE or 'never'. */ static MessageLevel SelectMessageLevel(cmMakefile* mf, bool never = false); + virtual void Compute(cmLocalGenerator*) {} + protected: virtual void GenerateScript(std::ostream& os); diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index be8096c..e6fbe88 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -91,7 +91,7 @@ void cmInstallProgramsCommand::FinalPass() cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(this->Makefile); this->Makefile->AddInstallGenerator( - new cmInstallFilesGenerator(this->Makefile, this->Files, + new cmInstallFilesGenerator(this->Files, destination.c_str(), true, no_permissions, no_configurations, no_component.c_str(), message, no_rename)); diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 082a78c..30cf175 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -16,24 +16,30 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmGeneratorTarget.h" #include "cmake.h" +#include "cmGeneratorTarget.h" #include <assert.h> //---------------------------------------------------------------------------- cmInstallTargetGenerator -::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib, +::cmInstallTargetGenerator(const std::string& targetName, + const char* dest, bool implib, const char* file_permissions, std::vector<std::string> const& configurations, const char* component, MessageLevel message, bool optional): - cmInstallGenerator(dest, configurations, component, message), Target(&t), - ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional) + cmInstallGenerator(dest, configurations, component, message), + TargetName(targetName), + Target(0), + FilePermissions(file_permissions), + ImportLibrary(implib), + Optional(optional) { this->ActionsPerConfig = true; this->NamelinkMode = NamelinkModeNone; - this->Target->SetHaveInstallRule(true); } //---------------------------------------------------------------------------- @@ -69,13 +75,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, std::string fromDirConfig; if(this->Target->NeedRelinkBeforeInstall(config)) { - fromDirConfig = this->Target->GetMakefile()->GetCurrentBinaryDirectory(); + fromDirConfig = + this->Target->Target->GetMakefile()->GetCurrentBinaryDirectory(); fromDirConfig += cmake::GetCMakeFilesDirectory(); fromDirConfig += "/CMakeRelink.dir/"; } else { - fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary); + fromDirConfig = + this->Target->Target->GetDirectory(config, this->ImportLibrary); fromDirConfig += "/"; } std::string toDir = @@ -86,7 +94,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, std::vector<std::string> filesFrom; std::vector<std::string> filesTo; std::string literal_args; - cmTarget::TargetType targetType = this->Target->GetType(); + cmTarget::TargetType targetType = + static_cast<cmTarget::TargetType>(this->Target->GetType()); cmInstallType type = cmInstallType(); switch(targetType) { @@ -103,7 +112,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, case cmTarget::UTILITY: case cmTarget::GLOBAL_TARGET: case cmTarget::UNKNOWN_LIBRARY: - this->Target->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, + this->Target->Target->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, "cmInstallTargetGenerator created with non-installable target."); return; } @@ -126,7 +135,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, filesFrom.push_back(from1); filesTo.push_back(to1); std::string targetNameImportLib; - if(this->Target->GetImplibGNUtoMS(targetNameImport, + if(this->Target->Target->GetImplibGNUtoMS(targetNameImport, targetNameImportLib)) { filesFrom.push_back(fromDirConfig + targetNameImportLib); @@ -142,7 +151,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, std::string to1 = toDir + targetName; // Handle OSX Bundles. - if(this->Target->IsAppBundleOnApple()) + if(this->Target->Target->IsAppBundleOnApple()) { // Install the whole app bundle directory. type = cmInstallType_DIRECTORY; @@ -176,7 +185,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal, + this->Target->GetLibraryNames(targetName, targetNameSO, + targetNameReal, targetNameImport, targetNamePDB, config); if(this->ImportLibrary) @@ -189,7 +199,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, filesFrom.push_back(from1); filesTo.push_back(to1); std::string targetNameImportLib; - if(this->Target->GetImplibGNUtoMS(targetNameImport, + if(this->Target->Target->GetImplibGNUtoMS(targetNameImport, targetNameImportLib)) { filesFrom.push_back(fromDirConfig + targetNameImportLib); @@ -199,7 +209,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, // An import library looks like a static library. type = cmInstallType_STATIC_LIBRARY; } - else if(this->Target->IsFrameworkOnApple()) + else if(this->Target->Target->IsFrameworkOnApple()) { // There is a bug in cmInstallCommand if this fails. assert(this->NamelinkMode == NamelinkModeNone); @@ -217,7 +227,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, filesFrom.push_back(from1); filesTo.push_back(to1); } - else if(this->Target->IsCFBundleOnApple()) + else if(this->Target->Target->IsCFBundleOnApple()) { // Install the whole app bundle directory. type = cmInstallType_DIRECTORY; @@ -341,7 +351,7 @@ cmInstallTargetGenerator::GetDestination(std::string const& config) const { cmGeneratorExpression ge; return ge.Parse(this->Destination) - ->Evaluate(this->Target->GetMakefile(), config); + ->Evaluate(this->Target->Target->GetMakefile(), config); } //---------------------------------------------------------------------------- @@ -350,7 +360,7 @@ cmInstallTargetGenerator::GetInstallFilename(const std::string& config) const { NameType nameType = this->ImportLibrary? NameImplib : NameNormal; return - cmInstallTargetGenerator::GetInstallFilename(this->Target, config, + cmInstallTargetGenerator::GetInstallFilename(this->Target->Target, config, nameType); } @@ -362,13 +372,16 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target, { std::string fname; // Compute the name of the library. + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); if(target->GetType() == cmTarget::EXECUTABLE) { std::string targetName; std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - target->GetExecutableNames(targetName, targetNameReal, + gtgt->GetExecutableNames(targetName, targetNameReal, targetNameImport, targetNamePDB, config); if(nameType == NameImplib) @@ -398,7 +411,7 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target, std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - target->GetLibraryNames(targetName, targetNameSO, targetNameReal, + gtgt->GetLibraryNames(targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB, config); if(nameType == NameImplib) { @@ -429,6 +442,12 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target, return fname; } +void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg) +{ + this->Target = lg->GetGlobalGenerator()->GetGeneratorTarget( + lg->GetMakefile()->FindTarget(this->TargetName)); +} + //---------------------------------------------------------------------------- void cmInstallTargetGenerator @@ -531,8 +550,8 @@ cmInstallTargetGenerator } // Fix the install_name settings in installed binaries. - std::string installNameTool = - this->Target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); + std::string installNameTool = this->Target->Target->GetMakefile() + ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); if(installNameTool.empty()) { @@ -557,11 +576,14 @@ cmInstallTargetGenerator continue; } + cmGeneratorTarget *gtgt = tgt->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(tgt); // If the build tree and install tree use different path // components of the install_name field then we need to create a // mapping to be applied after installation. - std::string for_build = tgt->GetInstallNameDirForBuildTree(config); - std::string for_install = tgt->GetInstallNameDirForInstallTree(); + std::string for_build = gtgt->GetInstallNameDirForBuildTree(config); + std::string for_install = gtgt->GetInstallNameDirForInstallTree(); if(for_build != for_install) { // The directory portions differ. Append the filename to @@ -590,7 +612,7 @@ cmInstallTargetGenerator std::string for_install = this->Target->GetInstallNameDirForInstallTree(); - if(this->Target->IsFrameworkOnApple() && for_install.empty()) + if(this->Target->Target->IsFrameworkOnApple() && for_install.empty()) { // Frameworks seem to have an id corresponding to their own full // path. @@ -604,7 +626,7 @@ cmInstallTargetGenerator { // Prepare to refer to the install-tree install_name. new_id = for_install; - new_id += this->GetInstallFilename(this->Target, config, NameSO); + new_id += this->GetInstallFilename(this->Target->Target, config, NameSO); } } @@ -641,9 +663,9 @@ cmInstallTargetGenerator { return; } - // Skip if on Apple - if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + if(this->Target->Target->GetMakefile() + ->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { return; } @@ -688,7 +710,7 @@ cmInstallTargetGenerator return; } - cmMakefile* mf = this->Target->GetMakefile(); + cmMakefile* mf = this->Target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { @@ -800,20 +822,20 @@ cmInstallTargetGenerator::AddStripRule(std::ostream& os, } // Don't handle OSX Bundles. - if(this->Target->GetMakefile()->IsOn("APPLE") && - this->Target->GetPropertyAsBool("MACOSX_BUNDLE")) + if(this->Target->Target->GetMakefile()->IsOn("APPLE") && + this->Target->Target->GetPropertyAsBool("MACOSX_BUNDLE")) { return; } - if(! this->Target->GetMakefile()->IsSet("CMAKE_STRIP")) + if(! this->Target->Target->GetMakefile()->IsSet("CMAKE_STRIP")) { return; } os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n"; os << indent << " execute_process(COMMAND \"" - << this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP") + << this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP") << "\" \"" << toDestDirPath << "\")\n"; os << indent << "endif()\n"; } @@ -832,13 +854,13 @@ cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, // Perform post-installation processing on the file depending // on its type. - if(!this->Target->GetMakefile()->IsOn("APPLE")) + if(!this->Target->Target->GetMakefile()->IsOn("APPLE")) { return; } std::string ranlib = - this->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB"); + this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB"); if(ranlib.empty()) { return; diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 075c8a4..a8f4a75 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -13,8 +13,9 @@ #define cmInstallTargetGenerator_h #include "cmInstallGenerator.h" -#include "cmTarget.h" -#include "cmGeneratorTarget.h" + +class cmTarget; +class cmGeneratorTarget; /** \class cmInstallTargetGenerator * \brief Generate target installation rules. @@ -23,7 +24,7 @@ class cmInstallTargetGenerator: public cmInstallGenerator { public: cmInstallTargetGenerator( - cmTarget& t, const char* dest, bool implib, + std::string const& targetName, const char* dest, bool implib, const char* file_permissions, std::vector<std::string> const& configurations, const char* component, @@ -57,7 +58,10 @@ public: const std::string& config, NameType nameType = NameNormal); - cmTarget* GetTarget() const { return this->Target; } + void Compute(cmLocalGenerator* lg); + + cmGeneratorTarget* GetTarget() const { return this->Target; } + bool IsImportLibrary() const { return this->ImportLibrary; } std::string GetDestination(std::string const& config) const; @@ -99,12 +103,12 @@ protected: void AddRanlibRule(std::ostream& os, Indent const& indent, const std::string& toDestDirPath); - cmTarget* Target; - bool ImportLibrary; + std::string TargetName; + cmGeneratorTarget* Target; std::string FilePermissions; - bool Optional; NamelinkModeType NamelinkMode; - cmGeneratorTarget* GeneratorTarget; + bool ImportLibrary; + bool Optional; }; #endif diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 8c52b48..fa5e815 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -44,7 +44,7 @@ cmInstalledFile::Property::~Property() void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name) { cmListFileBacktrace backtrace = mf->GetBacktrace(); - cmGeneratorExpression ge(&backtrace); + cmGeneratorExpression ge(backtrace); this->Name = name; this->NameExpression = ge.Parse(name).release(); @@ -81,7 +81,7 @@ void cmInstalledFile::AppendProperty(cmMakefile const* mf, const std::string& prop, const char* value, bool /*asString*/) { cmListFileBacktrace backtrace = mf->GetBacktrace(); - cmGeneratorExpression ge(&backtrace); + cmGeneratorExpression ge(backtrace); Property& property = this->Properties[prop]; property.ValueExpressions.push_back(ge.Parse(value).release()); diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index f486bf7..b6c0072 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -65,5 +65,5 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir) unixPath = tmp; } } - this->Makefile->AddLinkDirectory(unixPath); + this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str()); } diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h new file mode 100644 index 0000000..10dd465 --- /dev/null +++ b/Source/cmLinkItem.h @@ -0,0 +1,121 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2004-2015 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmLinkItem_h +#define cmLinkItem_h + +#include "cmListFileCache.h" + +class cmTarget; + +// Basic information about each link item. +class cmLinkItem: public std::string +{ + typedef std::string std_string; +public: + cmLinkItem(): std_string(), Target(0) {} + cmLinkItem(const std_string& n, + cmTarget const* t): std_string(n), Target(t) {} + cmLinkItem(cmLinkItem const& r): std_string(r), Target(r.Target) {} + cmTarget const* Target; +}; + +class cmLinkImplItem: public cmLinkItem +{ +public: + cmLinkImplItem(): cmLinkItem(), Backtrace(), FromGenex(false) {} + cmLinkImplItem(std::string const& n, + cmTarget const* t, + cmListFileBacktrace const& bt, + bool fromGenex): + cmLinkItem(n, t), Backtrace(bt), FromGenex(fromGenex) {} + cmLinkImplItem(cmLinkImplItem const& r): + cmLinkItem(r), Backtrace(r.Backtrace), FromGenex(r.FromGenex) {} + cmListFileBacktrace Backtrace; + bool FromGenex; +}; + +/** The link implementation specifies the direct library + dependencies needed by the object files of the target. */ +struct cmLinkImplementationLibraries +{ + // Libraries linked directly in this configuration. + std::vector<cmLinkImplItem> Libraries; + + // Libraries linked directly in other configurations. + // Needed only for OLD behavior of CMP0003. + std::vector<cmLinkItem> WrongConfigLibraries; +}; + +struct cmLinkInterfaceLibraries +{ + // Libraries listed in the interface. + std::vector<cmLinkItem> Libraries; +}; + +struct cmLinkInterface: public cmLinkInterfaceLibraries +{ + // Languages whose runtime libraries must be linked. + std::vector<std::string> Languages; + + // Shared library dependencies needed for linking on some platforms. + std::vector<cmLinkItem> SharedDeps; + + // Number of repetitions of a strongly connected component of two + // or more static libraries. + int Multiplicity; + + // Libraries listed for other configurations. + // Needed only for OLD behavior of CMP0003. + std::vector<cmLinkItem> WrongConfigLibraries; + + bool ImplementationIsInterface; + + cmLinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {} +}; + +struct cmOptionalLinkInterface: public cmLinkInterface +{ + cmOptionalLinkInterface(): + LibrariesDone(false), AllDone(false), + Exists(false), HadHeadSensitiveCondition(false), + ExplicitLibraries(0) {} + bool LibrariesDone; + bool AllDone; + bool Exists; + bool HadHeadSensitiveCondition; + const char* ExplicitLibraries; +}; + +struct cmHeadToLinkInterfaceMap: + public std::map<cmTarget const*, cmOptionalLinkInterface> +{ +}; + +struct cmLinkImplementation: public cmLinkImplementationLibraries +{ + // Languages whose runtime libraries must be linked. + std::vector<std::string> Languages; +}; + +// Cache link implementation computation from each configuration. +struct cmOptionalLinkImplementation: public cmLinkImplementation +{ + cmOptionalLinkImplementation(): + LibrariesDone(false), LanguagesDone(false), + HadHeadSensitiveCondition(false) {} + bool LibrariesDone; + bool LanguagesDone; + bool HadHeadSensitiveCondition; +}; + +#endif diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h new file mode 100644 index 0000000..721a246 --- /dev/null +++ b/Source/cmLinkedTree.h @@ -0,0 +1,195 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmLinkedTree_h +#define cmLinkedTree_h + +#include "cmStandardIncludes.h" + +#include <assert.h> + +/** + @brief A adaptor for traversing a tree structure in a vector + + This class is not intended to be wholly generic like a standard library + container adaptor. Mostly it exists to facilitate code sharing for the + needs of the cmState. For example, the Truncate() method is a specific + requirement of the cmState. + + An empty cmLinkedTree provides a Root() method, and an Extend() method, + each of which return iterators. A Tree can be built up by extending + from the root, and then extending from any other iterator. + + An iterator resulting from this tree construction can be + forward-only-iterated toward the root. Extending the tree never + invalidates existing iterators. + */ +template<typename T> +class cmLinkedTree +{ + typedef typename std::vector<T>::size_type PositionType; + typedef T* PointerType; + typedef T& ReferenceType; +public: + class iterator : public std::iterator<std::forward_iterator_tag, T> + { + friend class cmLinkedTree; + cmLinkedTree* Tree; + + // The Position is always 'one past the end'. + PositionType Position; + + iterator(cmLinkedTree* tree, PositionType pos) + : Tree(tree), Position(pos) + { + + } + + public: + iterator() + : Tree(0), Position(0) + { + + } + + void operator++() + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + this->Position = this->Tree->UpPositions[this->Position - 1]; + } + + PointerType operator->() const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetPointer(this->Position - 1); + } + + PointerType operator->() + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetPointer(this->Position - 1); + } + + ReferenceType operator*() const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetReference(this->Position - 1); + } + + ReferenceType operator*() + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetReference(this->Position - 1); + } + + bool operator==(iterator other) const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Tree == other.Tree); + return this->Position == other.Position; + } + + bool operator!=(iterator other) const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + return !(*this == other); + } + + bool IsValid() const + { + if (!this->Tree) + { + return false; + } + return this->Position <= this->Tree->Data.size(); + } + + bool StrictWeakOrdered(iterator other) const + { + assert(this->Tree); + assert(this->Tree == other.Tree); + return this->Position < other.Position; + } + }; + + iterator Root() const + { + return iterator(const_cast<cmLinkedTree*>(this), 0); + } + + iterator Extend(iterator it) + { + return Extend_impl(it, T()); + } + + iterator Extend(iterator it, T t) + { + return Extend_impl(it, t); + } + + iterator Truncate() + { + assert(this->UpPositions.size() > 0); + this->UpPositions.erase(this->UpPositions.begin() + 1, + this->UpPositions.end()); + assert(this->Data.size() > 0); + this->Data.erase(this->Data.begin() + 1, this->Data.end()); + return iterator(this, 1); + } + + void Clear() + { + this->UpPositions.clear(); + this->Data.clear(); + } + +private: + T& GetReference(PositionType pos) + { + return this->Data[pos]; + } + + T* GetPointer(PositionType pos) + { + return &this->Data[pos]; + } + + iterator Extend_impl(iterator it, T t) + { + assert(this->UpPositions.size() == this->Data.size()); + assert(it.Position <= this->UpPositions.size()); + this->UpPositions.push_back(it.Position); + this->Data.push_back(t); + return iterator(this, this->UpPositions.size()); + } + + std::vector<T> Data; + std::vector<PositionType> UpPositions; +}; + +#endif diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index f96b4a8..6041fb7 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -247,7 +247,7 @@ bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args) { listString += ";"; } - listString += cmJoin(cmRange(args).advance(2), ";"); + listString += cmJoin(cmMakeRange(args).advance(2), ";"); this->Makefile->AddDefinition(listName, listString.c_str()); return true; @@ -361,9 +361,9 @@ bool cmListCommand std::vector<std::string>::const_iterator remBegin = remove.begin(); std::vector<std::string>::const_iterator argsEnd = - cmRemoveMatching(varArgsExpanded, cmRange(remBegin, remEnd)); + cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd)); std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin(); - std::string value = cmJoin(cmRange(argsBegin, argsEnd), ";"); + std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";"); this->Makefile->AddDefinition(listName, value.c_str()); return true; } @@ -421,7 +421,7 @@ bool cmListCommand cmRemoveDuplicates(varArgsExpanded); std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin(); - std::string value = cmJoin(cmRange(argsBegin, argsEnd), ";"); + std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";"); this->Makefile->AddDefinition(listName, value.c_str()); return true; @@ -509,9 +509,9 @@ bool cmListCommand::HandleRemoveAtCommand( std::vector<size_t>::const_iterator remBegin = removed.begin(); std::vector<std::string>::const_iterator argsEnd = - cmRemoveIndices(varArgsExpanded, cmRange(remBegin, remEnd)); + cmRemoveIndices(varArgsExpanded, cmMakeRange(remBegin, remEnd)); std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin(); - std::string value = cmJoin(cmRange(argsBegin, argsEnd), ";"); + std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";"); this->Makefile->AddDefinition(listName, value.c_str()); return true; diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 2756cd2..bff2986 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -234,8 +234,7 @@ bool cmListFile::ParseFile(const char* filename, { cmListFileFunction project; project.Name = "PROJECT"; - cmListFileArgument prj("Project", cmListFileArgument::Unquoted, - filename, 0); + cmListFileArgument prj("Project", cmListFileArgument::Unquoted, 0); project.Arguments.push_back(prj); this->Functions.insert(this->Functions.begin(),project); } @@ -252,7 +251,6 @@ bool cmListFileParser::ParseFunction(const char* name, long line) { // Inintialize a new function call. this->Function = cmListFileFunction(); - this->Function.FilePath = this->FileName; this->Function.Name = name; this->Function.Line = line; @@ -375,7 +373,7 @@ bool cmListFileParser::ParseFunction(const char* name, long line) bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, cmListFileArgument::Delimiter delim) { - cmListFileArgument a(token->text, delim, this->FileName, token->line); + cmListFileArgument a(token->text, delim, token->line); this->Function.Arguments.push_back(a); if(this->Separation == SeparationOkay) { @@ -400,50 +398,50 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, } } -void cmListFileBacktrace::Append(cmListFileContext const& context) +void cmListFileBacktrace::PrintTitle(std::ostream& out) const { - this->push_back(context); -} - -//---------------------------------------------------------------------------- -void cmListFileBacktrace::MakeRelative() -{ - if (this->Relative) + if (!this->Snapshot.IsValid()) { return; } - for (cmListFileBacktrace::iterator i = this->begin(); - i != this->end(); ++i) - { - i->FilePath = this->LocalGenerator->Convert(i->FilePath, - cmLocalGenerator::HOME); - } - this->Relative = true; + cmOutputConverter converter(this->Snapshot); + cmListFileContext lfc = + cmListFileContext::FromCommandContext( + this->Context, this->Snapshot.GetExecutionListFile()); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); + out << (lfc.Line ? " at " : " in ") << lfc; } -void cmListFileBacktrace::PrintTitle(std::ostream& out) +void cmListFileBacktrace::PrintCallStack(std::ostream& out) const { - if (this->empty()) + if (!this->Snapshot.IsValid()) { return; } - out << (this->front().Line ? " at " : " in ") << this->front(); -} - -void cmListFileBacktrace::PrintCallStack(std::ostream& out) -{ - if (size() <= 1) + cmState::Snapshot parent = this->Snapshot.GetCallStackParent(); + if (!parent.IsValid() || parent.GetExecutionListFile().empty()) { return; } - const_iterator i = this->begin() + 1; + cmOutputConverter converter(this->Snapshot); + std::string commandName = this->Snapshot.GetEntryPointCommand(); + long commandLine = this->Snapshot.GetEntryPointLine(); + out << "Call Stack (most recent call first):\n"; - while(i != this->end()) + while(parent.IsValid()) { - cmListFileContext const& lfc = *i; + cmListFileContext lfc; + lfc.Name = commandName; + lfc.Line = commandLine; + + lfc.FilePath = converter.Convert(parent.GetExecutionListFile(), + cmOutputConverter::HOME); out << " " << lfc << "\n"; - ++i; + + commandName = parent.GetEntryPointCommand(); + commandLine = parent.GetEntryPointLine(); + parent = parent.GetCallStackParent(); } } diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 4a1d181..0afd7f5 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -14,7 +14,7 @@ #include "cmStandardIncludes.h" -class cmLocalGenerator; +#include "cmState.h" /** \class cmListFileCache * \brief A class to cache list file contents. @@ -25,6 +25,13 @@ class cmLocalGenerator; class cmMakefile; +struct cmCommandContext +{ + std::string Name; + long Line; + cmCommandContext(): Name(), Line(0) {} +}; + struct cmListFileArgument { enum Delimiter @@ -33,12 +40,11 @@ struct cmListFileArgument Quoted, Bracket }; - cmListFileArgument(): Value(), Delim(Unquoted), FilePath(0), Line(0) {} - cmListFileArgument(const cmListFileArgument& r): - Value(r.Value), Delim(r.Delim), FilePath(r.FilePath), Line(r.Line) {} - cmListFileArgument(const std::string& v, Delimiter d, const char* file, - long line): Value(v), Delim(d), - FilePath(file), Line(line) {} + cmListFileArgument(): Value(), Delim(Unquoted), Line(0) {} + cmListFileArgument(const cmListFileArgument& r) + : Value(r.Value), Delim(r.Delim), Line(r.Line) {} + cmListFileArgument(const std::string& v, Delimiter d, long line) + : Value(v), Delim(d), Line(line) {} bool operator == (const cmListFileArgument& r) const { return (this->Value == r.Value) && (this->Delim == r.Delim); @@ -49,7 +55,6 @@ struct cmListFileArgument } std::string Value; Delimiter Delim; - const char* FilePath; long Line; }; @@ -59,6 +64,16 @@ struct cmListFileContext std::string FilePath; long Line; cmListFileContext(): Name(), FilePath(), Line(0) {} + + static cmListFileContext FromCommandContext(cmCommandContext const& lfcc, + std::string const& fileName) + { + cmListFileContext lfc; + lfc.FilePath = fileName; + lfc.Line = lfcc.Line; + lfc.Name = lfcc.Name; + return lfc; + } }; std::ostream& operator<<(std::ostream&, cmListFileContext const&); @@ -66,29 +81,25 @@ bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs); bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs); bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); -struct cmListFileFunction: public cmListFileContext +struct cmListFileFunction: public cmCommandContext { std::vector<cmListFileArgument> Arguments; }; -class cmListFileBacktrace: private std::vector<cmListFileContext> +class cmListFileBacktrace { public: - cmListFileBacktrace(cmLocalGenerator* localGen) - : LocalGenerator(localGen) - , Relative(localGen ? false : true) + cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot(), + cmCommandContext const& cc = cmCommandContext()) + : Context(cc), Snapshot(snapshot) { } - void Append(cmListFileContext const& context); - - void MakeRelative(); - - void PrintTitle(std::ostream& out); - void PrintCallStack(std::ostream& out); + void PrintTitle(std::ostream& out) const; + void PrintCallStack(std::ostream& out) const; private: - cmLocalGenerator* LocalGenerator; - bool Relative; + cmCommandContext Context; + cmState::Snapshot Snapshot; }; struct cmListFile diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx new file mode 100644 index 0000000..5a18e2f --- /dev/null +++ b/Source/cmLocalCommonGenerator.cxx @@ -0,0 +1,39 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmLocalCommonGenerator.h" + +#include "cmMakefile.h" + +cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, + cmMakefile* mf): + cmLocalGenerator(gg, mf) +{ +} + +cmLocalCommonGenerator::~cmLocalCommonGenerator() +{ +} + +void cmLocalCommonGenerator::SetConfigName() +{ + // Store the configuration name that will be generated. + if(const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) + { + // Use the build type given by the user. + this->ConfigName = config; + } + else + { + // No configuration type given. + this->ConfigName = ""; + } +} diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h new file mode 100644 index 0000000..6b4b1cd --- /dev/null +++ b/Source/cmLocalCommonGenerator.h @@ -0,0 +1,37 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmLocalCommonGenerator_h +#define cmLocalCommonGenerator_h + +#include "cmLocalGenerator.h" + +class cmCommonTargetGenerator; + +/** \class cmLocalCommonGenerator + * \brief Common infrastructure for Makefile and Ninja local generators. + */ +class cmLocalCommonGenerator: public cmLocalGenerator +{ +public: + cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf); + ~cmLocalCommonGenerator(); + + std::string const& GetConfigName() { return this->ConfigName; } + +protected: + void SetConfigName(); + std::string ConfigName; + + friend class cmCommonTargetGenerator; +}; + +#endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index eb6b871..b360c22 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -16,6 +16,7 @@ #include "cmGlobalGenerator.h" #include "cmInstallGenerator.h" #include "cmInstallFilesGenerator.h" +#include "cmGeneratorExpressionEvaluationFile.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmMakefile.h" @@ -32,8 +33,6 @@ # include <cmsys/MD5.h> #endif -#include <cmsys/System.h> - #include <ctype.h> // for isalpha #include <assert.h> @@ -44,23 +43,14 @@ #endif cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot) - : StateSnapshot(snapshot) + cmMakefile* makefile) + : cmOutputConverter(makefile->GetStateSnapshot()), + StateSnapshot(makefile->GetStateSnapshot()) { - assert(snapshot.IsValid()); this->GlobalGenerator = gg; - this->Parent = parent; - if (parent) - { - parent->AddChild(this); - } - this->Makefile = new cmMakefile(this); + this->Makefile = makefile; - this->LinkScriptShell = false; - this->UseRelativePaths = false; - this->Configured = false; this->EmitUniversalBinaryFlags = true; this->BackwardsCompatibility = 0; this->BackwardsCompatibilityFinal = false; @@ -68,82 +58,22 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator::~cmLocalGenerator() { - delete this->Makefile; } -bool cmLocalGenerator::IsRootMakefile() const +void cmLocalGenerator::IssueMessage(cmake::MessageType t, + std::string const& text) const { - return !this->StateSnapshot.GetParent().IsValid(); -} + cmListFileContext lfc; + lfc.FilePath = this->StateSnapshot.GetDirectory().GetCurrentSource(); + lfc.FilePath += "/CMakeLists.txt"; -//---------------------------------------------------------------------------- -class cmLocalGeneratorCurrent -{ - cmGlobalGenerator* GG; - cmLocalGenerator* LG; - cmState::Snapshot Snapshot; -public: - cmLocalGeneratorCurrent(cmLocalGenerator* lg) - { - this->GG = lg->GetGlobalGenerator(); - this->LG = this->GG->GetCurrentLocalGenerator(); - this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot(); - this->GG->GetCMakeInstance()->SetCurrentSnapshot(lg->GetStateSnapshot()); - this->GG->SetCurrentLocalGenerator(lg); -#if defined(CMAKE_BUILD_WITH_CMAKE) - this->GG->GetFileLockPool().PushFileScope(); -#endif - } - ~cmLocalGeneratorCurrent() + if(!this->GlobalGenerator->GetCMakeInstance()->GetIsInTryCompile()) { -#if defined(CMAKE_BUILD_WITH_CMAKE) - this->GG->GetFileLockPool().PopFileScope(); -#endif - this->GG->SetCurrentLocalGenerator(this->LG); - this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot); + cmOutputConverter converter(this->StateSnapshot); + lfc.FilePath = converter.Convert(lfc.FilePath, cmLocalGenerator::HOME); } -}; - -//---------------------------------------------------------------------------- -void cmLocalGenerator::Configure() -{ - // Manage the global generator's current local generator. - cmLocalGeneratorCurrent clg(this); - static_cast<void>(clg); - - // make sure the CMakeFiles dir is there - std::string filesDir = this->StateSnapshot.GetCurrentBinaryDirectory(); - filesDir += cmake::GetCMakeFilesDirectory(); - cmSystemTools::MakeDirectory(filesDir.c_str()); - - std::string currentStart = this->StateSnapshot.GetCurrentSourceDirectory(); - currentStart += "/CMakeLists.txt"; - assert(cmSystemTools::FileExists(currentStart.c_str(), true)); - this->Makefile->ProcessBuildsystemFile(currentStart.c_str()); - - // at the end of the ReadListFile handle any old style subdirs - // first get all the subdirectories - std::vector<cmLocalGenerator *> subdirs = this->GetChildren(); - - // for each subdir recurse - std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin(); - for (; sdi != subdirs.end(); ++sdi) - { - if (!(*sdi)->Configured) - { - this->Makefile->ConfigureSubDirectory(*sdi); - } - } - - this->Makefile->AddCMakeDependFilesFromUser(); - - // Check whether relative paths should be used for optionally - // relative paths. - this->UseRelativePaths = this->Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS"); - - this->ComputeObjectMaxPath(); - - this->Configured = true; + lfc.Line = 0; + this->GlobalGenerator->GetCMakeInstance()->IssueMessage(t, text, lfc); } //---------------------------------------------------------------------------- @@ -171,7 +101,7 @@ void cmLocalGenerator::ComputeObjectMaxPath() w << "CMAKE_OBJECT_PATH_MAX is set to " << pmax << ", which is less than the minimum of 128. " << "The value will be ignored."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } } else @@ -180,17 +110,12 @@ void cmLocalGenerator::ComputeObjectMaxPath() w << "CMAKE_OBJECT_PATH_MAX is set to \"" << plen << "\", which fails to parse as a positive integer. " << "The value will be ignored."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } } this->ObjectMaxPathViolations.clear(); } -void cmLocalGenerator::ConfigureFinalPass() -{ - this->Makefile->ConfigureFinalPass(); -} - void cmLocalGenerator::TraceDependencies() { std::vector<std::string> configs; @@ -230,7 +155,8 @@ void cmLocalGenerator::GenerateTestFiles() const std::string& config = this->Makefile->GetConfigurations(configurationTypes, false); - std::string file = this->StateSnapshot.GetCurrentBinaryDirectory(); + std::string file = + this->StateSnapshot.GetDirectory().GetCurrentBinary(); file += "/"; file += "CTestTestfile.cmake"; @@ -239,9 +165,11 @@ void cmLocalGenerator::GenerateTestFiles() fout << "# CMake generated Testfile for " << std::endl << "# Source directory: " - << this->StateSnapshot.GetCurrentSourceDirectory() << std::endl + << this->StateSnapshot.GetDirectory().GetCurrentSource() + << std::endl << "# Build directory: " - << this->StateSnapshot.GetCurrentBinaryDirectory() << std::endl + << this->StateSnapshot.GetDirectory().GetCurrentBinary() + << std::endl << "# " << std::endl << "# This file includes the relevant testing commands " << "required for " << std::endl @@ -261,20 +189,66 @@ void cmLocalGenerator::GenerateTestFiles() for(std::vector<cmTestGenerator*>::const_iterator gi = testers.begin(); gi != testers.end(); ++gi) { + (*gi)->Compute(this); (*gi)->Generate(fout, config, configurationTypes); } - if (!this->Children.empty()) + size_t i; + std::vector<cmState::Snapshot> children + = this->Makefile->GetStateSnapshot().GetChildren(); + for(i = 0; i < children.size(); ++i) + { + // TODO: Use add_subdirectory instead? + fout << "subdirs("; + std::string outP = children[i].GetDirectory().GetCurrentBinary(); + fout << this->Convert(outP,START_OUTPUT); + fout << ")" << std::endl; + } +} + +void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config) +{ + std::vector<cmGeneratorExpressionEvaluationFile*> ef = + this->Makefile->GetEvaluationFiles(); + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = ef.begin(); li != ef.end(); ++li) + { + (*li)->CreateOutputFile(this, config); + } +} + +void cmLocalGenerator::ProcessEvaluationFiles( + std::vector<std::string>& generatedFiles) +{ + std::vector<cmGeneratorExpressionEvaluationFile*> ef = + this->Makefile->GetEvaluationFiles(); + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = ef.begin(); + li != ef.end(); + ++li) { - size_t i; - for(i = 0; i < this->Children.size(); ++i) + (*li)->Generate(this); + if (cmSystemTools::GetFatalErrorOccured()) + { + return; + } + std::vector<std::string> files = (*li)->GetFiles(); + std::sort(files.begin(), files.end()); + + std::vector<std::string> intersection; + std::set_intersection(files.begin(), files.end(), + generatedFiles.begin(), generatedFiles.end(), + std::back_inserter(intersection)); + if (!intersection.empty()) { - // TODO: Use add_subdirectory instead? - fout << "subdirs("; - std::string outP = - this->Children[i]->GetMakefile()->GetCurrentBinaryDirectory(); - fout << this->Convert(outP,START_OUTPUT); - fout << ")" << std::endl; + cmSystemTools::Error("Files to be generated by multiple different " + "commands: ", cmWrap('"', intersection, '"', " ").c_str()); + return; } + + generatedFiles.insert(generatedFiles.end(), files.begin(), files.end()); + std::vector<std::string>::iterator newIt = + generatedFiles.end() - files.size(); + std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end()); } } @@ -355,7 +329,8 @@ void cmLocalGenerator::GenerateInstallRules() } // Create the install script file. - std::string file = this->StateSnapshot.GetCurrentBinaryDirectory(); + std::string file = + this->StateSnapshot.GetDirectory().GetCurrentBinary(); std::string homedir = this->GetState()->GetBinaryDirectory(); int toplevel_install = 0; if (file == homedir) @@ -368,7 +343,7 @@ void cmLocalGenerator::GenerateInstallRules() // Write the header. fout << "# Install script for directory: " - << this->StateSnapshot.GetCurrentSourceDirectory() + << this->StateSnapshot.GetDirectory().GetCurrentSource() << std::endl << std::endl; fout << "# Set the install prefix" << std::endl << "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl @@ -432,16 +407,18 @@ void cmLocalGenerator::GenerateInstallRules() this->GenerateTargetInstallRules(fout, config, configurationTypes); // Include install scripts from subdirectories. - if(!this->Children.empty()) + std::vector<cmState::Snapshot> children + = this->Makefile->GetStateSnapshot().GetChildren(); + if(!children.empty()) { fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"; fout << " # Include the install script for each subdirectory.\n"; - for(std::vector<cmLocalGenerator*>::const_iterator - ci = this->Children.begin(); ci != this->Children.end(); ++ci) + for(std::vector<cmState::Snapshot>::const_iterator + ci = children.begin(); ci != children.end(); ++ci) { - if(!(*ci)->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL")) + if(!ci->GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) { - std::string odir = (*ci)->GetMakefile()->GetCurrentBinaryDirectory(); + std::string odir = ci->GetDirectory().GetCurrentBinary(); cmSystemTools::ConvertToUnixSlashes(odir); fout << " include(\"" << odir << "/cmake_install.cmake\")" << std::endl; @@ -470,7 +447,7 @@ void cmLocalGenerator::GenerateInstallRules() } //---------------------------------------------------------------------------- -void cmLocalGenerator::GenerateTargetManifest() +void cmLocalGenerator::ComputeTargetManifest() { // Collect the set of configuration types. std::vector<std::string> configNames; @@ -498,7 +475,7 @@ void cmLocalGenerator::GenerateTargetManifest() ci != configNames.end(); ++ci) { const char* config = ci->c_str(); - target.GenerateTargetManifest(config); + target.ComputeTargetManifest(config); } } } @@ -513,225 +490,6 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const return this->StateSnapshot; } -void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, - const std::string& lang, - cmSourceFile& source, - cmGeneratorTarget& target) -{ - std::string objectDir = cmSystemTools::GetFilenamePath(std::string(ofname)); - objectDir = this->Convert(objectDir,START_OUTPUT,SHELL); - std::string objectFile = this->Convert(ofname,START_OUTPUT,SHELL); - std::string sourceFile = - this->Convert(source.GetFullPath(),START_OUTPUT,SHELL,true); - std::string varString = "CMAKE_"; - varString += lang; - varString += "_COMPILE_OBJECT"; - std::vector<std::string> rules; - rules.push_back(this->Makefile->GetRequiredDefinition(varString)); - varString = "CMAKE_"; - varString += lang; - varString += "_FLAGS"; - std::string flags; - flags += this->Makefile->GetSafeDefinition(varString); - flags += " "; - { - std::vector<std::string> includes; - this->GetIncludeDirectories(includes, &target, lang); - flags += this->GetIncludeFlags(includes, &target, lang); - } - flags += this->Makefile->GetDefineFlags(); - - // Construct the command lines. - cmCustomCommandLines commandLines; - std::vector<std::string> commands; - cmSystemTools::ExpandList(rules, commands); - cmLocalGenerator::RuleVariables vars; - vars.Language = lang.c_str(); - vars.Source = sourceFile.c_str(); - vars.Object = objectFile.c_str(); - vars.ObjectDir = objectDir.c_str(); - vars.Flags = flags.c_str(); - for(std::vector<std::string>::iterator i = commands.begin(); - i != commands.end(); ++i) - { - // Expand the full command line string. - this->ExpandRuleVariables(*i, vars); - - // Parse the string to get the custom command line. - cmCustomCommandLine commandLine; - std::vector<std::string> cmd = cmSystemTools::ParseArguments(i->c_str()); - commandLine.insert(commandLine.end(), cmd.begin(), cmd.end()); - - // Store this command line. - commandLines.push_back(commandLine); - } - - // Check for extra object-file dependencies. - std::vector<std::string> depends; - const char* additionalDeps = source.GetProperty("OBJECT_DEPENDS"); - if(additionalDeps) - { - cmSystemTools::ExpandListArgument(additionalDeps, depends); - } - - // Generate a meaningful comment for the command. - std::string comment = "Building "; - comment += lang; - comment += " object "; - comment += this->Convert(ofname, START_OUTPUT); - - // Add the custom command to build the object file. - this->Makefile->AddCustomCommandToOutput( - ofname, - depends, - source.GetFullPath(), - commandLines, - comment.c_str(), - this->StateSnapshot.GetCurrentBinaryDirectory() - ); -} - -void cmLocalGenerator::AddBuildTargetRule(const std::string& llang, - cmGeneratorTarget& target) -{ - std::string objs; - std::vector<std::string> objVector; - std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - // Add all the sources outputs to the depends of the target - std::vector<cmSourceFile*> classes; - target.GetSourceFiles(classes, config); - for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) - { - cmSourceFile* sf = *i; - if(!sf->GetCustomCommand() && - !sf->GetPropertyAsBool("HEADER_FILE_ONLY") && - !sf->GetPropertyAsBool("EXTERNAL_OBJECT")) - { - std::string dir_max; - dir_max += this->StateSnapshot.GetCurrentBinaryDirectory(); - dir_max += "/"; - std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_max); - if(!obj.empty()) - { - std::string ofname = this->StateSnapshot.GetCurrentBinaryDirectory(); - ofname += "/"; - ofname += obj; - objVector.push_back(ofname); - this->AddCustomCommandToCreateObject(ofname.c_str(), - llang, *(*i), target); - objs += this->Convert(ofname,START_OUTPUT,SHELL); - objs += " "; - } - } - } - std::string createRule = target.GetCreateRuleVariable(llang, config); - bool useWatcomQuote = this->Makefile->IsOn(createRule+"_USE_WATCOM_QUOTE"); - std::string targetName = target.Target->GetFullName(); - // Executable : - // Shared Library: - // Static Library: - // Shared Module: - std::string linkLibs; // should be set - std::string frameworkPath; - std::string linkPath; - std::string flags; // should be set - std::string linkFlags; // should be set - this->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags, - &target, useWatcomQuote); - linkLibs = frameworkPath + linkPath + linkLibs; - cmLocalGenerator::RuleVariables vars; - vars.Language = llang.c_str(); - vars.Objects = objs.c_str(); - vars.ObjectDir = "."; - vars.Target = targetName.c_str(); - vars.LinkLibraries = linkLibs.c_str(); - vars.Flags = flags.c_str(); - vars.LinkFlags = linkFlags.c_str(); - - std::string langFlags; - this->AddLanguageFlags(langFlags, llang, ""); - this->AddArchitectureFlags(langFlags, &target, llang, ""); - vars.LanguageCompileFlags = langFlags.c_str(); - - cmCustomCommandLines commandLines; - std::vector<std::string> rules; - rules.push_back(this->Makefile->GetRequiredDefinition(createRule)); - std::vector<std::string> commands; - cmSystemTools::ExpandList(rules, commands); - for(std::vector<std::string>::iterator i = commands.begin(); - i != commands.end(); ++i) - { - // Expand the full command line string. - this->ExpandRuleVariables(*i, vars); - // Parse the string to get the custom command line. - cmCustomCommandLine commandLine; - std::vector<std::string> cmd = cmSystemTools::ParseArguments(i->c_str()); - commandLine.insert(commandLine.end(), cmd.begin(), cmd.end()); - - // Store this command line. - commandLines.push_back(commandLine); - } - std::string targetFullPath = target.Target->GetFullPath(); - // Generate a meaningful comment for the command. - std::string comment = "Linking "; - comment += llang; - comment += " target "; - comment += this->Convert(targetFullPath, START_OUTPUT); - this->Makefile->AddCustomCommandToOutput( - targetFullPath, - objVector, - "", - commandLines, - comment.c_str(), - this->StateSnapshot.GetCurrentBinaryDirectory() - ); - this->Makefile->GetSource(targetFullPath); - target.Target->AddSource(targetFullPath); -} - - -void cmLocalGenerator -::CreateCustomTargetsAndCommands(std::set<std::string> const& lang) -{ - cmGeneratorTargetsType tgts = this->Makefile->GetGeneratorTargets(); - for(cmGeneratorTargetsType::iterator l = tgts.begin(); - l != tgts.end(); l++) - { - if (l->first->IsImported()) - { - continue; - } - cmGeneratorTarget& target = *l->second; - switch(target.GetType()) - { - case cmTarget::STATIC_LIBRARY: - case cmTarget::SHARED_LIBRARY: - case cmTarget::MODULE_LIBRARY: - case cmTarget::EXECUTABLE: - { - std::string llang = target.Target->GetLinkerLanguage(); - if(llang.empty()) - { - cmSystemTools::Error - ("CMake can not determine linker language for target: ", - target.Target->GetName().c_str()); - return; - } - // if the language is not in the set lang then create custom - // commands to build the target - if(lang.count(llang) == 0) - { - this->AddBuildTargetRule(llang, target); - } - } - break; - default: - break; - } - } -} - // List of variables that are replaced when // rules are expanced. These variables are // replaced in the form <var> with GetSafeDefinition(var). @@ -835,6 +593,10 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, { return replaceValues.Defines; } + if(replaceValues.Includes && variable == "INCLUDES") + { + return replaceValues.Includes; + } if(replaceValues.TargetPDB ) { if(variable == "TARGET_PDB") @@ -1169,56 +931,6 @@ void cmLocalGenerator::InsertRuleLauncher(std::string& s, cmTarget* target, //---------------------------------------------------------------------------- std::string -cmLocalGenerator::ConvertToOutputForExistingCommon(const std::string& remote, - std::string const& result, - OutputFormat format) -{ - // If this is a windows shell, the result has a space, and the path - // already exists, we can use a short-path to reference it without a - // space. - if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos && - cmSystemTools::FileExists(remote.c_str())) - { - std::string tmp; - if(cmSystemTools::GetShortPath(remote, tmp)) - { - return this->Convert(tmp, NONE, format, true); - } - } - - // Otherwise, leave it unchanged. - return result; -} - -//---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToOutputForExisting(const std::string& remote, - RelativeRoot local, - OutputFormat format) -{ - // Perform standard conversion. - std::string result = this->Convert(remote, local, format, true); - - // Consider short-path. - return this->ConvertToOutputForExistingCommon(remote, result, format); -} - -//---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote, - const std::string& local, - OutputFormat format) -{ - // Perform standard conversion. - std::string result = this->Convert(remote, local, format, true); - - // Consider short-path. - const char* remotePath = this->GetRelativeRootPath(remote); - return this->ConvertToOutputForExistingCommon(remotePath, result, format); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::ConvertToIncludeReference(std::string const& path, OutputFormat format, bool forceFullPaths) @@ -1316,8 +1028,7 @@ std::string cmLocalGenerator::GetIncludeFlags( { includeFlags << fwSearchFlag; } - includeFlags << this->Convert(frameworkDir, START_OUTPUT, - shellFormat, true) + includeFlags << this->ConvertToOutputFormat(frameworkDir, shellFormat) << " "; } continue; @@ -1365,7 +1076,8 @@ void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines, const std::string& lang) { std::vector<std::string> targetDefines; - target->GetCompileDefinitions(targetDefines, config, lang); + cmGeneratorTarget* gtgt = this->GlobalGenerator->GetGeneratorTarget(target); + gtgt->GetCompileDefinitions(targetDefines, config, lang); this->AppendDefines(defines, targetDefines); } @@ -1376,6 +1088,10 @@ void cmLocalGenerator::AddCompileOptions( ) { std::string langFlagRegexVar = std::string("CMAKE_")+lang+"_FLAG_REGEX"; + + cmGeneratorTarget* gtgt = + this->GlobalGenerator->GetGeneratorTarget(target); + if(const char* langFlagRegexStr = this->Makefile->GetDefinition(langFlagRegexVar)) { @@ -1386,7 +1102,7 @@ void cmLocalGenerator::AddCompileOptions( { cmSystemTools::ParseWindowsCommandLine(targetFlags, opts); } - target->GetCompileOptions(opts, config, lang); + gtgt->GetCompileOptions(opts, config, lang); for(std::vector<std::string>::const_iterator i = opts.begin(); i != opts.end(); ++i) { @@ -1407,7 +1123,7 @@ void cmLocalGenerator::AddCompileOptions( this->AppendFlags(flags, targetFlags); } std::vector<std::string> opts; - target->GetCompileOptions(opts, config, lang); + gtgt->GetCompileOptions(opts, config, lang); for(std::vector<std::string>::const_iterator i = opts.begin(); i != opts.end(); ++i) { @@ -1416,7 +1132,7 @@ void cmLocalGenerator::AddCompileOptions( } } std::vector<std::string> features; - target->GetCompileFeatures(features, config); + gtgt->GetCompileFeatures(features, config); for(std::vector<std::string>::const_iterator it = features.begin(); it != features.end(); ++it) { @@ -1446,7 +1162,7 @@ void cmLocalGenerator::AddCompileOptions( "higher \"" << it->first << "_STANDARD\" \"" << standard << "\". " "This is not permitted. The COMPILE_FEATURES may not both depend on " "and be depended on by the link implementation." << std::endl; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } } @@ -1459,7 +1175,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, const std::string& lang, const std::string& config, bool stripImplicitInclDirs - ) + ) const { // Need to decide whether to automatically include the source and // binary directories at the beginning of the include path. @@ -1485,20 +1201,20 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, // Store the automatic include paths. if(includeBinaryDir) { - if(emitted.find( - this->StateSnapshot.GetCurrentBinaryDirectory()) == emitted.end()) + std::string binDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); + if(emitted.find(binDir) == emitted.end()) { - dirs.push_back(this->StateSnapshot.GetCurrentBinaryDirectory()); - emitted.insert(this->StateSnapshot.GetCurrentBinaryDirectory()); + dirs.push_back(binDir); + emitted.insert(binDir); } } if(includeSourceDir) { - if(emitted.find( - this->StateSnapshot.GetCurrentSourceDirectory()) == emitted.end()) + std::string srcDir = this->StateSnapshot.GetDirectory().GetCurrentSource(); + if(emitted.find(srcDir) == emitted.end()) { - dirs.push_back(this->StateSnapshot.GetCurrentSourceDirectory()); - emitted.insert(this->StateSnapshot.GetCurrentSourceDirectory()); + dirs.push_back(srcDir); + emitted.insert(srcDir); } } @@ -1684,7 +1400,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, linkFlags += this->Makefile->GetSafeDefinition(build); linkFlags += " "; } - std::string linkLanguage = target->Target->GetLinkerLanguage(buildType); + std::string linkLanguage = target->GetLinkerLanguage(buildType); if(linkLanguage.empty()) { cmSystemTools::Error @@ -1799,7 +1515,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, bool escapeAllowMakeVars = !forResponseFile; std::ostringstream fout; std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config); + cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config); if(!pcli) { return; @@ -2030,7 +1746,8 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, } // Look for a CMake target with the given name. - if(cmTarget* target = this->Makefile->FindTargetToUse(name)) + if(cmGeneratorTarget* target = + this->Makefile->FindGeneratorTargetToUse(name)) { // make sure it is not just a coincidence that the target name // found is part of the inName @@ -2099,7 +1816,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, // Treat the name as relative to the source directory in which it // was given. - dep = this->StateSnapshot.GetCurrentSourceDirectory(); + dep = this->StateSnapshot.GetDirectory().GetCurrentSource(); dep += "/"; dep += inName; return true; @@ -2170,7 +1887,7 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget const* target, "dialect \"" << lang << standardProp << "\" " << (ext ? "(with compiler extensions)" : "") << ", but CMake " "does not know the compile flags to use to enable it."; - this->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(cmake::FATAL_ERROR, e.str()); } else { @@ -2214,7 +1931,7 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget const* target, std::string e = "CMAKE_" + lang + "_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) + "'"; - this->Makefile->IssueMessage(cmake::INTERNAL_ERROR, e); + this->IssueMessage(cmake::INTERNAL_ERROR, e); return; } @@ -2389,7 +2106,9 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, return; } - if (target->GetLinkInterfaceDependentBoolProperty( + cmGeneratorTarget* gtgt = + this->GlobalGenerator->GetGeneratorTarget(target); + if (gtgt->GetLinkInterfaceDependentBoolProperty( "POSITION_INDEPENDENT_CODE", config)) { @@ -2430,7 +2149,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, << flagsVar << " was removed.\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018); - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); // fall through to OLD behaviour } case cmPolicies::OLD: @@ -2644,6 +2363,30 @@ void cmLocalGenerator::AppendFeatureOptions( } //---------------------------------------------------------------------------- +const char* cmLocalGenerator::GetFeature(const std::string& feature, + const std::string& config) +{ + std::string featureName = feature; + // TODO: Define accumulation policy for features (prepend, append, replace). + // Currently we always replace. + if(!config.empty()) + { + featureName += "_"; + featureName += cmSystemTools::UpperCase(config); + } + cmState::Snapshot snp = this->StateSnapshot; + while(snp.IsValid()) + { + if(const char* value = snp.GetDirectory().GetProperty(featureName)) + { + return value; + } + snp = snp.GetBuildsystemDirectoryParent(); + } + return 0; +} + +//---------------------------------------------------------------------------- std::string cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg, const char* default_comment) @@ -2675,250 +2418,18 @@ cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg, } //---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToOptionallyRelativeOutputPath( - const std::string& remote) -{ - return this->Convert(remote, START_OUTPUT, SHELL, true); -} - -//---------------------------------------------------------------------------- -const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot) -{ - switch (relroot) - { - case HOME: return this->GetState()->GetSourceDirectory(); - case START: return this->StateSnapshot.GetCurrentSourceDirectory(); - case HOME_OUTPUT: return this->GetState()->GetBinaryDirectory(); - case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory(); - default: break; - } - return 0; -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::Convert(const std::string& source, - RelativeRoot relative, - OutputFormat output, - bool optional) -{ - // Convert the path to a relative path. - std::string result = source; - - if (!optional || this->UseRelativePaths) - { - switch (relative) - { - case HOME: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->GetState()->GetSourceDirectoryComponents(), result); - break; - case START: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result); - break; - case HOME_OUTPUT: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->GetState()->GetBinaryDirectoryComponents(), result); - break; - case START_OUTPUT: - //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath( - this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result); - break; - case FULL: - result = cmSystemTools::CollapseFullPath(result); - break; - case NONE: - break; - } - } - return this->ConvertToOutputFormat(result, output); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source, - OutputFormat output) -{ - std::string result = source; - // Convert it to an output path. - if (output == MAKERULE) - { - result = cmSystemTools::ConvertToOutputPath(result.c_str()); - } - else if(output == SHELL || output == WATCOMQUOTE) - { - // For the MSYS shell convert drive letters to posix paths, so - // that c:/some/path becomes /c/some/path. This is needed to - // avoid problems with the shell path translation. - if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) - { - if(result.size() > 2 && result[1] == ':') - { - result[1] = result[0]; - result[0] = '/'; - } - } - if(this->GetState()->UseWindowsShell()) - { - std::replace(result.begin(), result.end(), '/', '\\'); - } - result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); - } - else if(output == RESPONSE) - { - result = this->EscapeForShell(result, false, false, false); - } - return result; -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::Convert(RelativeRoot remote, - const std::string& local, - OutputFormat output, - bool optional) -{ - const char* remotePath = this->GetRelativeRootPath(remote); - - // The relative root must have a path (i.e. not FULL or NONE) - assert(remotePath != 0); - - if(!local.empty() && (!optional || this->UseRelativePaths)) - { - std::vector<std::string> components; - cmSystemTools::SplitPath(local, components); - std::string result = this->ConvertToRelativePath(components, remotePath); - return this->ConvertToOutputFormat(result, output); - } - else - { - return this->ConvertToOutputFormat(remotePath, output); - } -} - -//---------------------------------------------------------------------------- -static bool cmLocalGeneratorNotAbove(const char* a, const char* b) -{ - return (cmSystemTools::ComparePath(a, b) || - cmSystemTools::IsSubDirectory(a, b)); -} - -//---------------------------------------------------------------------------- -std::string -cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local, - const std::string& in_remote, - bool force) -{ - // The path should never be quoted. - assert(in_remote[0] != '\"'); - - // The local path should never have a trailing slash. - assert(!local.empty() && !(local[local.size()-1] == "")); - - // If the path is already relative then just return the path. - if(!cmSystemTools::FileIsFullPath(in_remote.c_str())) - { - return in_remote; - } - - if(!force) - { - // Skip conversion if the path and local are not both in the source - // or both in the binary tree. - std::string local_path = cmSystemTools::JoinPath(local); - if(!((cmLocalGeneratorNotAbove(local_path.c_str(), - this->StateSnapshot.GetRelativePathTopBinary()) && - cmLocalGeneratorNotAbove(in_remote.c_str(), - this->StateSnapshot.GetRelativePathTopBinary())) || - (cmLocalGeneratorNotAbove(local_path.c_str(), - this->StateSnapshot.GetRelativePathTopSource()) && - cmLocalGeneratorNotAbove(in_remote.c_str(), - this->StateSnapshot.GetRelativePathTopSource())))) - { - return in_remote; - } - } - - // Identify the longest shared path component between the remote - // path and the local path. - std::vector<std::string> remote; - cmSystemTools::SplitPath(in_remote, remote); - unsigned int common=0; - while(common < remote.size() && - common < local.size() && - cmSystemTools::ComparePath(remote[common], - local[common])) - { - ++common; - } - - // If no part of the path is in common then return the full path. - if(common == 0) - { - return in_remote; - } - - // If the entire path is in common then just return a ".". - if(common == remote.size() && - common == local.size()) - { - return "."; - } - - // If the entire path is in common except for a trailing slash then - // just return a "./". - if(common+1 == remote.size() && - remote[common].empty() && - common == local.size()) - { - return "./"; - } - - // Construct the relative path. - std::string relative; - - // First add enough ../ to get up to the level of the shared portion - // of the path. Leave off the trailing slash. Note that the last - // component of local will never be empty because local should never - // have a trailing slash. - for(unsigned int i=common; i < local.size(); ++i) - { - relative += ".."; - if(i < local.size()-1) - { - relative += "/"; - } - } - - // Now add the portion of the destination path that is not included - // in the shared portion of the path. Add a slash the first time - // only if there was already something in the path. If there was a - // trailing slash in the input then the last iteration of the loop - // will add a slash followed by an empty string which will preserve - // the trailing slash in the output. - - if(!relative.empty() && !remote.empty()) - { - relative += "/"; - } - relative += cmJoin(cmRange(remote).advance(common), "/"); - - // Finally return the path. - return relative; -} - -//---------------------------------------------------------------------------- class cmInstallTargetGeneratorLocal: public cmInstallTargetGenerator { public: - cmInstallTargetGeneratorLocal(cmTarget& t, const char* dest, bool implib): + cmInstallTargetGeneratorLocal(cmLocalGenerator* lg, std::string const& t, + const char* dest, bool implib): cmInstallTargetGenerator( t, dest, implib, "", std::vector<std::string>(), "Unspecified", - cmInstallGenerator::SelectMessageLevel(t.GetMakefile()), - false) {} + cmInstallGenerator::SelectMessageLevel(lg->GetMakefile()), + false) + { + this->Compute(lg); + } }; //---------------------------------------------------------------------------- @@ -2967,7 +2478,7 @@ cmLocalGenerator { // Use a target install generator. cmInstallTargetGeneratorLocal - g(l->second, destination.c_str(), false); + g(this, l->first, destination.c_str(), false); g.Generate(os, config, configurationTypes); } break; @@ -2978,18 +2489,18 @@ cmLocalGenerator // to the normal destination and the DLL to the runtime // destination. cmInstallTargetGeneratorLocal - g1(l->second, destination.c_str(), true); + g1(this, l->first, destination.c_str(), true); g1.Generate(os, config, configurationTypes); // We also skip over the leading slash given by the user. destination = l->second.GetRuntimeInstallPath().substr(1); cmSystemTools::ConvertToUnixSlashes(destination); cmInstallTargetGeneratorLocal - g2(l->second, destination.c_str(), false); + g2(this, l->first, destination.c_str(), false); g2.Generate(os, config, configurationTypes); #else // Use a target install generator. cmInstallTargetGeneratorLocal - g(l->second, destination.c_str(), false); + g(this, l->first, destination.c_str(), false); g.Generate(os, config, configurationTypes); #endif } @@ -3151,7 +2662,7 @@ cmLocalGenerator << " " << ssin << "\n" << "cannot be safely placed under this directory. " << "The build may not work correctly."; - this->Makefile->IssueMessage(cmake::WARNING, m.str()); + this->IssueMessage(cmake::WARNING, m.str()); } } #else @@ -3195,11 +2706,6 @@ bool cmLocalGenerator::IsNMake() const return this->GetState()->UseNMake(); } -void cmLocalGenerator::SetConfiguredCMP0014(bool configured) -{ - this->Configured = configured; -} - //---------------------------------------------------------------------------- std::string cmLocalGenerator @@ -3308,150 +2814,6 @@ cmLocalGenerator } //---------------------------------------------------------------------------- -static bool cmLocalGeneratorIsShellOperator(const std::string& str) -{ - static std::set<std::string> shellOperators; - if(shellOperators.empty()) - { - shellOperators.insert("<"); - shellOperators.insert(">"); - shellOperators.insert("<<"); - shellOperators.insert(">>"); - shellOperators.insert("|"); - shellOperators.insert("||"); - shellOperators.insert("&&"); - shellOperators.insert("&>"); - shellOperators.insert("1>"); - shellOperators.insert("2>"); - shellOperators.insert("2>&1"); - shellOperators.insert("1>&2"); - } - return shellOperators.count(str) > 0; -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::EscapeForShell(const std::string& str, - bool makeVars, - bool forEcho, - bool useWatcomQuote) -{ - // Do not escape shell operators. - if(cmLocalGeneratorIsShellOperator(str)) - { - return str; - } - - // Compute the flags for the target shell environment. - int flags = 0; - if(this->GetState()->UseWindowsVSIDE()) - { - flags |= cmsysSystem_Shell_Flag_VSIDE; - } - else if(!this->LinkScriptShell) - { - flags |= cmsysSystem_Shell_Flag_Make; - } - if(makeVars) - { - flags |= cmsysSystem_Shell_Flag_AllowMakeVariables; - } - if(forEcho) - { - flags |= cmsysSystem_Shell_Flag_EchoWindows; - } - if(useWatcomQuote) - { - flags |= cmsysSystem_Shell_Flag_WatcomQuote; - } - if(this->GetState()->UseWatcomWMake()) - { - flags |= cmsysSystem_Shell_Flag_WatcomWMake; - } - if(this->GetState()->UseMinGWMake()) - { - flags |= cmsysSystem_Shell_Flag_MinGWMake; - } - if(this->GetState()->UseNMake()) - { - flags |= cmsysSystem_Shell_Flag_NMake; - } - - // Compute the buffer size needed. - int size = (this->GetState()->UseWindowsShell() ? - cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) : - cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags)); - - // Compute the shell argument itself. - std::vector<char> arg(size); - if(this->GetState()->UseWindowsShell()) - { - cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags); - } - else - { - cmsysSystem_Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags); - } - return std::string(&arg[0]); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::EscapeForCMake(const std::string& str) -{ - // Always double-quote the argument to take care of most escapes. - std::string result = "\""; - for(const char* c = str.c_str(); *c; ++c) - { - if(*c == '"') - { - // Escape the double quote to avoid ending the argument. - result += "\\\""; - } - else if(*c == '$') - { - // Escape the dollar to avoid expanding variables. - result += "\\$"; - } - else if(*c == '\\') - { - // Escape the backslash to avoid other escapes. - result += "\\\\"; - } - else - { - // Other characters will be parsed correctly. - result += *c; - } - } - result += "\""; - return result; -} - -//---------------------------------------------------------------------------- -cmLocalGenerator::FortranFormat -cmLocalGenerator::GetFortranFormat(const char* value) -{ - FortranFormat format = FortranFormatNone; - if(value && *value) - { - std::vector<std::string> fmt; - cmSystemTools::ExpandListArgument(value, fmt); - for(std::vector<std::string>::iterator fi = fmt.begin(); - fi != fmt.end(); ++fi) - { - if(*fi == "FIXED") - { - format = FortranFormatFixed; - } - if(*fi == "FREE") - { - format = FortranFormatFree; - } - } - } - return format; -} - -//---------------------------------------------------------------------------- std::string cmLocalGenerator::GetTargetDirectory(cmTarget const&) const { @@ -3481,7 +2843,7 @@ cmIML_INT_uint64_t cmLocalGenerator::GetBackwardsCompatibility() } } this->BackwardsCompatibility = CMake_VERSION_ENCODE(major, minor, patch); - this->BackwardsCompatibilityFinal = this->Configured; + this->BackwardsCompatibilityFinal = this->Makefile->IsConfigured(); } return this->BackwardsCompatibility; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 32b17f5..b051e5d 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -14,6 +14,8 @@ #include "cmStandardIncludes.h" #include "cmState.h" +#include "cmake.h" +#include "cmOutputConverter.h" class cmMakefile; class cmGlobalGenerator; @@ -31,26 +33,18 @@ class cmCustomCommandGenerator; * platforms. This class should never be constructed directly. A * GlobalGenerator will create it and invoke the appropriate commands on it. */ -class cmLocalGenerator +class cmLocalGenerator : public cmOutputConverter { public: - cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile); virtual ~cmLocalGenerator(); - /// @return whether we are processing the top CMakeLists.txt file. - bool IsRootMakefile() const; - /** * Generate the makefile for this directory. */ virtual void Generate() {} - /** - * Process the CMakeLists files for this directory to fill in the - * Makefile ivar - */ - virtual void Configure(); + virtual void ComputeHomeRelativeOutputPath() {} /** * Calls TraceVSDependencies() on all targets of this generator. @@ -60,11 +54,6 @@ public: virtual void AddHelperCommands() {} /** - * Perform any final calculations prior to generation - */ - void ConfigureFinalPass(); - - /** * Generate the install rules files in this directory. */ void GenerateInstallRules(); @@ -77,7 +66,7 @@ public: /** * Generate a manifest of target files that will be built. */ - void GenerateTargetManifest(); + void ComputeTargetManifest(); ///! Get the makefile for this generator cmMakefile *GetMakefile() { @@ -96,52 +85,6 @@ public: cmState* GetState() const; cmState::Snapshot GetStateSnapshot() const; - /** - * Convert something to something else. This is a centralized conversion - * routine used by the generators to handle relative paths and the like. - * The flags determine what is actually done. - * - * relative: treat the argument as a directory and convert it to make it - * relative or full or unchanged. If relative (HOME, START etc) then that - * specifies what it should be relative to. - * - * output: make the result suitable for output to a... - * - * optional: should any relative path operation be controlled by the rel - * path setting - */ - enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; - enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE }; - std::string ConvertToOutputFormat(const std::string& source, - OutputFormat output); - std::string Convert(const std::string& remote, RelativeRoot local, - OutputFormat output = UNCHANGED, - bool optional = false); - std::string Convert(RelativeRoot remote, const std::string& local, - OutputFormat output = UNCHANGED, - bool optional = false); - - /** - * Get path for the specified relative root. - */ - const char* GetRelativeRootPath(RelativeRoot relroot); - - /** - * Convert the given path to an output path that is optionally - * relative based on the cache option CMAKE_USE_RELATIVE_PATHS. The - * remote path must use forward slashes and not already be escaped - * or quoted. - */ - std::string ConvertToOptionallyRelativeOutputPath(const std::string& remote); - - ///! set/get the parent generator - cmLocalGenerator* GetParent() const {return this->Parent;} - - ///! set/get the children - void AddChild(cmLocalGenerator* g) { this->Children.push_back(g); } - std::vector<cmLocalGenerator*>& GetChildren() { return this->Children; } - - void AddArchitectureFlags(std::string& flags, cmGeneratorTarget const* target, const std::string&lang, const std::string& config); @@ -194,6 +137,9 @@ public: void AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature); + const char* GetFeature(const std::string& feature, + const std::string& config); + /** \brief Get absolute path to dependency \a name * * Translate a dependency as given in CMake code to the name to @@ -209,17 +155,6 @@ public: bool GetRealDependency(const std::string& name, const std::string& config, std::string& dep); - ///! for existing files convert to output path and short path if spaces - std::string ConvertToOutputForExisting(const std::string& remote, - RelativeRoot local = START_OUTPUT, - OutputFormat format = SHELL); - - /** For existing path identified by RelativeRoot convert to output - path and short path if spaces. */ - std::string ConvertToOutputForExisting(RelativeRoot remote, - const std::string& local = "", - OutputFormat format = SHELL); - virtual std::string ConvertToIncludeReference(std::string const& path, OutputFormat format = SHELL, bool forceFullPaths = false); @@ -239,7 +174,7 @@ public: cmGeneratorTarget* target, const std::string& lang = "C", const std::string& config = "", - bool stripImplicitInclDirs = true); + bool stripImplicitInclDirs = true) const; void AddCompileOptions(std::string& flags, cmTarget* target, const std::string& lang, const std::string& config); void AddCompileDefinitions(std::set<std::string>& defines, @@ -286,45 +221,12 @@ public: const char* LinkFlags; const char* LanguageCompileFlags; const char* Defines; + const char* Includes; const char* RuleLauncher; const char* DependencyFile; const char* FilterPrefix; }; - /** Set whether to treat conversions to SHELL as a link script shell. */ - void SetLinkScriptShell(bool b) { this->LinkScriptShell = b; } - - /** Escape the given string to be used as a command line argument in - the native build system shell. Optionally allow the build - system to replace make variable references. Optionally adjust - escapes for the special case of passing to the native echo - command. */ - std::string EscapeForShell(const std::string& str, bool makeVars = false, - bool forEcho = false, - bool useWatcomQuote = false); - - /** Escape the given string as an argument in a CMake script. */ - static std::string EscapeForCMake(const std::string& str); - - enum FortranFormat - { - FortranFormatNone, - FortranFormatFixed, - FortranFormatFree - }; - FortranFormat GetFortranFormat(const char* value); - - /** - * Convert the given remote path to a relative path with respect to - * the given local path. The local path must be given in component - * form (see SystemTools::SplitPath) without a trailing slash. The - * remote path must use forward slashes and not already be escaped - * or quoted. - */ - std::string ConvertToRelativePath(const std::vector<std::string>& local, - const std::string& remote, - bool force=false); - /** * Get the relative path from the generator output directory to a * per-target support directory. @@ -392,8 +294,12 @@ public: bool IsMinGWMake() const; bool IsNMake() const; - void SetConfiguredCMP0014(bool configured); + void IssueMessage(cmake::MessageType t, std::string const& text) const; + void CreateEvaluationFileOutputs(const std::string& config); + void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles); + + void ComputeObjectMaxPath(); protected: ///! put all the libraries for a target on into the given stream void OutputLinkLibraries(std::string& linkLibraries, @@ -415,23 +321,6 @@ protected: void InsertRuleLauncher(std::string& s, cmTarget* target, const std::string& prop); - - /** Convert a target to a utility target for unsupported - * languages of a generator */ - void AddBuildTargetRule(const std::string& llang, - cmGeneratorTarget& target); - ///! add a custom command to build a .o file that is part of a target - void AddCustomCommandToCreateObject(const char* ofname, - const std::string& lang, - cmSourceFile& source, - cmGeneratorTarget& target); - // Create Custom Targets and commands for unsupported languages - // The set passed in should contain the languages supported by the - // generator directly. Any targets containing files that are not - // of the types listed will be compiled as custom commands and added - // to a custom target. - void CreateCustomTargetsAndCommands(std::set<std::string> const&); - // Handle old-style install rules stored in the targets. void GenerateTargetInstallRules( std::ostream& os, const std::string& config, @@ -439,7 +328,6 @@ protected: std::string& CreateSafeUniqueObjectFileName(const std::string& sin, std::string const& dir_max); - void ComputeObjectMaxPath(); virtual std::string ConvertToLinkReference(std::string const& lib, OutputFormat format = SHELL); @@ -451,17 +339,12 @@ protected: cmMakefile *Makefile; cmState::Snapshot StateSnapshot; cmGlobalGenerator *GlobalGenerator; - cmLocalGenerator* Parent; - std::vector<cmLocalGenerator*> Children; std::map<std::string, std::string> UniqueObjectNamesMap; std::string::size_type ObjectPathMax; std::set<std::string> ObjectMaxPathViolations; std::set<cmTarget const*> WarnCMP0063; - bool LinkScriptShell; - bool UseRelativePaths; - bool Configured; bool EmitUniversalBinaryFlags; // Hack for ExpandRuleVariable until object-oriented version is @@ -471,10 +354,6 @@ protected: cmIML_INT_uint64_t BackwardsCompatibility; bool BackwardsCompatibilityFinal; private: - std::string ConvertToOutputForExistingCommon(const std::string& remote, - std::string const& result, - OutputFormat format); - void AddSharedFlags(std::string& flags, const std::string& lang, bool shared); bool GetShouldUseOldFlags(bool shared, const std::string &lang) const; diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index 870b9b9..bac989f 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -17,9 +17,8 @@ #include "cmGeneratedFileStream.h" cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot) - : cmLocalGenerator(gg, parent, snapshot) + cmMakefile* mf) + : cmLocalGenerator(gg, mf) { } @@ -37,7 +36,7 @@ void cmLocalGhsMultiGenerator::Generate() { continue; } - cmGhsMultiTargetGenerator tg(l->second->Target); + cmGhsMultiTargetGenerator tg(l->second); tg.Generate(); } } diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index f52ef39..b6a9a33 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -25,8 +25,7 @@ class cmGeneratedFileStream; class cmLocalGhsMultiGenerator : public cmLocalGenerator { public: - cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalGhsMultiGenerator(); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index c08c91f..7525bf2 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -23,10 +23,8 @@ #include <assert.h> cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot) - : cmLocalGenerator(gg, parent, snapshot) - , ConfigName("") + cmMakefile* mf) + : cmLocalCommonGenerator(gg, mf) , HomeRelativeOutputPath("") { this->TargetImplib = "$TARGET_IMPLIB"; @@ -41,6 +39,15 @@ cmLocalNinjaGenerator::~cmLocalNinjaGenerator() void cmLocalNinjaGenerator::Generate() { + // Compute the path to use when referencing the current output + // directory from the top output directory. + this->HomeRelativeOutputPath = + this->Convert(this->Makefile->GetCurrentBinaryDirectory(), HOME_OUTPUT); + if(this->HomeRelativeOutputPath == ".") + { + this->HomeRelativeOutputPath = ""; + } + this->SetConfigName(); this->WriteProcessedMakefile(this->GetBuildFileStream()); @@ -49,7 +56,7 @@ void cmLocalNinjaGenerator::Generate() #endif // We do that only once for the top CMakeLists.txt file. - if(this->IsRootMakefile()) + if(this->Makefile->IsRootMakefile()) { this->WriteBuildFileTop(); @@ -82,7 +89,7 @@ void cmLocalNinjaGenerator::Generate() // Add the target to "all" if required. if (!this->GetGlobalNinjaGenerator()->IsExcluded( this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0], - *t->second->Target)) + t->second)) this->GetGlobalNinjaGenerator()->AddDependencyToAll(t->second->Target); delete tg; } @@ -91,25 +98,6 @@ void cmLocalNinjaGenerator::Generate() this->WriteCustomCommandBuildStatements(); } -// Implemented in: -// cmLocalUnixMakefileGenerator3. -// Used in: -// Source/cmMakefile.cxx -// Source/cmGlobalGenerator.cxx -void cmLocalNinjaGenerator::Configure() -{ - // Compute the path to use when referencing the current output - // directory from the top output directory. - this->HomeRelativeOutputPath = - this->Convert(this->Makefile->GetCurrentBinaryDirectory(), HOME_OUTPUT); - if(this->HomeRelativeOutputPath == ".") - { - this->HomeRelativeOutputPath = ""; - } - this->cmLocalGenerator::Configure(); - -} - // TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it. std::string cmLocalNinjaGenerator ::GetTargetDirectory(cmTarget const& target) const @@ -204,16 +192,14 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) { // Default required version - // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3 - std::string requiredVersion = "1.3"; + std::string requiredVersion = + this->GetGlobalNinjaGenerator()->RequiredNinjaVersion(); // Ninja generator uses the 'console' pool if available (>= 1.5) - std::string usedVersion = this->GetGlobalNinjaGenerator()->ninjaVersion(); - if(cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, - usedVersion.c_str(), - "1.5") == false) + if(this->GetGlobalNinjaGenerator()->SupportsConsolePool()) { - requiredVersion = "1.5"; + requiredVersion = + this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool(); } cmGlobalNinjaGenerator::WriteComment(os, @@ -271,22 +257,6 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os) os << "\n"; } -void cmLocalNinjaGenerator::SetConfigName() -{ - // Store the configuration name that will be generated. - if(const char* config = - this->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE")) - { - // Use the build type given by the user. - this->ConfigName = config; - } - else - { - // No configuration type given. - this->ConfigName = ""; - } -} - //---------------------------------------------------------------------------- void cmLocalNinjaGenerator::ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, @@ -308,7 +278,7 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) << "# Write statements declared in CMakeLists.txt:" << std::endl << "# " << this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE") << std::endl; - if(this->IsRootMakefile()) + if(this->Makefile->IsRootMakefile()) os << "# Which is the root file." << std::endl; cmGlobalNinjaGenerator::WriteDivider(os); os << std::endl; @@ -431,7 +401,7 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc)) return; - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile); + cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this); const std::vector<std::string> &outputs = ccg.GetOutputs(); const std::vector<std::string> &byproducts = ccg.GetByproducts(); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 7ae97de..8d3d49c 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -13,7 +13,7 @@ #ifndef cmLocalNinjaGenerator_h # define cmLocalNinjaGenerator_h -# include "cmLocalGenerator.h" +# include "cmLocalCommonGenerator.h" # include "cmNinjaTypes.h" class cmCustomCommandGenerator; @@ -28,18 +28,15 @@ class cmake; * cmLocalNinjaGenerator produces a local build.ninja file from its * member Makefile. */ -class cmLocalNinjaGenerator : public cmLocalGenerator +class cmLocalNinjaGenerator : public cmLocalCommonGenerator { public: - cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalNinjaGenerator(); virtual void Generate(); - virtual void Configure(); - virtual std::string GetTargetDirectory(cmTarget const& target) const; const cmGlobalNinjaGenerator* GetGlobalNinjaGenerator() const; @@ -48,9 +45,6 @@ public: const cmake* GetCMakeInstance() const; cmake* GetCMakeInstance(); - std::string const& GetConfigName() const - { return this->ConfigName; } - /// @returns the relative path between the HomeOutputDirectory and this /// local generators StartOutputDirectory. std::string GetHomeRelativeOutputPath() const @@ -112,8 +106,6 @@ private: void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); - void SetConfigName(); - void WriteCustomCommandRule(); void WriteCustomCommandBuildStatement(cmCustomCommand const *cc, const cmNinjaDeps& orderOnlyDeps); @@ -122,7 +114,6 @@ private: std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); - std::string ConfigName; std::string HomeRelativeOutputPath; typedef std::map<cmCustomCommand const*, std::set<cmTarget*> > diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 3eea59b..b131a63 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -80,9 +80,8 @@ static std::string cmSplitExtension(std::string const& in, std::string& base) //---------------------------------------------------------------------------- cmLocalUnixMakefileGenerator3:: -cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmLocalGenerator* parent, - cmState::Snapshot snapshot) - : cmLocalGenerator(gg, parent, snapshot) +cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf) + : cmLocalCommonGenerator(gg, mf) { this->MakefileVariableSize = 0; this->ColorMakefile = false; @@ -98,37 +97,9 @@ cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() } //---------------------------------------------------------------------------- -void cmLocalUnixMakefileGenerator3::Configure() -{ - // Compute the path to use when referencing the current output - // directory from the top output directory. - this->HomeRelativeOutputPath = - this->Convert(this->Makefile->GetCurrentBinaryDirectory(), HOME_OUTPUT); - if(this->HomeRelativeOutputPath == ".") - { - this->HomeRelativeOutputPath = ""; - } - if(!this->HomeRelativeOutputPath.empty()) - { - this->HomeRelativeOutputPath += "/"; - } - this->cmLocalGenerator::Configure(); -} - -//---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3::Generate() { - // Store the configuration name that will be generated. - if(const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) - { - // Use the build type given by the user. - this->ConfigurationName = config; - } - else - { - // No configuration type given. - this->ConfigurationName = ""; - } + this->SetConfigName(); // Record whether some options are enabled to avoid checking many // times later. @@ -169,6 +140,22 @@ void cmLocalUnixMakefileGenerator3::Generate() this->WriteDirectoryInformationFile(); } +void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath() +{ + // Compute the path to use when referencing the current output + // directory from the top output directory. + this->HomeRelativeOutputPath = + this->Convert(this->Makefile->GetCurrentBinaryDirectory(), HOME_OUTPUT); + if(this->HomeRelativeOutputPath == ".") + { + this->HomeRelativeOutputPath = ""; + } + if(!this->HomeRelativeOutputPath.empty()) + { + this->HomeRelativeOutputPath += "/"; + } +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3::ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, @@ -268,7 +255,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() return; } // always write the top makefile - if (this->Parent) + if (!this->GetMakefile()->IsRootMakefile()) { ruleFileStream.SetCopyIfDifferent(true); } @@ -279,7 +266,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() // only write local targets unless at the top Keep track of targets already // listed. std::set<std::string> emittedTargets; - if (this->Parent) + if (!this->GetMakefile()->IsRootMakefile()) { // write our targets, and while doing it collect up the object // file rules @@ -498,8 +485,7 @@ void cmLocalUnixMakefileGenerator3 // Add a local name for the rule to relink the target before // installation. - if(t->second->Target - ->NeedRelinkBeforeInstall(this->ConfigurationName)) + if(t->second->NeedRelinkBeforeInstall(this->ConfigName)) { makeTargetName = this->GetRelativeTargetDirectory(*t->second->Target); makeTargetName += "/preinstall"; @@ -542,10 +528,10 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() infoFileStream << "# Relative path conversion top directories.\n" << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" - << this->StateSnapshot.GetRelativePathTopSource() + << this->StateSnapshot.GetDirectory().GetRelativePathTopSource() << "\")\n" << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \"" - << this->StateSnapshot.GetRelativePathTopBinary() + << this->StateSnapshot.GetDirectory().GetRelativePathTopBinary() << "\")\n" << "\n"; @@ -900,7 +886,7 @@ void cmLocalUnixMakefileGenerator3 std::vector<std::string> no_depends; std::vector<std::string> commands; commands.push_back(runRule); - if(this->Parent) + if(!this->GetMakefile()->IsRootMakefile()) { this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), @@ -1019,8 +1005,7 @@ cmLocalUnixMakefileGenerator3 for(std::vector<cmCustomCommand>::const_iterator i = ccs.begin(); i != ccs.end(); ++i) { - cmCustomCommandGenerator ccg(*i, this->ConfigurationName, - this->Makefile); + cmCustomCommandGenerator ccg(*i, this->ConfigName, this); this->AppendCustomDepend(depends, ccg); } } @@ -1036,7 +1021,7 @@ cmLocalUnixMakefileGenerator3 { // Lookup the real name of the dependency in case it is a CMake target. std::string dep; - if(this->GetRealDependency(*d, this->ConfigurationName, + if(this->GetRealDependency(*d, this->ConfigName, dep)) { depends.push_back(dep); @@ -1055,8 +1040,7 @@ cmLocalUnixMakefileGenerator3 for(std::vector<cmCustomCommand>::const_iterator i = ccs.begin(); i != ccs.end(); ++i) { - cmCustomCommandGenerator ccg(*i, this->ConfigurationName, - this->Makefile); + cmCustomCommandGenerator ccg(*i, this->ConfigName, this); this->AppendCustomCommand(commands, ccg, target, true, relative); } } @@ -1259,7 +1243,7 @@ cmLocalUnixMakefileGenerator3 f != files.end(); ++f) { std::string fc = this->Convert(*f,START_OUTPUT,UNCHANGED); - fout << " " << cmLocalGenerator::EscapeForCMake(fc) << "\n"; + fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n"; } fout << ")\n"; } @@ -1272,7 +1256,9 @@ cmLocalUnixMakefileGenerator3 { // Get the set of source languages in the target. std::set<std::string> languages; - target.GetLanguages(languages, + cmGeneratorTarget *gtgt = + this->GlobalGenerator->GetGeneratorTarget(&target); + gtgt->GetLanguages(languages, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); fout << "\n" << "# Per-language clean rules from dependency scanning.\n" @@ -1614,12 +1600,14 @@ cmLocalUnixMakefileGenerator3 if(const char* relativePathTopSource = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) { - this->StateSnapshot.SetRelativePathTopSource(relativePathTopSource); + this->StateSnapshot.GetDirectory() + .SetRelativePathTopSource(relativePathTopSource); } if(const char* relativePathTopBinary = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) { - this->StateSnapshot.SetRelativePathTopBinary(relativePathTopBinary); + this->StateSnapshot.GetDirectory() + .SetRelativePathTopBinary(relativePathTopBinary); } } else @@ -1845,7 +1833,6 @@ void cmLocalUnixMakefileGenerator3 std::vector<std::string> commands; // Write the all rule. - std::string dir; std::string recursiveTarget = this->Makefile->GetCurrentBinaryDirectory(); recursiveTarget += "/all"; @@ -2046,7 +2033,7 @@ void cmLocalUnixMakefileGenerator3 // Build a list of preprocessor definitions for the target. std::set<std::string> defines; this->AddCompileDefinitions(defines, &target, - this->ConfigurationName, l->first); + this->ConfigName, l->first); if(!defines.empty()) { cmakefileStream @@ -2057,7 +2044,7 @@ void cmLocalUnixMakefileGenerator3 di != defines.end(); ++di) { cmakefileStream - << " " << cmLocalGenerator::EscapeForCMake(*di) << "\n"; + << " " << cmOutputConverter::EscapeForCMake(*di) << "\n"; } cmakefileStream << " )\n"; @@ -2111,7 +2098,7 @@ void cmLocalUnixMakefileGenerator3 tri != transformRules.end(); ++tri) { cmakefileStream << " " - << cmLocalGenerator::EscapeForCMake(*tri) << "\n"; + << cmOutputConverter::EscapeForCMake(*tri) << "\n"; } cmakefileStream << " )\n"; @@ -2270,7 +2257,7 @@ cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(const char* p, std::string()); std::vector<std::string>::const_iterator compStart = components.begin() + 1; - result += cmJoin(cmRange(compStart, compEnd), slash); + result += cmJoin(cmMakeRange(compStart, compEnd), slash); // Only the last component can be empty to avoid double slashes. result += slash; result += components.back(); diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 988d660..98f15e6 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -12,7 +12,7 @@ #ifndef cmLocalUnixMakefileGenerator3_h #define cmLocalUnixMakefileGenerator3_h -#include "cmLocalGenerator.h" +#include "cmLocalCommonGenerator.h" // for cmDepends::DependencyVector #include "cmDepends.h" @@ -31,26 +31,19 @@ class cmSourceFile; * cmLocalUnixMakefileGenerator3 produces a LocalUnix makefile from its * member Makefile. */ -class cmLocalUnixMakefileGenerator3 : public cmLocalGenerator +class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator { public: - cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalUnixMakefileGenerator3(); - /** - * Process the CMakeLists files for this directory to fill in the - * Makefile ivar - */ - virtual void Configure(); + virtual void ComputeHomeRelativeOutputPath(); /** * Generate the makefile for this directory. */ virtual void Generate(); - // this returns the relative path between the HomeOutputDirectory and this // local generators StartOutputDirectory const std::string &GetHomeRelativeOutputPath(); @@ -153,9 +146,6 @@ public: void AddImplicitDepends(cmTarget const& tgt, const std::string& lang, const char* obj, const char* src); - void AppendGlobalTargetDepends(std::vector<std::string>& depends, - cmTarget& target); - // write the target rules for the local Makefile into the stream void WriteLocalAllRules(std::ostream& ruleFileStream); @@ -260,26 +250,8 @@ private: ImplicitDependTargetMap ImplicitDepends; - //========================================================================== - // Configuration settings. - int MakefileVariableSize; - std::string ConfigurationName; - bool MakeCommandEscapeTargetTwice; - bool BorlandMakeCurlyHack; - //========================================================================== - std::string HomeRelativeOutputPath; - /* Copy the setting of CMAKE_COLOR_MAKEFILE from the makefile at the - beginning of generation to avoid many duplicate lookups. */ - bool ColorMakefile; - - /* Copy the setting of CMAKE_SKIP_PREPROCESSED_SOURCE_RULES and - CMAKE_SKIP_ASSEMBLY_SOURCE_RULES at the beginning of generation to - avoid many duplicate lookups. */ - bool SkipPreprocessedSourceRules; - bool SkipAssemblySourceRules; - struct LocalObjectEntry { cmTarget* Target; @@ -308,6 +280,13 @@ private: /* does the work for each target */ std::map<std::string, std::string> MakeVariableMap; std::map<std::string, std::string> ShortMakeVariableMap; + + int MakefileVariableSize; + bool MakeCommandEscapeTargetTwice; + bool BorlandMakeCurlyHack; + bool ColorMakefile; + bool SkipPreprocessedSourceRules; + bool SkipAssemblySourceRules; }; #endif diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index ad6a020..b043b00 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -33,7 +33,7 @@ class cmVS10XMLParser : public cmXMLParser virtual void StartElement(const std::string& name, const char**) { // once the GUID is found do nothing - if(this->GUID.size()) + if(!this->GUID.empty()) { return; } @@ -62,10 +62,8 @@ class cmVS10XMLParser : public cmXMLParser //---------------------------------------------------------------------------- cmLocalVisualStudio10Generator -::cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot): - cmLocalVisualStudio7Generator(gg, parent, snapshot) +::cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, cmMakefile* mf): + cmLocalVisualStudio7Generator(gg, mf) { } @@ -107,10 +105,9 @@ void cmLocalVisualStudio10Generator cmVS10XMLParser parser; parser.ParseFile(path); - // if we can not find a GUID then create one + // if we can not find a GUID then we will generate one later if(parser.GUID.empty()) { - this->GlobalGenerator->CreateGUID(name); return; } diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index c588aaf..e187590 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -25,9 +25,7 @@ class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator { public: ///! Set cache only and recurse to false by default. - cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalVisualStudio10Generator(); diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index ad34857..cc94cd4 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -24,10 +24,8 @@ #include <cmsys/FStream.hxx> cmLocalVisualStudio6Generator -::cmLocalVisualStudio6Generator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot): - cmLocalVisualStudioGenerator(gg, parent, snapshot) +::cmLocalVisualStudio6Generator(cmGlobalGenerator* gg, cmMakefile* mf): + cmLocalVisualStudioGenerator(gg, mf) { } @@ -62,7 +60,7 @@ public: } void Write(cmCustomCommand const& cc) { - cmCustomCommandGenerator ccg(cc, this->Config, this->LG->GetMakefile()); + cmCustomCommandGenerator ccg(cc, this->Config, this->LG); if(this->First) { this->Code += this->Event + "_Cmds="; @@ -82,21 +80,14 @@ private: std::string Event; }; -void cmLocalVisualStudio6Generator::AddHelperCommands() -{ - std::set<std::string> lang; - lang.insert("C"); - lang.insert("CXX"); - this->CreateCustomTargetsAndCommands(lang); -} - void cmLocalVisualStudio6Generator::AddCMakeListsRules() { cmTargets &tgts = this->Makefile->GetTargets(); for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) { - if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY) + if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY + || l->second.GetType() == cmTarget::GLOBAL_TARGET) { continue; } @@ -235,13 +226,10 @@ void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt) comment += makefileIn; std::string args; args = "-H"; - args += this->Convert(this->Makefile->GetHomeDirectory(), - START_OUTPUT, UNCHANGED, true); + args += this->Makefile->GetHomeDirectory(); commandLine.push_back(args); args = "-B"; - args += - this->Convert(this->Makefile->GetHomeOutputDirectory(), - START_OUTPUT, UNCHANGED, true); + args += this->Makefile->GetHomeOutputDirectory(); commandLine.push_back(args); std::vector<std::string> const& listFiles = this->Makefile->GetListFiles(); @@ -315,9 +303,12 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout, // We may be modifying the source groups temporarily, so make a copy. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + // get the classes from the source lists then add them to the groups std::vector<cmSourceFile*> classes; - if (!target.GetConfigCommonSourceFiles(classes)) + if (!gt->GetConfigCommonSourceFiles(classes)) { return; } @@ -498,7 +489,7 @@ void cmLocalVisualStudio6Generator // Tell MS-Dev what the source is. If the compiler knows how to // build it, then it will. fout << "SOURCE=" << - this->ConvertToOptionallyRelativeOutputPath(source.c_str()) << "\n\n"; + this->ConvertToOutputFormat(source.c_str(), SHELL) << "\n\n"; if(!depends.empty()) { // Write out the dependencies for the rule. @@ -507,7 +498,7 @@ void cmLocalVisualStudio6Generator d != depends.end(); ++d) { fout << "\\\n\t" << - this->ConvertToOptionallyRelativeOutputPath(d->c_str()); + this->ConvertToOutputFormat(d->c_str(), SHELL); } fout << "\n"; } @@ -628,7 +619,7 @@ cmLocalVisualStudio6Generator for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i) { std::string config = this->GetConfigName(*i); - cmCustomCommandGenerator ccg(command, config, this->Makefile); + cmCustomCommandGenerator ccg(command, config, this); std::string comment = this->ConstructComment(ccg, "Building Custom Rule $(InputPath)"); if(comment == "<hack>") @@ -663,7 +654,7 @@ cmLocalVisualStudio6Generator if(this->GetRealDependency(d->c_str(), config.c_str(), dep)) { fout << "\\\n\t" << - this->ConvertToOptionallyRelativeOutputPath(dep.c_str()); + this->ConvertToOutputFormat(dep.c_str(), SHELL); } } fout << "\n"; @@ -689,7 +680,7 @@ cmLocalVisualStudio6Generator ++o) { // Write a rule for every output generated by this command. - fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str()) + fout << this->ConvertToOutputFormat(o->c_str(), SHELL) << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t"; fout << script.c_str() << "\n\n"; } @@ -906,7 +897,7 @@ cmLocalVisualStudio6Generator::GetTargetIncludeOptions(cmTarget &target, for(i = includes.begin(); i != includes.end(); ++i) { std::string tmp = - this->ConvertToOptionallyRelativeOutputPath(i->c_str()); + this->ConvertToOutputFormat(i->c_str(), SHELL); if(useShortPath) { cmSystemTools::GetShortPath(tmp.c_str(), tmp); @@ -994,17 +985,17 @@ void cmLocalVisualStudio6Generator std::string libMultiLineDebugOptions; std::string libMultiLineOptimizedOptions; - if(libPath.size()) + if(!libPath.empty()) { std::string lpath = - this->ConvertToOptionallyRelativeOutputPath(libPath.c_str()); - if(lpath.size() == 0) + this->ConvertToOutputFormat(libPath.c_str(), SHELL); + if(lpath.empty()) { lpath = "."; } std::string lpathIntDir = libPath + "$(INTDIR)"; lpathIntDir = - this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str()); + this->ConvertToOutputFormat(lpathIntDir.c_str(), SHELL); if(pathEmitted.insert(lpath).second) { libOptions += " /LIBPATH:"; @@ -1027,17 +1018,17 @@ void cmLocalVisualStudio6Generator libMultiLineOptionsForDebug += " \n"; } } - if(exePath.size()) + if(!exePath.empty()) { std::string lpath = - this->ConvertToOptionallyRelativeOutputPath(exePath.c_str()); - if(lpath.size() == 0) + this->ConvertToOutputFormat(exePath.c_str(), SHELL); + if(lpath.empty()) { lpath = "."; } std::string lpathIntDir = exePath + "$(INTDIR)"; lpathIntDir = - this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str()); + this->ConvertToOutputFormat(lpathIntDir.c_str(), SHELL); if(pathEmitted.insert(lpath).second) { @@ -1071,14 +1062,14 @@ void cmLocalVisualStudio6Generator path += "/"; } std::string lpath = - this->ConvertToOptionallyRelativeOutputPath(path.c_str()); - if(lpath.size() == 0) + this->ConvertToOutputFormat(path.c_str(), SHELL); + if(lpath.empty()) { lpath = "."; } std::string lpathIntDir = path + "$(INTDIR)"; lpathIntDir = - this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str()); + this->ConvertToOutputFormat(lpathIntDir.c_str(), SHELL); if(pathEmitted.insert(lpath).second) { libOptions += " /LIBPATH:"; @@ -1125,10 +1116,12 @@ void cmLocalVisualStudio6Generator cmTarget* tgt = this->GlobalGenerator->FindTarget(j->first.c_str()); if(tgt) { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(tgt); lib = cmSystemTools::GetFilenameWithoutExtension - (tgt->GetFullName().c_str()); + (gt->GetFullName().c_str()); libDebug = cmSystemTools::GetFilenameWithoutExtension - (tgt->GetFullName("Debug").c_str()); + (gt->GetFullName("Debug").c_str()); lib += ".lib"; libDebug += ".lib"; } @@ -1142,9 +1135,9 @@ void cmLocalVisualStudio6Generator libDebug += ".lib"; } } - lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str()); + lib = this->ConvertToOutputFormat(lib.c_str(), SHELL); libDebug = - this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str()); + this->ConvertToOutputFormat(libDebug.c_str(), SHELL); if (j->second == cmTarget::GENERAL) { @@ -1268,8 +1261,8 @@ void cmLocalVisualStudio6Generator extraLinkOptionsRelWithDebInfo += targetLinkFlags; } - - + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); // Get standard libraries for this language. if(targetBuilds) @@ -1278,10 +1271,10 @@ void cmLocalVisualStudio6Generator std::vector<std::string> configs; target.GetMakefile()->GetConfigurations(configs); std::vector<std::string>::const_iterator it = configs.begin(); - const std::string& linkLanguage = target.GetLinkerLanguage(*it); + const std::string& linkLanguage = gt->GetLinkerLanguage(*it); for ( ; it != configs.end(); ++it) { - const std::string& configLinkLanguage = target.GetLinkerLanguage(*it); + const std::string& configLinkLanguage = gt->GetLinkerLanguage(*it); if (configLinkLanguage != linkLanguage) { cmSystemTools::Error @@ -1338,11 +1331,11 @@ void cmLocalVisualStudio6Generator target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY) { - outputName = target.GetFullName(); - outputNameDebug = target.GetFullName("Debug"); - outputNameRelease = target.GetFullName("Release"); - outputNameMinSizeRel = target.GetFullName("MinSizeRel"); - outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo"); + outputName = gt->GetFullName(); + outputNameDebug = gt->GetFullName("Debug"); + outputNameRelease = gt->GetFullName("Release"); + outputNameMinSizeRel = gt->GetFullName("MinSizeRel"); + outputNameRelWithDebInfo = gt->GetFullName("RelWithDebInfo"); } else if(target.GetType() == cmTarget::OBJECT_LIBRARY) { @@ -1367,21 +1360,21 @@ void cmLocalVisualStudio6Generator { #ifdef CM_USE_OLD_VS6 outputDirOld = - removeQuotes(this->ConvertToOptionallyRelativeOutputPath - (target.GetDirectory().c_str())); + removeQuotes(this->ConvertToOutputFormat + (target.GetDirectory().c_str(), SHELL)); #endif outputDirDebug = - removeQuotes(this->ConvertToOptionallyRelativeOutputPath( - target.GetDirectory("Debug").c_str())); + removeQuotes(this->ConvertToOutputFormat( + target.GetDirectory("Debug").c_str(), SHELL)); outputDirRelease = - removeQuotes(this->ConvertToOptionallyRelativeOutputPath( - target.GetDirectory("Release").c_str())); + removeQuotes(this->ConvertToOutputFormat( + target.GetDirectory("Release").c_str(), SHELL)); outputDirMinSizeRel = - removeQuotes(this->ConvertToOptionallyRelativeOutputPath( - target.GetDirectory("MinSizeRel").c_str())); + removeQuotes(this->ConvertToOutputFormat( + target.GetDirectory("MinSizeRel").c_str(), SHELL)); outputDirRelWithDebInfo = - removeQuotes(this->ConvertToOptionallyRelativeOutputPath( - target.GetDirectory("RelWithDebInfo").c_str())); + removeQuotes(this->ConvertToOutputFormat( + target.GetDirectory("RelWithDebInfo").c_str(), SHELL)); } else if(target.GetType() == cmTarget::OBJECT_LIBRARY) { @@ -1439,30 +1432,28 @@ void cmLocalVisualStudio6Generator fullPathImpRelease += "/"; fullPathImpMinSizeRel += "/"; fullPathImpRelWithDebInfo += "/"; - fullPathImpDebug += target.GetFullName("Debug", true); - fullPathImpRelease += target.GetFullName("Release", true); - fullPathImpMinSizeRel += target.GetFullName("MinSizeRel", true); - fullPathImpRelWithDebInfo += target.GetFullName("RelWithDebInfo", true); + fullPathImpDebug += gt->GetFullName("Debug", true); + fullPathImpRelease += gt->GetFullName("Release", true); + fullPathImpMinSizeRel += gt->GetFullName("MinSizeRel", true); + fullPathImpRelWithDebInfo += gt->GetFullName("RelWithDebInfo", true); targetImplibFlagDebug = "/implib:"; targetImplibFlagRelease = "/implib:"; targetImplibFlagMinSizeRel = "/implib:"; targetImplibFlagRelWithDebInfo = "/implib:"; targetImplibFlagDebug += - this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug.c_str()); + this->ConvertToOutputFormat(fullPathImpDebug.c_str(), SHELL); targetImplibFlagRelease += - this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease.c_str()); + this->ConvertToOutputFormat(fullPathImpRelease.c_str(), SHELL); targetImplibFlagMinSizeRel += - this->ConvertToOptionallyRelativeOutputPath( - fullPathImpMinSizeRel.c_str()); + this->ConvertToOutputFormat(fullPathImpMinSizeRel.c_str(), SHELL); targetImplibFlagRelWithDebInfo += - this->ConvertToOptionallyRelativeOutputPath( - fullPathImpRelWithDebInfo.c_str()); + this->ConvertToOutputFormat(fullPathImpRelWithDebInfo.c_str(), SHELL); } #ifdef CM_USE_OLD_VS6 // Compute link information for the target. - if(extraLinkOptions.size()) + if(!extraLinkOptions.empty()) { libOptions += " "; libOptions += extraLinkOptions; @@ -1553,7 +1544,7 @@ void cmLocalVisualStudio6Generator std::string line; std::string libnameExports; - if(exportSymbol.size()) + if(!exportSymbol.empty()) { libnameExports = "/D \""; libnameExports += exportSymbol; @@ -1669,12 +1660,12 @@ void cmLocalVisualStudio6Generator // to convert to output path for unix to win32 conversion cmSystemTools::ReplaceString (line, "LIBRARY_OUTPUT_PATH", - removeQuotes(this->ConvertToOptionallyRelativeOutputPath - (libPath.c_str())).c_str()); + removeQuotes(this->ConvertToOutputFormat + (libPath.c_str(), SHELL)).c_str()); cmSystemTools::ReplaceString (line, "EXECUTABLE_OUTPUT_PATH", - removeQuotes(this->ConvertToOptionallyRelativeOutputPath - (exePath.c_str())).c_str()); + removeQuotes(this->ConvertToOutputFormat + (exePath.c_str(), SHELL)).c_str()); #endif if(targetBuilds || target.GetType() == cmTarget::OBJECT_LIBRARY) @@ -1713,10 +1704,10 @@ void cmLocalVisualStudio6Generator std::vector<std::string> configs; target.GetMakefile()->GetConfigurations(configs); std::vector<std::string>::const_iterator it = configs.begin(); - const std::string& linkLanguage = target.GetLinkerLanguage(*it); + const std::string& linkLanguage = gt->GetLinkerLanguage(*it); for ( ; it != configs.end(); ++it) { - const std::string& configLinkLanguage = target.GetLinkerLanguage(*it); + const std::string& configLinkLanguage = gt->GetLinkerLanguage(*it); if (configLinkLanguage != linkLanguage) { cmSystemTools::Error @@ -1858,8 +1849,10 @@ void cmLocalVisualStudio6Generator const std::string extraOptions, std::string& options) { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); // Compute the link information for this configuration. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1884,9 +1877,9 @@ void cmLocalVisualStudio6Generator } dir += "$(IntDir)"; options += "# ADD LINK32 /LIBPATH:"; - options += this->ConvertToOptionallyRelativeOutputPath(dir.c_str()); + options += this->ConvertToOutputFormat(dir.c_str(), SHELL); options += " /LIBPATH:"; - options += this->ConvertToOptionallyRelativeOutputPath(d->c_str()); + options += this->ConvertToOutputFormat(d->c_str(), SHELL); options += "\n"; } } @@ -1897,7 +1890,7 @@ void cmLocalVisualStudio6Generator if(l->IsPath) { options += - this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str()); + this->ConvertToOutputFormat(l->Value.c_str(), SHELL); } else if (!l->Target || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY) @@ -1933,7 +1926,7 @@ void cmLocalVisualStudio6Generator options += "# ADD "; options += tool; options += "32 "; - options += this->ConvertToOptionallyRelativeOutputPath(oi->c_str()); + options += this->ConvertToOutputFormat(oi->c_str(), SHELL); options += "\n"; } } diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index 8f4d521..828d252 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -29,13 +29,10 @@ class cmLocalVisualStudio6Generator : public cmLocalVisualStudioGenerator { public: ///! Set cache only and recurse to false by default. - cmLocalVisualStudio6Generator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalVisualStudio6Generator(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalVisualStudio6Generator(); - virtual void AddHelperCommands(); virtual void AddCMakeListsRules(); /** diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 9c031cf..cf67251 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -23,8 +23,6 @@ #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" -#include <cmsys/System.h> - #include <ctype.h> // for isspace static bool cmLVS6G_IsFAT(const char* dir); @@ -55,10 +53,8 @@ static void cmConvertToWindowsSlash(std::string& s) //---------------------------------------------------------------------------- cmLocalVisualStudio7Generator -::cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot): - cmLocalVisualStudioGenerator(gg, parent, snapshot) +::cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, cmMakefile* mf): + cmLocalVisualStudioGenerator(gg, mf) { this->Internal = new cmLocalVisualStudio7GeneratorInternals(this); } @@ -70,20 +66,9 @@ cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() void cmLocalVisualStudio7Generator::AddHelperCommands() { - std::set<std::string> lang; - lang.insert("C"); - lang.insert("CXX"); - lang.insert("RC"); - lang.insert("IDL"); - lang.insert("DEF"); - lang.insert("Fortran"); - this->CreateCustomTargetsAndCommands(lang); - // Now create GUIDs for targets cmTargets &tgts = this->Makefile->GetTargets(); - cmGlobalVisualStudio7Generator* gg = - static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) { if(l->second.GetType() == cmTarget::INTERFACE_LIBRARY) @@ -96,10 +81,6 @@ void cmLocalVisualStudio7Generator::AddHelperCommands() this->ReadAndStoreExternalGUID( l->second.GetName().c_str(), path); } - else - { - gg->CreateGUID(l->first.c_str()); - } } @@ -125,6 +106,10 @@ void cmLocalVisualStudio7Generator::AddCMakeListsRules() // Add the rule to targets that need it. for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l) { + if (l->second.GetType() == cmTarget::GLOBAL_TARGET) + { + continue; + } if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { l->second.AddSource(sf->GetFullPath()); @@ -305,13 +290,10 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() comment += makefileIn; std::string args; args = "-H"; - args += this->Convert(this->Makefile->GetHomeDirectory(), - START_OUTPUT, UNCHANGED, true); + args += this->Makefile->GetHomeDirectory(); commandLine.push_back(args); args = "-B"; - args += - this->Convert(this->Makefile->GetHomeOutputDirectory(), - START_OUTPUT, UNCHANGED, true); + args += this->Makefile->GetHomeOutputDirectory(); commandLine.push_back(args); commandLine.push_back("--check-stamp-file"); std::string stampFilename = this->Convert(stampName.c_str(), FULL, @@ -630,7 +612,7 @@ public: } void Write(cmCustomCommand const& cc) { - cmCustomCommandGenerator ccg(cc, this->Config, this->LG->GetMakefile()); + cmCustomCommandGenerator ccg(cc, this->Config, this->LG); if(this->First) { const char* comment = ccg.GetComment(); @@ -680,6 +662,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, const char* configType = "10"; const char* projectType = 0; bool targetBuilds = true; + + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + switch(target.GetType()) { case cmTarget::OBJECT_LIBRARY: @@ -712,7 +698,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, { const std::string& linkLanguage = (this->FortranProject? std::string("Fortran"): - target.GetLinkerLanguage(configName)); + gt->GetLinkerLanguage(configName)); if(linkLanguage.empty()) { cmSystemTools::Error @@ -774,10 +760,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.Parse(flags.c_str()); targetOptions.Parse(defineFlags.c_str()); targetOptions.ParseFinish(); - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); std::vector<std::string> targetDefines; - target.GetCompileDefinitions(targetDefines, configName, "CXX"); + gt->GetCompileDefinitions(targetDefines, configName, "CXX"); targetOptions.AddDefines(targetDefines); targetOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); @@ -819,7 +803,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, if (this->FortranProject) { // Intel Fortran >= 15.0 uses TargetName property. - std::string targetNameFull = target.GetFullName(configName); + std::string targetNameFull = gt->GetFullName(configName); std::string targetName = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); std::string targetExt = @@ -897,7 +881,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, if(target.GetType() <= cmTarget::OBJECT_LIBRARY) { // Specify the compiler program database file if configured. - std::string pdb = target.GetCompilePDBPath(configName); + std::string pdb = gt->GetCompilePDBPath(configName); if(!pdb.empty()) { fout << "\t\t\t\tProgramDataBaseFileName=\"" @@ -1087,9 +1071,20 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, if(!this->ModuleDefinitionFile.empty()) { std::string defFile = - this->ConvertToOptionallyRelativeOutputPath(this->ModuleDefinitionFile); + this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def"); + } + } switch(target.GetType()) { case cmTarget::UNKNOWN_LIBRARY: @@ -1112,7 +1107,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, } case cmTarget::STATIC_LIBRARY: { - std::string targetNameFull = target.GetFullName(configName); + std::string targetNameFull = gt->GetFullName(configName); std::string libpath = target.GetDirectory(configName); libpath += "/"; libpath += targetNameFull; @@ -1152,11 +1147,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, std::string targetNameFull; std::string targetNameImport; std::string targetNamePDB; - target.GetLibraryNames(targetName, targetNameSO, targetNameFull, + gt->GetLibraryNames(targetName, targetNameSO, targetNameFull, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1249,11 +1244,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, std::string targetNameFull; std::string targetNameImport; std::string targetNamePDB; - target.GetExecutableNames(targetName, targetNameFull, + gt->GetExecutableNames(targetName, targetNameFull, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1472,10 +1467,13 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // We may be modifying the source groups temporarily, so make a copy. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + // get the classes from the source lists then add them to the groups this->ModuleDefinitionFile = ""; std::vector<cmSourceFile*> classes; - if (!target.GetConfigCommonSourceFiles(classes)) + if (!gt->GetConfigCommonSourceFiles(classes)) { return; } @@ -1517,8 +1515,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, { // VS >= 8 support per-config source locations so we // list object library content as external objects. - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); std::vector<std::string> objs; gt->UseObjectLibraries(objs, ""); if(!objs.empty()) @@ -1640,7 +1636,7 @@ cmLocalVisualStudio7GeneratorFCInfo lg->GlobalGenerator->GetLanguageFromExtension (sf.GetExtension().c_str()); const std::string& sourceLang = lg->GetSourceFileLanguage(sf); - const std::string& linkLanguage = target.GetLinkerLanguage(i->c_str()); + const std::string& linkLanguage = gt->GetLinkerLanguage(i->c_str()); bool needForceLang = false; // source file does not match its extension language if(lang != sourceLang) @@ -1906,7 +1902,7 @@ WriteCustomRule(std::ostream& fout, for (std::vector<std::string>::const_iterator i = configs.begin(); i != configs.end(); ++i) { - cmCustomCommandGenerator ccg(command, *i, this->Makefile); + cmCustomCommandGenerator ccg(command, *i, this); cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i]; fout << "\t\t\t\t<FileConfiguration\n"; fout << "\t\t\t\t\tName=\"" << *i << "|" @@ -2024,7 +2020,28 @@ void cmLocalVisualStudio7Generator // Add pre-link event. tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool"; event.Start(tool); - event.Write(target.GetPreLinkCommands()); + bool addedPrelink = false; + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + addedPrelink = true; + std::vector<cmCustomCommand> commands = + target.GetPreLinkCommands(); + cmGlobalVisualStudioGenerator* gg + = static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + gg->AddSymbolExportCommand( + gt, commands, configName); + event.Write(commands); + } + } + if (!addedPrelink) + { + event.Write(target.GetPreLinkCommands()); + } cmsys::auto_ptr<cmCustomCommand> pcc( this->MaybeCreateImplibDir(target, configName, this->FortranProject)); if(pcc.get()) @@ -2234,7 +2251,7 @@ std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s) std::string cmLocalVisualStudio7Generator ::ConvertToXMLOutputPath(const char* path) { - std::string ret = this->ConvertToOptionallyRelativeOutputPath(path); + std::string ret = this->ConvertToOutputFormat(path, SHELL); cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "\"", """); cmSystemTools::ReplaceString(ret, "<", "<"); @@ -2245,7 +2262,7 @@ std::string cmLocalVisualStudio7Generator std::string cmLocalVisualStudio7Generator ::ConvertToXMLOutputPathSingle(const char* path) { - std::string ret = this->ConvertToOptionallyRelativeOutputPath(path); + std::string ret = this->ConvertToOutputFormat(path, SHELL); cmSystemTools::ReplaceString(ret, "\"", ""); cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "<", "<"); @@ -2265,7 +2282,7 @@ public: virtual void StartElement(const std::string& name, const char** atts) { // once the GUID is found do nothing - if(this->GUID.size()) + if(!this->GUID.empty()) { return; } @@ -2312,12 +2329,9 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( { cmVS7XMLParser parser; parser.ParseFile(path); - // if we can not find a GUID then create one - if(parser.GUID.size() == 0) + // if we can not find a GUID then we will generate one later + if(parser.GUID.empty()) { - cmGlobalVisualStudio7Generator* gg = - static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); - gg->CreateGUID(name); return; } std::string guidStoreName = name; diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 43f3af9..bc05a06 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -35,9 +35,7 @@ class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator { public: ///! Set cache only and recurse to false by default. - cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalVisualStudio7Generator(); diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index ca72939..c0072de 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -19,10 +19,8 @@ //---------------------------------------------------------------------------- cmLocalVisualStudioGenerator -::cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot) - : cmLocalGenerator(gg, parent, snapshot) +::cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, cmMakefile* mf) + : cmLocalGenerator(gg, mf) { } @@ -57,7 +55,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames( cmSourceFile const* sf = si->first; std::string objectNameLower = cmSystemTools::LowerCase( cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); - objectNameLower += ".obj"; + objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf); counts[objectNameLower] += 1; } @@ -70,7 +68,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames( cmSourceFile const* sf = si->first; std::string objectName = cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); - objectName += ".obj"; + objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf); if(counts[cmSystemTools::LowerCase(objectName)] > 1) { const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf); diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index d414651..071bfb3 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -31,9 +31,7 @@ class cmCustomCommandGenerator; class cmLocalVisualStudioGenerator : public cmLocalGenerator { public: - cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, cmMakefile* mf); virtual ~cmLocalVisualStudioGenerator(); /** Construct a script from the given list of command lines. */ diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 804dd7d..b19112d 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -16,9 +16,8 @@ //---------------------------------------------------------------------------- cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg, - cmLocalGenerator* parent, - cmState::Snapshot snapshot) - : cmLocalGenerator(gg, parent, snapshot) + cmMakefile* mf) + : cmLocalGenerator(gg, mf) { // the global generator does this, so do not // put these flags into the language flags diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index 26fff9c..6d0926f 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -24,8 +24,8 @@ class cmLocalXCodeGenerator : public cmLocalGenerator { public: ///! Set cache only and recurse to false by default. - cmLocalXCodeGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, - cmState::Snapshot snapshot); + cmLocalXCodeGenerator(cmGlobalGenerator* gg, + cmMakefile* mf); virtual ~cmLocalXCodeGenerator(); virtual std::string GetTargetDirectory(cmTarget const& target) const; diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 7ac4432..e4026b0 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -96,12 +96,9 @@ bool cmMacroHelperCommand::InvokeInitialPass return false; } - // Enforce matching logical blocks inside the macro. - cmMakefile::LexicalPushPop lexScope(this->Makefile); - - // Push a weak policy scope which restores the policies recorded at - // macro creation. - cmMakefile::PolicyPushPop polScope(this->Makefile, true, this->Policies); + cmMakefile::MacroPushPop macroScope(this->Makefile, + this->FilePath, + this->Policies); // set the value of argc std::ostringstream argcDefStream; @@ -110,7 +107,7 @@ bool cmMacroHelperCommand::InvokeInitialPass std::vector<std::string>::const_iterator eit = expandedArgs.begin() + (this->Args.size() - 1); - std::string expandedArgn = cmJoin(cmRange(eit, expandedArgs.end()), ";"); + std::string expandedArgn = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); std::string expandedArgv = cmJoin(expandedArgs, ";"); std::vector<std::string> variables; variables.reserve(this->Args.size() - 1); @@ -126,10 +123,6 @@ bool cmMacroHelperCommand::InvokeInitialPass sprintf(argvName,"${ARGV%i}",j); argVs.push_back(argvName); } - if(!this->Functions.empty()) - { - this->FilePath = this->Functions[0].FilePath; - } // Invoke all the functions that were collected in the block. cmListFileFunction newLFF; // for each function @@ -139,7 +132,6 @@ bool cmMacroHelperCommand::InvokeInitialPass newLFF.Arguments.clear(); newLFF.Arguments.reserve(this->Functions[c].Arguments.size()); newLFF.Name = this->Functions[c].Name; - newLFF.FilePath = this->Functions[c].FilePath; newLFF.Line = this->Functions[c].Line; // for each argument of the current function @@ -147,10 +139,6 @@ bool cmMacroHelperCommand::InvokeInitialPass this->Functions[c].Arguments.begin(); k != this->Functions[c].Arguments.end(); ++k) { - // Set the FilePath on the arguments to match the function since it is - // not stored and the original values may be freed - k->FilePath = this->FilePath.c_str(); - cmListFileArgument arg; arg.Value = k->Value; if(k->Delim != cmListFileArgument::Bracket) @@ -181,7 +169,6 @@ bool cmMacroHelperCommand::InvokeInitialPass } } arg.Delim = k->Delim; - arg.FilePath = k->FilePath; arg.Line = k->Line; newLFF.Arguments.push_back(arg); } @@ -191,8 +178,7 @@ bool cmMacroHelperCommand::InvokeInitialPass { // The error message should have already included the call stack // so we do not need to report an error here. - lexScope.Quiet(); - polScope.Quiet(); + macroScope.Quiet(); inStatus.SetNestedError(true); return false; } @@ -225,11 +211,12 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, // if this is the endmacro for this macro then execute if (!this->Depth) { - mf.AddMacro(this->Args[0].c_str()); + mf.AppendProperty("MACROS", this->Args[0].c_str()); // create a new command and add it to cmake cmMacroHelperCommand *f = new cmMacroHelperCommand(); f->Args = this->Args; f->Functions = this->Functions; + f->FilePath = this->GetStartingContext().FilePath; mf.RecordPolicies(f->Policies); std::string newName = "_" + this->Args[0]; mf.GetState()->RenameCommand(this->Args[0], newName); @@ -259,7 +246,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf) if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endmacro")) { std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments); + mf.ExpandArguments(lff.Arguments, expandedArguments, + this->GetStartingContext().FilePath.c_str()); // if the endmacro has arguments make sure they // match the arguments of the macro if ((expandedArguments.empty() || diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx index a6d4e58..cbc7e02 100644 --- a/Source/cmMakeDepend.cxx +++ b/Source/cmMakeDepend.cxx @@ -49,7 +49,7 @@ void cmMakeDepend::SetMakefile(cmMakefile* makefile) // Now extract the include file regular expression from the makefile. this->IncludeFileRegularExpression.compile( - this->Makefile->IncludeFileRegularExpression.c_str()); + this->Makefile->GetIncludeRegularExpression()); this->ComplainFileRegularExpression.compile( this->Makefile->ComplainFileRegularExpression.c_str()); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bdc55f2..8a3d197 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -16,10 +16,11 @@ #include "cmSourceFileLocation.h" #include "cmSystemTools.h" #include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" #include "cmCommands.h" #include "cmState.h" +#include "cmOutputConverter.h" #include "cmFunctionBlocker.h" +#include "cmGeneratorExpressionEvaluationFile.h" #include "cmListFileCache.h" #include "cmCommandArgumentParserHelper.h" #include "cmGeneratorExpression.h" @@ -29,7 +30,6 @@ #endif #include "cmInstallGenerator.h" #include "cmTestGenerator.h" -#include "cmDefinitions.h" #include "cmAlgorithms.h" #include "cmake.h" #include <stdlib.h> // required for atoi @@ -42,115 +42,23 @@ #include <ctype.h> // for isspace #include <assert.h> -class cmMakefile::Internals -{ -public: - std::list<cmDefinitions> VarStack; - bool IsSourceFileTryCompile; - - void PushDefinitions() - { - this->VarStack.push_back(cmDefinitions()); - } - - void InitializeDefinitions(cmMakefile* parent) - { - this->VarStack.back() = - cmDefinitions::MakeClosure(parent->Internal->VarStack.rbegin(), - parent->Internal->VarStack.rend()); - } - - const char* GetDefinition(std::string const& name) - { - return cmDefinitions::Get(name, this->VarStack.rbegin(), - this->VarStack.rend()); - } - - bool IsInitialized(std::string const& name) - { - return cmDefinitions::HasKey(name, this->VarStack.rbegin(), - this->VarStack.rend()); - } - - void SetDefinition(std::string const& name, std::string const& value) - { - this->VarStack.back().Set(name, value.c_str()); - } - - void RemoveDefinition(std::string const& name) - { - this->VarStack.back().Set(name, 0); - } - - std::vector<std::string> UnusedKeys() const - { - return this->VarStack.back().UnusedKeys(); - } - - std::vector<std::string> ClosureKeys() const - { - return cmDefinitions::ClosureKeys(this->VarStack.rbegin(), - this->VarStack.rend()); - } - - void PopDefinitions() - { - this->VarStack.pop_back(); - } - - bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) - { - std::list<cmDefinitions>::reverse_iterator it = this->VarStack.rbegin(); - assert(it != this->VarStack.rend()); - ++it; - if(it == this->VarStack.rend()) - { - cmLocalGenerator* plg = mf->GetLocalGenerator()->GetParent(); - if(!plg) - { - return false; - } - // Update the definition in the parent directory top scope. This - // directory's scope was initialized by the closure of the parent - // scope, so we do not need to localize the definition first. - cmMakefile* parent = plg->GetMakefile(); - if (varDef) - { - parent->AddDefinition(var, varDef); - } - else - { - parent->RemoveDefinition(var); - } - return true; - } - // First localize the definition in the current scope. - cmDefinitions::Raise(var, this->VarStack.rbegin(), this->VarStack.rend()); - - // Now update the definition in the parent scope. - it->Set(var, varDef); - return true; - } -}; - // default is not to be building executables -cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) - : Internal(new Internals), - LocalGenerator(localGenerator), - StateSnapshot(localGenerator->GetStateSnapshot()) +cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, + cmState::Snapshot const& snapshot) + : GlobalGenerator(globalGenerator), + StateSnapshot(snapshot) { - this->Internal->PushDefinitions(); - this->Internal->IsSourceFileTryCompile = false; + this->IsSourceFileTryCompile = false; // Initialize these first since AddDefaultDefinitions calls AddDefinition this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars(); - this->GeneratingBuildSystem = false; + this->Configured = false; this->SuppressWatches = false; // Setup the default include file regular expression (match everything). - this->IncludeFileRegularExpression = "^.*$"; + this->SetProperty("INCLUDE_REGULAR_EXPRESSION", "^.*$"); // Setup the default include complaint regular expression (match nothing). this->ComplainFileRegularExpression = "^$"; // Source and header file extensions that we can handle @@ -188,12 +96,12 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) this->cmAtVarRegex.compile("(@[A-Za-z_0-9/.+-]+@)"); this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{"); + this->StateSnapshot = this->StateSnapshot.GetState() + ->CreatePolicyScopeSnapshot(this->StateSnapshot); + // Enter a policy level for this directory. this->PushPolicy(); - // Protect the directory-level policies. - this->PushPolicyBarrier(); - // push empty loop block this->PushLoopBlockBarrier(); @@ -213,8 +121,6 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$"); #endif - this->Properties.SetCMakeInstance(this->GetCMakeInstance()); - { const char* dir = this->GetCMakeInstance()->GetHomeDirectory(); this->AddDefinition("CMAKE_SOURCE_DIR", dir); @@ -236,12 +142,10 @@ cmMakefile::~cmMakefile() cmDeleteAll(this->ImportedTargetsOwned); cmDeleteAll(this->FinalPassCommands); cmDeleteAll(this->FunctionBlockers); + cmDeleteAll(this->EvaluationFiles); + this->EvaluationFiles.clear(); + this->FunctionBlockers.clear(); - if (this->PolicyStack.size() != 1) - { - cmSystemTools::Error("Internal CMake Error, Policy Stack has not been" - " popped properly"); - } } //---------------------------------------------------------------------------- @@ -249,11 +153,11 @@ void cmMakefile::IssueMessage(cmake::MessageType t, std::string const& text) const { // Collect context information. - if(!this->CallStack.empty()) + if(!this->ExecutionStatusStack.empty()) { if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) { - this->CallStack.back().Status->SetNestedError(true); + this->ExecutionStatusStack.back()->SetNestedError(true); } this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); } @@ -262,46 +166,99 @@ void cmMakefile::IssueMessage(cmake::MessageType t, cmListFileContext lfc; // We are not currently executing a command. Add whatever context // information we have. - lfc.FilePath = this->ListFileStack.back(); + lfc.FilePath = this->GetExecutionFilePath(); if(!this->GetCMakeInstance()->GetIsInTryCompile()) { - lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath, - cmLocalGenerator::HOME); + cmOutputConverter converter(this->StateSnapshot); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); } lfc.Line = 0; this->GetCMakeInstance()->IssueMessage(t, text, lfc); } } +cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const +{ + return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries(); +} + +cmBacktraceRange cmMakefile::GetIncludeDirectoriesBacktraces() const +{ + return this->StateSnapshot.GetDirectory() + .GetIncludeDirectoriesEntryBacktraces(); +} + +cmStringRange cmMakefile::GetCompileOptionsEntries() const +{ + return this->StateSnapshot.GetDirectory().GetCompileOptionsEntries(); +} + +cmBacktraceRange cmMakefile::GetCompileOptionsBacktraces() const +{ + return this->StateSnapshot.GetDirectory().GetCompileOptionsEntryBacktraces(); +} + +cmStringRange cmMakefile::GetCompileDefinitionsEntries() const +{ + return this->StateSnapshot.GetDirectory().GetCompileDefinitionsEntries(); +} + +cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const +{ + return this->StateSnapshot.GetDirectory() + .GetCompileDefinitionsEntryBacktraces(); +} + //---------------------------------------------------------------------------- cmListFileBacktrace cmMakefile::GetBacktrace() const { - cmListFileBacktrace backtrace(this->GetLocalGenerator()); - for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin(); - i != this->CallStack.rend(); ++i) + cmListFileBacktrace backtrace; + if (!this->ContextStack.empty()) { - backtrace.Append(*i->Context); + backtrace = cmListFileBacktrace(this->StateSnapshot, + *this->ContextStack.back()); } return backtrace; } //---------------------------------------------------------------------------- +cmListFileBacktrace +cmMakefile::GetBacktrace(cmCommandContext const& cc) const +{ + cmState::Snapshot snp = this->StateSnapshot; + return cmListFileBacktrace(snp, cc); +} + +//---------------------------------------------------------------------------- cmListFileContext cmMakefile::GetExecutionContext() const { - return *this->CallStack.back().Context; + return cmListFileContext::FromCommandContext( + *this->ContextStack.back(), + this->StateSnapshot.GetExecutionListFile()); } //---------------------------------------------------------------------------- void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const { std::ostringstream msg; - msg << lff.FilePath << "(" << lff.Line << "): "; + msg << this->GetExecutionFilePath() << "(" << lff.Line << "): "; msg << lff.Name << "("; + bool expand = this->GetCMakeInstance()->GetTraceExpand(); + std::string temp; for(std::vector<cmListFileArgument>::const_iterator i = lff.Arguments.begin(); i != lff.Arguments.end(); ++i) { - msg << i->Value; + if (expand) + { + temp = i->Value; + this->ExpandVariablesInString(temp); + msg << temp; + } + else + { + msg << i->Value; + } msg << " "; } msg << ")"; @@ -397,12 +354,12 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, class cmMakefile::IncludeScope { public: - IncludeScope(cmMakefile* mf, const char* fname, bool noPolicyScope); + IncludeScope(cmMakefile* mf, std::string const& filenametoread, + bool noPolicyScope); ~IncludeScope(); void Quiet() { this->ReportError = false; } private: cmMakefile* Makefile; - const char* File; bool NoPolicyScope; bool CheckCMP0011; bool ReportError; @@ -410,11 +367,20 @@ private: }; //---------------------------------------------------------------------------- -cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, const char* fname, +cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, + std::string const& filenametoread, bool noPolicyScope): - Makefile(mf), File(fname), NoPolicyScope(noPolicyScope), + Makefile(mf), NoPolicyScope(noPolicyScope), CheckCMP0011(false), ReportError(true) { + this->Makefile->PushFunctionBlockerBarrier(); + + this->Makefile->StateSnapshot = + this->Makefile->GetState()->CreateCallStackSnapshot( + this->Makefile->StateSnapshot, + this->Makefile->ContextStack.back()->Name, + this->Makefile->ContextStack.back()->Line, + filenametoread); if(!this->NoPolicyScope) { // Check CMP0011 to determine the policy scope type. @@ -443,24 +409,19 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, const char* fname, break; } } - - // The included file cannot pop our policy scope. - this->Makefile->PushPolicyBarrier(); } //---------------------------------------------------------------------------- cmMakefile::IncludeScope::~IncludeScope() { - // Enforce matching policy scopes inside the included file. - this->Makefile->PopPolicyBarrier(this->ReportError); - if(!this->NoPolicyScope) { // If we need to enforce policy CMP0011 then the top entry is the // one we pushed above. If the entry is empty, then the included // script did not set any policies that might affect the includer so // we do not need to enforce the policy. - if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().IsEmpty()) + if(this->CheckCMP0011 + && !this->Makefile->StateSnapshot.HasDefinedPolicyCMP0011()) { this->CheckCMP0011 = false; } @@ -475,6 +436,9 @@ cmMakefile::IncludeScope::~IncludeScope() this->EnforceCMP0011(); } } + this->Makefile->PopPolicyBarrier(this->ReportError); + + this->Makefile->PopFunctionBlockerBarrier(this->ReportError); } //---------------------------------------------------------------------------- @@ -489,7 +453,8 @@ void cmMakefile::IncludeScope::EnforceCMP0011() { std::ostringstream w; w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n" - << "The included script\n " << this->File << "\n" + << "The included script\n " + << this->Makefile->GetExecutionFilePath() << "\n" << "affects policy settings. " << "CMake is implying the NO_POLICY_SCOPE option for compatibility, " << "so the effects are applied to the including context."; @@ -501,7 +466,8 @@ void cmMakefile::IncludeScope::EnforceCMP0011() { std::ostringstream e; e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n" - << "The included script\n " << this->File << "\n" + << "The included script\n " + << this->Makefile->GetExecutionFilePath() << "\n" << "affects policy settings, so it requires this policy to be set."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } @@ -515,38 +481,116 @@ void cmMakefile::IncludeScope::EnforceCMP0011() } } -bool cmMakefile::ProcessBuildsystemFile(const char* listfile) +class cmParseFileScope { - this->AddDefinition("CMAKE_PARENT_LIST_FILE", listfile); - std::string curSrc = this->GetCurrentSourceDirectory(); - return this->ReadListFile(listfile, true, - curSrc == this->GetHomeDirectory()); -} +public: + cmParseFileScope(cmMakefile* mf) + : Makefile(mf) + { + this->Makefile->ContextStack.push_back(&this->Context); + } + + ~cmParseFileScope() + { + this->Makefile->ContextStack.pop_back(); + } + +private: + cmMakefile* Makefile; + cmCommandContext Context; +}; -bool cmMakefile::ReadDependentFile(const char* listfile, bool noPolicyScope) +bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope) { this->AddDefinition("CMAKE_PARENT_LIST_FILE", this->GetDefinition("CMAKE_CURRENT_LIST_FILE")); - bool result = this->ReadListFile(listfile, noPolicyScope, false); - this->ListFileStack.pop_back(); - return result; + std::string filenametoread = + cmSystemTools::CollapseFullPath(filename, + this->GetCurrentSourceDirectory()); + + IncludeScope incScope(this, filenametoread, noPolicyScope); + + cmListFile listFile; + { + cmParseFileScope pfs(this); + if (!listFile.ParseFile(filenametoread.c_str(), false, this)) + { + return false; + } + } + + this->ReadListFile(listFile, filenametoread); + if(cmSystemTools::GetFatalErrorOccured()) + { + incScope.Quiet(); + } + return true; } -bool cmMakefile::ReadListFile(const char* listfile) +class cmMakefile::ListFileScope { - bool result = this->ReadListFile(listfile, true, false); - this->ListFileStack.pop_back(); - return result; -} +public: + ListFileScope(cmMakefile* mf, std::string const& filenametoread) + : Makefile(mf), ReportError(true) + { + long line = 0; + std::string name; + if (!this->Makefile->ContextStack.empty()) + { + line = this->Makefile->ContextStack.back()->Line; + name = this->Makefile->ContextStack.back()->Name; + } + this->Makefile->StateSnapshot = + this->Makefile->GetState()->CreateInlineListFileSnapshot( + this->Makefile->StateSnapshot, name, line, filenametoread); + assert(this->Makefile->StateSnapshot.IsValid()); + + this->Makefile->PushFunctionBlockerBarrier(); + } + + ~ListFileScope() + { + this->Makefile->PopPolicyBarrier(this->ReportError); + this->Makefile->PopFunctionBlockerBarrier(this->ReportError); + } + + void Quiet() { this->ReportError = false; } +private: + cmMakefile* Makefile; + bool ReportError; +}; -bool cmMakefile::ReadListFile(const char* listfile, - bool noPolicyScope, - bool requireProjectCommand) +bool cmMakefile::ReadListFile(const char* filename) { std::string filenametoread = - cmSystemTools::CollapseFullPath(listfile, + cmSystemTools::CollapseFullPath(filename, this->GetCurrentSourceDirectory()); + ListFileScope scope(this, filenametoread); + + cmListFile listFile; + { + cmParseFileScope pfs(this); + if (!listFile.ParseFile(filenametoread.c_str(), false, this)) + { + return false; + } + } + + this->ReadListFile(listFile, filenametoread); + if(cmSystemTools::GetFatalErrorOccured()) + { + scope.Quiet(); + } + return true; +} + +void cmMakefile::ReadListFile(cmListFile const& listFile, + std::string const& filenametoread) +{ + // add this list file to the list of dependencies + this->ListFiles.push_back(filenametoread); + std::string currentParentFile = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE"); std::string currentFile @@ -560,55 +604,14 @@ bool cmMakefile::ReadListFile(const char* listfile, this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR"); - this->ListFileStack.push_back(filenametoread); - - bool res = this->ReadListFileInternal(filenametoread.c_str(), - noPolicyScope, requireProjectCommand); - - this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str()); - this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str()); - this->AddDefinition("CMAKE_CURRENT_LIST_DIR", - cmSystemTools::GetFilenamePath(currentFile).c_str()); - this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE"); - this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); - this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR"); - - if (res) - { - this->CheckForUnusedVariables(); - } - - return res; -} - -bool cmMakefile::ReadListFileInternal(const char* filenametoread, - bool noPolicyScope, - bool requireProjectCommand) -{ - cmListFile cacheFile; - if( !cacheFile.ParseFile(filenametoread, requireProjectCommand, this) ) - { - return false; - } - // add this list file to the list of dependencies - this->ListFiles.push_back( filenametoread); - - // Enforce balanced blocks (if/endif, function/endfunction, etc.). - { - LexicalPushPop lexScope(this); - IncludeScope incScope(this, filenametoread, noPolicyScope); - // Run the parsed commands. - const size_t numberFunctions = cacheFile.Functions.size(); + const size_t numberFunctions = listFile.Functions.size(); for(size_t i =0; i < numberFunctions; ++i) { cmExecutionStatus status; - this->ExecuteCommand(cacheFile.Functions[i],status); + this->ExecuteCommand(listFile.Functions[i],status); if(cmSystemTools::GetFatalErrorOccured()) { - // Exit early due to error. - lexScope.Quiet(); - incScope.Quiet(); break; } if(status.GetReturnInvoked()) @@ -617,16 +620,15 @@ bool cmMakefile::ReadListFileInternal(const char* filenametoread, break; } } - } - - // If this is the directory-level CMakeLists.txt file then perform - // some extra checks. - if(this->ListFileStack.size() == 1) - { - this->EnforceDirectoryLevelRules(); - } + this->CheckForUnusedVariables(); - return true; + this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str()); + this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str()); + this->AddDefinition("CMAKE_CURRENT_LIST_DIR", + cmSystemTools::GetFilenamePath(currentFile).c_str()); + this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE"); + this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); + this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR"); } //---------------------------------------------------------------------------- @@ -668,6 +670,23 @@ void cmMakefile::EnforceDirectoryLevelRules() const } } +void cmMakefile::AddEvaluationFile(const std::string& inputFile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent) +{ + this->EvaluationFiles.push_back( + new cmGeneratorExpressionEvaluationFile(inputFile, outputName, + condition, + inputIsContent)); +} + +std::vector<cmGeneratorExpressionEvaluationFile*> +cmMakefile::GetEvaluationFiles() const +{ + return this->EvaluationFiles; +} + namespace { struct file_not_persistent @@ -1096,15 +1115,16 @@ cmMakefile::AddCustomCommandOldStyle(const std::string& target, } //---------------------------------------------------------------------------- -void cmMakefile::AddUtilityCommand(const std::string& utilityName, - bool excludeFromAll, - const std::vector<std::string>& depends, - const char* workingDirectory, - const char* command, - const char* arg1, - const char* arg2, - const char* arg3, - const char* arg4) +cmTarget* +cmMakefile::AddUtilityCommand(const std::string& utilityName, + bool excludeFromAll, + const std::vector<std::string>& depends, + const char* workingDirectory, + const char* command, + const char* arg1, + const char* arg2, + const char* arg3, + const char* arg4) { // Construct the command line for the custom command. cmCustomCommandLine commandLine; @@ -1129,8 +1149,8 @@ void cmMakefile::AddUtilityCommand(const std::string& utilityName, commandLines.push_back(commandLine); // Call the real signature of this method. - this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory, - depends, commandLines); + return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory, + depends, commandLines); } //---------------------------------------------------------------------------- @@ -1361,7 +1381,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) std::remove(defs.begin(), defs.end(), define); std::vector<std::string>::const_iterator defBegin = defs.begin(); - std::string ndefs = cmJoin(cmRange(defBegin, defEnd), ";"); + std::string ndefs = cmJoin(cmMakeRange(defBegin, defEnd), ";"); // Store the new list. this->SetProperty("COMPILE_DEFINITIONS", ndefs.c_str()); @@ -1451,61 +1471,15 @@ void cmMakefile::AddLinkLibrary(const std::string& lib) this->AddLinkLibrary(lib,cmTarget::GENERAL); } -void cmMakefile::AddLinkDirectory(const std::string& dir) -{ - // Don't add a link directory that is already present. Yes, this - // linear search results in n^2 behavior, but n won't be getting - // much bigger than 20. We cannot use a set because of order - // dependency of the link search path. - - if(dir.empty()) - { - return; - } - std::string newdir = dir; - // remove trailing slashes - if(*dir.rbegin() == '/') - { - newdir = dir.substr(0, dir.size()-1); - } - if(std::find(this->LinkDirectories.begin(), - this->LinkDirectories.end(), newdir) - == this->LinkDirectories.end()) - { - this->LinkDirectories.push_back(dir); - } -} - -void cmMakefile::InitializeFromParent() +void cmMakefile::InitializeFromParent(cmMakefile* parent) { - cmMakefile *parent = this->LocalGenerator->GetParent()->GetMakefile(); - - // Initialize definitions with the closure of the parent scope. - this->Internal->InitializeDefinitions(parent); + this->StateSnapshot.InitializeFromParent(); this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", this->GetCurrentSourceDirectory()); this->AddDefinition("CMAKE_CURRENT_BINARY_DIR", this->GetCurrentBinaryDirectory()); - const std::vector<cmValueWithOrigin>& parentIncludes = - parent->GetIncludeDirectoriesEntries(); - this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(), - parentIncludes.begin(), - parentIncludes.end()); - - const std::vector<cmValueWithOrigin>& parentOptions = - parent->GetCompileOptionsEntries(); - this->CompileOptionsEntries.insert(this->CompileOptionsEntries.end(), - parentOptions.begin(), - parentOptions.end()); - - const std::vector<cmValueWithOrigin>& parentDefines = - parent->GetCompileDefinitionsEntries(); - this->CompileDefinitionsEntries.insert(this->CompileDefinitionsEntries.end(), - parentDefines.begin(), - parentDefines.end()); - this->SystemIncludeDirectories = parent->SystemIncludeDirectories; // define flags @@ -1540,23 +1514,178 @@ void cmMakefile::InitializeFromParent() this->LinkLibraries = parent->LinkLibraries; // link directories - this->LinkDirectories = parent->LinkDirectories; + this->SetProperty("LINK_DIRECTORIES", + parent->GetProperty("LINK_DIRECTORIES")); // the initial project name - this->ProjectName = parent->ProjectName; + this->SetProjectName(parent->GetProjectName()); // Copy include regular expressions. - this->IncludeFileRegularExpression = parent->IncludeFileRegularExpression; this->ComplainFileRegularExpression = parent->ComplainFileRegularExpression; // Imported targets. this->ImportedTargets = parent->ImportedTargets; } -void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2) +void cmMakefile::PushFunctionScope(std::string const& fileName, + const cmPolicies::PolicyMap& pm) +{ + this->StateSnapshot = + this->GetState()->CreateFunctionCallSnapshot( + this->StateSnapshot, + this->ContextStack.back()->Name, this->ContextStack.back()->Line, + fileName); + assert(this->StateSnapshot.IsValid()); + + this->PushLoopBlockBarrier(); + +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope(); +#endif + + this->PushFunctionBlockerBarrier(); + + this->PushPolicy(true, pm); +} + +void cmMakefile::PopFunctionScope(bool reportError) +{ + this->PopPolicy(); + + this->PopPolicyBarrier(reportError); + + this->PopFunctionBlockerBarrier(reportError); + +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope(); +#endif + + this->PopLoopBlockBarrier(); + + this->CheckForUnusedVariables(); +} + +void cmMakefile::PushMacroScope(std::string const& fileName, + const cmPolicies::PolicyMap& pm) +{ + this->StateSnapshot = + this->GetState()->CreateMacroCallSnapshot( + this->StateSnapshot, + this->ContextStack.back()->Name, this->ContextStack.back()->Line, + fileName); + assert(this->StateSnapshot.IsValid()); + + this->PushFunctionBlockerBarrier(); + + this->PushPolicy(true, pm); +} + +void cmMakefile::PopMacroScope(bool reportError) +{ + this->PopPolicy(); + this->PopPolicyBarrier(reportError); + + this->PopFunctionBlockerBarrier(reportError); +} + +bool cmMakefile::IsRootMakefile() const +{ + return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid(); +} + +class cmMakefile::BuildsystemFileScope +{ +public: + BuildsystemFileScope(cmMakefile* mf) + : Makefile(mf), ReportError(true) + { + std::string currentStart = + this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(); + currentStart += "/CMakeLists.txt"; + this->Makefile->StateSnapshot.SetListFile(currentStart); + this->Makefile->StateSnapshot = this->Makefile->StateSnapshot.GetState() + ->CreatePolicyScopeSnapshot(this->Makefile->StateSnapshot); + this->Makefile->PushFunctionBlockerBarrier(); + + this->GG = mf->GetGlobalGenerator(); + this->CurrentMakefile = this->GG->GetCurrentMakefile(); + this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot(); + this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot); + this->GG->SetCurrentMakefile(mf); +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->GG->GetFileLockPool().PushFileScope(); +#endif + } + + ~BuildsystemFileScope() + { + this->Makefile->PopFunctionBlockerBarrier(this->ReportError); + this->Makefile->PopPolicyBarrier(this->ReportError); +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->GG->GetFileLockPool().PopFileScope(); +#endif + this->GG->SetCurrentMakefile(this->CurrentMakefile); + this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot); + } + + void Quiet() { this->ReportError = false; } +private: + cmMakefile* Makefile; + cmGlobalGenerator* GG; + cmMakefile* CurrentMakefile; + cmState::Snapshot Snapshot; + bool ReportError; +}; + +//---------------------------------------------------------------------------- +void cmMakefile::Configure() +{ + BuildsystemFileScope scope(this); + + // make sure the CMakeFiles dir is there + std::string filesDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); + filesDir += cmake::GetCMakeFilesDirectory(); + cmSystemTools::MakeDirectory(filesDir.c_str()); + + std::string currentStart = + this->StateSnapshot.GetDirectory().GetCurrentSource(); + currentStart += "/CMakeLists.txt"; + assert(cmSystemTools::FileExists(currentStart.c_str(), true)); + this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str()); + + cmListFile listFile; + { + cmParseFileScope pfs(this); + if (!listFile.ParseFile(currentStart.c_str(), this->IsRootMakefile(), this)) + { + this->SetConfigured(); + return; + } + } + this->ReadListFile(listFile, currentStart); + if(cmSystemTools::GetFatalErrorOccured()) + { + scope.Quiet(); + } + + // at the end handle any old style subdirs + std::vector<cmMakefile*> subdirs = this->UnConfiguredDirectories; + + // for each subdir recurse + std::vector<cmMakefile*>::iterator sdi = subdirs.begin(); + for (; sdi != subdirs.end(); ++sdi) + { + this->ConfigureSubDirectory(*sdi); + } + + this->AddCMakeDependFilesFromUser(); + this->SetConfigured(); +} + +void cmMakefile::ConfigureSubDirectory(cmMakefile *mf) { - lg2->GetMakefile()->InitializeFromParent(); - std::string currentStart = lg2->GetMakefile()->GetCurrentSourceDirectory(); + mf->InitializeFromParent(this); + std::string currentStart = mf->GetCurrentSourceDirectory(); if (this->GetCMakeInstance()->GetDebugOutput()) { std::string msg=" Entering "; @@ -1594,11 +1723,12 @@ void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2) // NEW behavior prints the error. this->IssueMessage(cmake::FATAL_ERROR, e.str()); } - lg2->SetConfiguredCMP0014(true); + mf->SetConfigured(); return; } // finally configure the subdir - lg2->Configure(); + mf->Configure(); + if (this->GetCMakeInstance()->GetDebugOutput()) { std::string msg=" Returning to "; @@ -1619,50 +1749,65 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, } cmState::Snapshot newSnapshot = this->GetState() - ->CreateSnapshot(this->StateSnapshot); + ->CreateBuildsystemDirectorySnapshot(this->StateSnapshot, + this->ContextStack.back()->Name, + this->ContextStack.back()->Line); + + cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot); + this->GetGlobalGenerator()->AddMakefile(subMf); // create a new local generator and set its parent cmLocalGenerator *lg2 = this->GetGlobalGenerator() - ->MakeLocalGenerator(newSnapshot, this->LocalGenerator); + ->CreateLocalGenerator(subMf); this->GetGlobalGenerator()->AddLocalGenerator(lg2); // set the subdirs start dirs - lg2->GetMakefile()->SetCurrentSourceDirectory(srcPath); - lg2->GetMakefile()->SetCurrentBinaryDirectory(binPath); + subMf->SetCurrentSourceDirectory(srcPath); + subMf->SetCurrentBinaryDirectory(binPath); if(excludeFromAll) { - lg2->GetMakefile()->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); + subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } if (immediate) { - this->ConfigureSubDirectory(lg2); + this->ConfigureSubDirectory(subMf); + } + else + { + this->UnConfiguredDirectories.push_back(subMf); } } void cmMakefile::SetCurrentSourceDirectory(const std::string& dir) { - this->StateSnapshot.SetCurrentSourceDirectory(dir); + this->StateSnapshot.GetDirectory().SetCurrentSource(dir); this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", - this->StateSnapshot.GetCurrentSourceDirectory()); + this->StateSnapshot.GetDirectory().GetCurrentSource()); } const char* cmMakefile::GetCurrentSourceDirectory() const { - return this->StateSnapshot.GetCurrentSourceDirectory(); + return this->StateSnapshot.GetDirectory().GetCurrentSource(); } void cmMakefile::SetCurrentBinaryDirectory(const std::string& dir) { - this->StateSnapshot.SetCurrentBinaryDirectory(dir); - const char* binDir = this->StateSnapshot.GetCurrentBinaryDirectory(); + this->StateSnapshot.GetDirectory().SetCurrentBinary(dir); + const char* binDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); cmSystemTools::MakeDirectory(binDir); this->AddDefinition("CMAKE_CURRENT_BINARY_DIR", binDir); } const char* cmMakefile::GetCurrentBinaryDirectory() const { - return this->StateSnapshot.GetCurrentBinaryDirectory(); + return this->StateSnapshot.GetDirectory().GetCurrentBinary(); +} + +void cmMakefile::AddGeneratorTarget(cmTarget* t, cmGeneratorTarget* gt) +{ + this->GeneratorTargets[t] = gt; + this->GetGlobalGenerator()->AddGeneratorTarget(t, gt); } //---------------------------------------------------------------------------- @@ -1674,20 +1819,25 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs, return; } - std::vector<cmValueWithOrigin>::iterator position = - before ? this->IncludeDirectoriesEntries.begin() - : this->IncludeDirectoriesEntries.end(); - cmListFileBacktrace lfbt = this->GetBacktrace(); - cmValueWithOrigin entry(cmJoin(incs, ";"), lfbt); - this->IncludeDirectoriesEntries.insert(position, entry); + std::string entryString = cmJoin(incs, ";"); + if (before) + { + this->StateSnapshot.GetDirectory() + .PrependIncludeDirectoriesEntry(entryString, lfbt); + } + else + { + this->StateSnapshot.GetDirectory() + .AppendIncludeDirectoriesEntry(entryString, lfbt); + } // Property on each target: for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end(); ++l) { cmTarget &t = l->second; - t.InsertInclude(entry, before); + t.InsertInclude(entryString, lfbt, before); } } @@ -1716,7 +1866,7 @@ void cmMakefile::AddDefinition(const std::string& name, const char* value) { this->LogUnused("changing definition", name); } - this->Internal->SetDefinition(name, value); + this->StateSnapshot.SetDefinition(name, value); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); @@ -1779,7 +1929,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, this->GetState()->AddCacheEntry(name, haveVal ? val.c_str() : 0, doc, type); // if there was a definition then remove it - this->Internal->RemoveDefinition(name); + this->StateSnapshot.RemoveDefinition(name); } @@ -1789,7 +1939,9 @@ void cmMakefile::AddDefinition(const std::string& name, bool value) { this->LogUnused("changing definition", name); } - this->Internal->SetDefinition(name, value ? "ON" : "OFF"); + + this->StateSnapshot.SetDefinition(name, value ? "ON" : "OFF"); + #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -1806,7 +1958,7 @@ void cmMakefile::CheckForUnusedVariables() const { return; } - const std::vector<std::string>& unused = this->Internal->UnusedKeys(); + const std::vector<std::string>& unused = this->StateSnapshot.UnusedKeys(); std::vector<std::string>::const_iterator it = unused.begin(); for (; it != unused.end(); ++it) { @@ -1816,12 +1968,12 @@ void cmMakefile::CheckForUnusedVariables() const void cmMakefile::MarkVariableAsUsed(const std::string& var) { - this->Internal->GetDefinition(var); + this->StateSnapshot.GetDefinition(var); } bool cmMakefile::VariableInitialized(const std::string& var) const { - return this->Internal->IsInitialized(var); + return this->StateSnapshot.IsInitialized(var); } void cmMakefile::LogUnused(const char* reason, @@ -1831,7 +1983,7 @@ void cmMakefile::LogUnused(const char* reason, { std::string path; cmListFileContext lfc; - if (!this->CallStack.empty()) + if (!this->ExecutionStatusStack.empty()) { lfc = this->GetExecutionContext(); path = lfc.FilePath; @@ -1843,8 +1995,8 @@ void cmMakefile::LogUnused(const char* reason, lfc.FilePath = path; lfc.Line = 0; } - lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath, - cmLocalGenerator::HOME); + cmOutputConverter converter(this->StateSnapshot); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); if (this->CheckSystemVars || cmSystemTools::IsSubDirectory(path, @@ -1869,7 +2021,7 @@ void cmMakefile::RemoveDefinition(const std::string& name) { this->LogUnused("unsetting", name); } - this->Internal->RemoveDefinition(name); + this->StateSnapshot.RemoveDefinition(name); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -1885,11 +2037,15 @@ void cmMakefile::RemoveCacheDefinition(const std::string& name) this->GetState()->RemoveCacheEntry(name); } -void cmMakefile::SetProjectName(const char* p) +void cmMakefile::SetProjectName(std::string const& p) { - this->ProjectName = p; + this->StateSnapshot.SetProjectName(p); } +std::string cmMakefile::GetProjectName() const +{ + return this->StateSnapshot.GetProjectName(); +} void cmMakefile::AddGlobalLinkInformation(const std::string& name, cmTarget& target) @@ -1903,11 +2059,27 @@ void cmMakefile::AddGlobalLinkInformation(const std::string& name, return; default:; } - std::vector<std::string>::iterator j; - for(j = this->LinkDirectories.begin(); - j != this->LinkDirectories.end(); ++j) + if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { - target.AddLinkDirectory(*j); + std::vector<std::string> linkDirs; + cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs); + + for(std::vector<std::string>::iterator j = linkDirs.begin(); + j != linkDirs.end(); ++j) + { + std::string newdir = *j; + // remove trailing slashes + if(*j->rbegin() == '/') + { + newdir = j->substr(0, j->size()-1); + } + if(std::find(this->LinkDirectories.begin(), + this->LinkDirectories.end(), newdir) + == this->LinkDirectories.end()) + { + target.AddLinkDirectory(*j); + } + } } target.MergeLinkLibraries( *this, name, this->LinkLibraries ); } @@ -2116,25 +2288,10 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, return; } // build the whole source group path - const char* fullname = sg->GetFullName(); - cmGlobalGenerator* gg = this->GetGlobalGenerator(); - if(strlen(fullname)) - { - std::string guidName = "SG_Filter_"; - guidName += fullname; - gg->CreateGUID(guidName); - } for(++i; i<=lastElement; ++i) { sg->AddChild(cmSourceGroup(name[i].c_str(), 0, sg->GetFullName())); sg = sg->LookupChild(name[i].c_str()); - fullname = sg->GetFullName(); - if(strlen(fullname)) - { - std::string guidName = "SG_Filter_"; - guidName += fullname; - gg->CreateGUID(guidName); - } } sg->SetGroupRegex(regex); @@ -2177,7 +2334,8 @@ void cmMakefile::ExpandVariablesCMP0019() l != this->Targets.end(); ++l) { cmTarget &t = l->second; - if (t.GetType() == cmTarget::INTERFACE_LIBRARY) + if (t.GetType() == cmTarget::INTERFACE_LIBRARY + || t.GetType() == cmTarget::GLOBAL_TARGET) { continue; } @@ -2197,19 +2355,19 @@ void cmMakefile::ExpandVariablesCMP0019() } } - for(std::vector<std::string>::iterator d = this->LinkDirectories.begin(); - d != this->LinkDirectories.end(); ++d) + if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { - if(mightExpandVariablesCMP0019(d->c_str())) + if(mightExpandVariablesCMP0019(linkDirsProp)) { - std::string orig = *d; - this->ExpandVariablesInString(*d, true, true); - if(pol == cmPolicies::WARN && *d != orig) + std::string d = linkDirsProp; + std::string orig = linkDirsProp; + this->ExpandVariablesInString(d, true, true); + if(pol == cmPolicies::WARN && d != orig) { - w << "Evaluated link directory\n" + w << "Evaluated link directories\n" << " " << orig << "\n" << "as\n" - << " " << *d << "\n"; + << " " << d << "\n"; } } } @@ -2278,6 +2436,18 @@ bool cmMakefile::PlatformIs64Bit() const return false; } +bool cmMakefile::PlatformIsAppleIos() const +{ + std::string sdkRoot; + sdkRoot = this->GetSafeDefinition("CMAKE_OSX_SYSROOT"); + sdkRoot = cmSystemTools::LowerCase(sdkRoot); + + return sdkRoot.find("iphoneos") == 0 || + sdkRoot.find("/iphoneos") != std::string::npos || + sdkRoot.find("iphonesimulator") == 0 || + sdkRoot.find("/iphonesimulator") != std::string::npos; +} + const char* cmMakefile::GetSONameFlag(const std::string& language) const { std::string name = "CMAKE_SHARED_LIBRARY_SONAME"; @@ -2335,7 +2505,7 @@ const char* cmMakefile::GetRequiredDefinition(const std::string& name) const bool cmMakefile::IsDefinitionSet(const std::string& name) const { - const char* def = this->Internal->GetDefinition(name); + const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2356,7 +2526,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const const char* cmMakefile::GetDefinition(const std::string& name) const { - const char* def = this->Internal->GetDefinition(name); + const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2390,18 +2560,11 @@ const char* cmMakefile::GetSafeDefinition(const std::string& def) const return ret; } -std::vector<std::string> cmMakefile -::GetDefinitions(int cacheonly /* = 0 */) const +std::vector<std::string> cmMakefile::GetDefinitions() const { - std::vector<std::string> res; - if ( !cacheonly ) - { - res = this->Internal->ClosureKeys(); - } - std::vector<std::string> cacheKeys = - this->GetState()->GetCacheEntryKeys(); + std::vector<std::string> res = this->StateSnapshot.ClosureKeys(); + std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys(); res.insert(res.end(), cacheKeys.begin(), cacheKeys.end()); - std::sort(res.begin(), res.end()); return res; } @@ -2763,8 +2926,9 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( { std::ostringstream msg; cmListFileContext lfc; - lfc.FilePath = this->LocalGenerator - ->Convert(filename, cmLocalGenerator::HOME); + cmOutputConverter converter(this->StateSnapshot); + lfc.FilePath = + converter.Convert(filename, cmOutputConverter::HOME); lfc.Line = line; msg << "uninitialized variable \'" << lookup << "\'"; this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, @@ -3214,11 +3378,22 @@ bool cmMakefile::IsLoopBlock() const return !this->LoopBlockCounter.empty() && this->LoopBlockCounter.top() > 0; } +std::string cmMakefile::GetExecutionFilePath() const +{ + assert(this->StateSnapshot.IsValid()); + return this->StateSnapshot.GetExecutionListFile(); +} + //---------------------------------------------------------------------------- bool cmMakefile::ExpandArguments( std::vector<cmListFileArgument> const& inArgs, - std::vector<std::string>& outArgs) const + std::vector<std::string>& outArgs, const char* filename) const { + std::string efp = this->GetExecutionFilePath(); + if (!filename) + { + filename = efp.c_str(); + } std::vector<cmListFileArgument>::const_iterator i; std::string value; outArgs.reserve(inArgs.size()); @@ -3233,8 +3408,7 @@ bool cmMakefile::ExpandArguments( // Expand the variables in the argument. value = i->Value; this->ExpandVariablesInString(value, false, false, false, - i->FilePath, i->Line, - false, false); + filename, i->Line, false, false); // If the argument is quoted, it should be one argument. // Otherwise, it may be a list of arguments. @@ -3253,8 +3427,13 @@ bool cmMakefile::ExpandArguments( //---------------------------------------------------------------------------- bool cmMakefile::ExpandArguments( std::vector<cmListFileArgument> const& inArgs, - std::vector<cmExpandedCommandArgument>& outArgs) const + std::vector<cmExpandedCommandArgument>& outArgs, const char* filename) const { + std::string efp = this->GetExecutionFilePath(); + if (!filename) + { + filename = efp.c_str(); + } std::vector<cmListFileArgument>::const_iterator i; std::string value; outArgs.reserve(inArgs.size()); @@ -3269,8 +3448,7 @@ bool cmMakefile::ExpandArguments( // Expand the variables in the argument. value = i->Value; this->ExpandVariablesInString(value, false, false, false, - i->FilePath, i->Line, - false, false); + filename, i->Line, false, false); // If the argument is quoted, it should be one argument. // Otherwise, it may be a list of arguments. @@ -3294,7 +3472,7 @@ bool cmMakefile::ExpandArguments( //---------------------------------------------------------------------------- void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb) { - if(!this->CallStack.empty()) + if(!this->ExecutionStatusStack.empty()) { // Record the context in which the blocker is created. fb->SetStartingContext(this->GetExecutionContext()); @@ -3327,11 +3505,13 @@ cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb, if(!(*pos)->ShouldRemove(lff, *this)) { cmListFileContext const& lfc = fb->GetStartingContext(); + cmListFileContext closingContext = + cmListFileContext::FromCommandContext(lff, lfc.FilePath); std::ostringstream e; e << "A logical block opening on the line\n" << " " << lfc << "\n" << "closes on the line\n" - << " " << lff << "\n" + << " " << closingContext << "\n" << "with mis-matching arguments."; this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); } @@ -3344,19 +3524,6 @@ cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb, return cmsys::auto_ptr<cmFunctionBlocker>(); } -//---------------------------------------------------------------------------- -cmMakefile::LexicalPushPop::LexicalPushPop(cmMakefile* mf): - Makefile(mf), ReportError(true) -{ - this->Makefile->PushFunctionBlockerBarrier(); -} - -//---------------------------------------------------------------------------- -cmMakefile::LexicalPushPop::~LexicalPushPop() -{ - this->Makefile->PopFunctionBlockerBarrier(this->ReportError); -} - const char* cmMakefile::GetHomeDirectory() const { return this->GetCMakeInstance()->GetHomeDirectory(); @@ -3448,7 +3615,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, const std::vector<std::string> *cmakeArgs, std::string& output) { - this->Internal->IsSourceFileTryCompile = fast; + this->IsSourceFileTryCompile = fast; // does the binary directory exist ? If not create it... if (!cmSystemTools::FileIsDirectory(bindir)) { @@ -3473,7 +3640,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, "Internal CMake error, TryCompile bad GlobalGenerator"); // return to the original directory cmSystemTools::ChangeDirectory(cwd); - this->Internal->IsSourceFileTryCompile = false; + this->IsSourceFileTryCompile = false; return 1; } cm.SetGlobalGenerator(gg); @@ -3544,7 +3711,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, "Internal CMake error, TryCompile configure of cmake failed"); // return to the original directory cmSystemTools::ChangeDirectory(cwd); - this->Internal->IsSourceFileTryCompile = false; + this->IsSourceFileTryCompile = false; return 1; } @@ -3554,7 +3721,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, "Internal CMake error, TryCompile generation of cmake failed"); // return to the original directory cmSystemTools::ChangeDirectory(cwd); - this->Internal->IsSourceFileTryCompile = false; + this->IsSourceFileTryCompile = false; return 1; } @@ -3567,23 +3734,23 @@ int cmMakefile::TryCompile(const std::string& srcdir, this); cmSystemTools::ChangeDirectory(cwd); - this->Internal->IsSourceFileTryCompile = false; + this->IsSourceFileTryCompile = false; return ret; } bool cmMakefile::GetIsSourceFileTryCompile() const { - return this->Internal->IsSourceFileTryCompile; + return this->IsSourceFileTryCompile; } cmake *cmMakefile::GetCMakeInstance() const { - return this->GetGlobalGenerator()->GetCMakeInstance(); + return this->GlobalGenerator->GetCMakeInstance(); } cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const { - return this->LocalGenerator->GetGlobalGenerator(); + return this->GlobalGenerator; } #ifdef CMAKE_BUILD_WITH_CMAKE @@ -3598,18 +3765,6 @@ cmVariableWatch *cmMakefile::GetVariableWatch() const } #endif -void cmMakefile::AddMacro(const char* name) -{ - assert(name); - this->MacrosList.push_back(name); -} - -void cmMakefile::GetListOfMacros(std::string& macros) const -{ - assert(macros.empty()); - macros = cmJoin(this->MacrosList, ";"); -} - cmState *cmMakefile::GetState() const { return this->GetCMakeInstance()->GetState(); @@ -3919,234 +4074,28 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, void cmMakefile::SetProperty(const std::string& prop, const char* value) { - if ( prop == "LINK_DIRECTORIES" ) - { - std::vector<std::string> varArgsExpanded; - if(value) - { - cmSystemTools::ExpandListArgument(value, varArgsExpanded); - } - this->SetLinkDirectories(varArgsExpanded); - return; - } - if (prop == "INCLUDE_DIRECTORIES") - { - this->IncludeDirectoriesEntries.clear(); - if (!value) - { - return; - } - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->IncludeDirectoriesEntries.push_back( - cmValueWithOrigin(value, lfbt)); - return; - } - if (prop == "COMPILE_OPTIONS") - { - this->CompileOptionsEntries.clear(); - if (!value) - { - return; - } - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->CompileOptionsEntries.push_back(cmValueWithOrigin(value, lfbt)); - return; - } - if (prop == "COMPILE_DEFINITIONS") - { - this->CompileDefinitionsEntries.clear(); - if (!value) - { - return; - } - cmListFileBacktrace lfbt = this->GetBacktrace(); - cmValueWithOrigin entry(value, lfbt); - this->CompileDefinitionsEntries.push_back(entry); - return; - } - - if ( prop == "INCLUDE_REGULAR_EXPRESSION" ) - { - this->SetIncludeRegularExpression(value); - return; - } - - if ( prop == "ADDITIONAL_MAKE_CLEAN_FILES" ) - { - // This property is not inherrited - if ( strcmp(this->GetCurrentSourceDirectory(), - this->GetCurrentSourceDirectory()) != 0 ) - { - return; - } - } - - this->Properties.SetProperty(prop,value,cmProperty::DIRECTORY); + cmListFileBacktrace lfbt = this->GetBacktrace(); + this->StateSnapshot.GetDirectory().SetProperty(prop, value, lfbt); } void cmMakefile::AppendProperty(const std::string& prop, const char* value, bool asString) { - if (prop == "INCLUDE_DIRECTORIES") - { - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->IncludeDirectoriesEntries.push_back( - cmValueWithOrigin(value, lfbt)); - return; - } - if (prop == "COMPILE_OPTIONS") - { - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->CompileOptionsEntries.push_back( - cmValueWithOrigin(value, lfbt)); - return; - } - if (prop == "COMPILE_DEFINITIONS") - { - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->CompileDefinitionsEntries.push_back( - cmValueWithOrigin(value, lfbt)); - return; - } - if ( prop == "LINK_DIRECTORIES" ) - { - std::vector<std::string> varArgsExpanded; - cmSystemTools::ExpandListArgument(value, varArgsExpanded); - for(std::vector<std::string>::const_iterator vi = varArgsExpanded.begin(); - vi != varArgsExpanded.end(); ++vi) - { - this->AddLinkDirectory(*vi); - } - return; - } - - this->Properties.AppendProperty(prop,value,cmProperty::DIRECTORY,asString); + cmListFileBacktrace lfbt = this->GetBacktrace(); + this->StateSnapshot.GetDirectory().AppendProperty(prop, value, + asString, lfbt); } const char *cmMakefile::GetProperty(const std::string& prop) const { - return this->GetProperty(prop, cmProperty::DIRECTORY); + return this->StateSnapshot.GetDirectory().GetProperty(prop); } const char *cmMakefile::GetProperty(const std::string& prop, - cmProperty::ScopeType scope) const + bool chain) const { - // watch for specific properties - static std::string output; - output = ""; - if (prop == "PARENT_DIRECTORY") - { - cmState::Snapshot parent = this->StateSnapshot.GetParent(); - if(parent.IsValid()) - { - return parent.GetCurrentSourceDirectory(); - } - return ""; - } - else if (prop == "INCLUDE_REGULAR_EXPRESSION" ) - { - output = this->GetIncludeRegularExpression(); - return output.c_str(); - } - else if (prop == "LISTFILE_STACK") - { - output = cmJoin(this->ListFileStack, ";"); - return output.c_str(); - } - else if (prop == "VARIABLES" || prop == "CACHE_VARIABLES") - { - int cacheonly = 0; - if ( prop == "CACHE_VARIABLES" ) - { - cacheonly = 1; - } - output = cmJoin(this->GetDefinitions(cacheonly), ";"); - return output.c_str(); - } - else if (prop == "MACROS") - { - this->GetListOfMacros(output); - return output.c_str(); - } - else if (prop == "DEFINITIONS") - { - switch(this->GetPolicyStatus(cmPolicies::CMP0059)) - { - case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, cmPolicies:: - GetPolicyWarning(cmPolicies::CMP0059)); - case cmPolicies::OLD: - output += this->DefineFlagsOrig; - return output.c_str(); - case cmPolicies::NEW: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - break; - } - } - else if (prop == "LINK_DIRECTORIES") - { - output = cmJoin(this->GetLinkDirectories(), ";"); - return output.c_str(); - } - else if (prop == "INCLUDE_DIRECTORIES") - { - std::string sep; - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->IncludeDirectoriesEntries.begin(), - end = this->IncludeDirectoriesEntries.end(); - it != end; ++it) - { - output += sep; - output += it->Value; - sep = ";"; - } - return output.c_str(); - } - else if (prop == "COMPILE_OPTIONS") - { - std::string sep; - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->CompileOptionsEntries.begin(), - end = this->CompileOptionsEntries.end(); - it != end; ++it) - { - output += sep; - output += it->Value; - sep = ";"; - } - return output.c_str(); - } - else if (prop == "COMPILE_DEFINITIONS") - { - std::string sep; - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->CompileDefinitionsEntries.begin(), - end = this->CompileDefinitionsEntries.end(); - it != end; ++it) - { - output += sep; - output += it->Value; - sep = ";"; - } - return output.c_str(); - } - - bool chain = false; - const char *retVal = - this->Properties.GetPropertyValue(prop, scope, chain); - if (chain) - { - if(this->LocalGenerator->GetParent()) - { - return this->LocalGenerator->GetParent()->GetMakefile()-> - GetProperty(prop, scope); - } - return this->GetState()->GetGlobalProperty(prop); - } - - return retVal; + return this->StateSnapshot.GetDirectory().GetProperty(prop, chain); } bool cmMakefile::GetPropertyAsBool(const std::string& prop) const @@ -4154,31 +4103,9 @@ bool cmMakefile::GetPropertyAsBool(const std::string& prop) const return cmSystemTools::IsOn(this->GetProperty(prop)); } -//---------------------------------------------------------------------------- -const char* cmMakefile::GetFeature(const std::string& feature, - const std::string& config) +std::vector<std::string> cmMakefile::GetPropertyKeys() const { - // TODO: Define accumulation policy for features (prepend, append, replace). - // Currently we always replace. - if(!config.empty()) - { - std::string featureConfig = feature; - featureConfig += "_"; - featureConfig += cmSystemTools::UpperCase(config); - if(const char* value = this->GetProperty(featureConfig)) - { - return value; - } - } - if(const char* value = this->GetProperty(feature)) - { - return value; - } - if(cmLocalGenerator* parent = this->LocalGenerator->GetParent()) - { - return parent->GetMakefile()->GetFeature(feature, config); - } - return 0; + return this->StateSnapshot.GetDirectory().GetPropertyKeys(); } cmTarget* cmMakefile::FindTarget(const std::string& name, @@ -4253,14 +4180,22 @@ void cmMakefile::AddCMakeDependFilesFromUser() std::string cmMakefile::FormatListFileStack() const { + std::vector<std::string> listFiles; + cmState::Snapshot snp = this->StateSnapshot; + while (snp.IsValid()) + { + listFiles.push_back(snp.GetExecutionListFile()); + snp = snp.GetCallStackParent(); + } + std::reverse(listFiles.begin(), listFiles.end()); std::ostringstream tmp; - size_t depth = this->ListFileStack.size(); + size_t depth = listFiles.size(); if (depth > 0) { - std::vector<std::string>::const_iterator it = this->ListFileStack.end(); + std::vector<std::string>::const_iterator it = listFiles.end(); do { - if (depth != this->ListFileStack.size()) + if (depth != listFiles.size()) { tmp << "\n "; } @@ -4271,7 +4206,7 @@ std::string cmMakefile::FormatListFileStack() const tmp << *it; depth--; } - while (it != this->ListFileStack.begin()); + while (it != listFiles.begin()); } return tmp.str(); } @@ -4279,8 +4214,17 @@ std::string cmMakefile::FormatListFileStack() const void cmMakefile::PushScope() { - this->Internal->PushDefinitions(); - + std::string commandName; + long line = 0; + if (!this->ContextStack.empty()) + { + commandName = this->ContextStack.back()->Name; + line = this->ContextStack.back()->Line; + } + this->StateSnapshot = this->GetState()->CreateVariableScopeSnapshot( + this->StateSnapshot, + commandName, + line); this->PushLoopBlockBarrier(); #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -4298,7 +4242,9 @@ void cmMakefile::PopScope() this->CheckForUnusedVariables(); - this->Internal->PopDefinitions(); + this->StateSnapshot = + this->GetState()->Pop(this->StateSnapshot); + assert(this->StateSnapshot.IsValid()); } void cmMakefile::RaiseScope(const std::string& var, const char *varDef) @@ -4308,7 +4254,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char *varDef) return; } - if (!this->Internal->RaiseScope(var, varDef, this)) + if (!this->StateSnapshot.RaiseScope(var, varDef)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; @@ -4596,57 +4542,21 @@ void cmMakefile::StoreMatches(cmsys::RegularExpression& re) this->MarkVariableAsUsed(nMatchesVariable); } -//---------------------------------------------------------------------------- -cmPolicies::PolicyStatus -cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) const +cmState::Snapshot cmMakefile::GetStateSnapshot() const { - // Get the current setting of the policy. - cmPolicies::PolicyStatus cur = this->GetPolicyStatusInternal(id); - - // If the policy is required to be set to NEW but is not, ignore the - // current setting and tell the caller. - if(cur != cmPolicies::NEW) - { - if(cur == cmPolicies::REQUIRED_ALWAYS || - cur == cmPolicies::REQUIRED_IF_USED) - { - return cur; - } - cmPolicies::PolicyStatus def = cmPolicies::GetPolicyStatus(id); - if(def == cmPolicies::REQUIRED_ALWAYS || - def == cmPolicies::REQUIRED_IF_USED) - { - return def; - } - } + return this->StateSnapshot; +} - // The current setting is okay. - return cur; +const char* cmMakefile::GetDefineFlagsCMP0059() const +{ + return this->DefineFlagsOrig.c_str(); } //---------------------------------------------------------------------------- cmPolicies::PolicyStatus -cmMakefile::GetPolicyStatusInternal(cmPolicies::PolicyID id) const +cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) const { - // Is the policy set in our stack? - for(PolicyStackType::const_reverse_iterator psi = this->PolicyStack.rbegin(); - psi != this->PolicyStack.rend(); ++psi) - { - if(psi->IsDefined(id)) - { - return psi->Get(id); - } - } - - // If we have a parent directory, recurse up to it. - if(this->LocalGenerator->GetParent()) - { - cmMakefile* parent = this->LocalGenerator->GetParent()->GetMakefile(); - return parent->GetPolicyStatusInternal(id); - } - - // The policy is not set. Use the default for this CMake version. - return cmPolicies::GetPolicyStatus(id); + return this->StateSnapshot.GetPolicy(id); } //---------------------------------------------------------------------------- @@ -4660,7 +4570,8 @@ bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) return cmSystemTools::IsOn(val); } } - // Enable optional policy warnings with --debug-output or --trace. + // Enable optional policy warnings with --debug-output, --trace, + // or --trace-expand. cmake* cm = this->GetCMakeInstance(); return cm->GetDebugOutput() || cm->GetTrace(); } @@ -4694,34 +4605,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, return false; } - // Update the policy stack from the top to the top-most strong entry. - bool previous_was_weak = true; - for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin(); - previous_was_weak && psi != this->PolicyStack.rend(); ++psi) - { - psi->Set(id, status); - previous_was_weak = psi->Weak; - } - - // Special hook for presenting compatibility variable as soon as - // the user requests it. - if(id == cmPolicies::CMP0001 && - (status == cmPolicies::WARN || status == cmPolicies::OLD)) - { - if(!(this->GetState() - ->GetInitializedCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))) - { - // Set it to 2.4 because that is the last version where the - // variable had meaning. - this->AddCacheDefinition - ("CMAKE_BACKWARDS_COMPATIBILITY", "2.4", - "For backwards compatibility, what version of CMake " - "commands and " - "syntax should this version of CMake try to support.", - cmState::STRING); - } - } - + this->StateSnapshot.SetPolicy(id, status); return true; } @@ -4730,32 +4614,28 @@ cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m, bool weak, cmPolicies::PolicyMap const& pm): Makefile(m), ReportError(true) { + this->Makefile->StateSnapshot = this->Makefile->StateSnapshot.GetState() + ->CreatePolicyScopeSnapshot(this->Makefile->StateSnapshot); this->Makefile->PushPolicy(weak, pm); - this->Makefile->PushPolicyBarrier(); } //---------------------------------------------------------------------------- cmMakefile::PolicyPushPop::~PolicyPushPop() { - this->Makefile->PopPolicyBarrier(this->ReportError); this->Makefile->PopPolicy(); + this->Makefile->PopPolicyBarrier(this->ReportError); } //---------------------------------------------------------------------------- void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm) { - // Allocate a new stack entry. - this->PolicyStack.push_back(PolicyStackEntry(pm, weak)); + this->StateSnapshot.PushPolicy(pm, weak); } //---------------------------------------------------------------------------- void cmMakefile::PopPolicy() { - if(this->PolicyStack.size() > this->PolicyBarriers.back()) - { - this->PolicyStack.pop_back(); - } - else + if (!this->StateSnapshot.PopPolicy()) { this->IssueMessage(cmake::FATAL_ERROR, "cmake_policy POP without matching PUSH"); @@ -4763,17 +4643,9 @@ void cmMakefile::PopPolicy() } //---------------------------------------------------------------------------- -void cmMakefile::PushPolicyBarrier() -{ - this->PolicyBarriers.push_back(this->PolicyStack.size()); -} - -//---------------------------------------------------------------------------- void cmMakefile::PopPolicyBarrier(bool reportError) { - // Remove any extra entries pushed on the barrier. - PolicyStackType::size_type barrier = this->PolicyBarriers.back(); - while(this->PolicyStack.size() > barrier) + while (!this->StateSnapshot.CanPopPolicyScope()) { if(reportError) { @@ -4784,8 +4656,8 @@ void cmMakefile::PopPolicyBarrier(bool reportError) this->PopPolicy(); } - // Remove the barrier. - this->PolicyBarriers.pop_back(); + this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot); + assert(this->StateSnapshot.IsValid()); } //---------------------------------------------------------------------------- @@ -5357,3 +5229,44 @@ AddRequiredTargetCFeature(cmTarget *target, const std::string& feature) const } return true; } + + +cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf, + const std::string& fileName, + cmPolicies::PolicyMap const& pm) + : Makefile(mf), ReportError(true) +{ + this->Makefile->PushFunctionScope(fileName, pm); +} + +cmMakefile::FunctionPushPop::~FunctionPushPop() +{ + this->Makefile->PopFunctionScope(this->ReportError); +} + + +cmMakefile::MacroPushPop::MacroPushPop(cmMakefile* mf, + const std::string& fileName, + const cmPolicies::PolicyMap& pm) + : Makefile(mf), ReportError(true) +{ + this->Makefile->PushMacroScope(fileName, pm); +} + +cmMakefile::MacroPushPop::~MacroPushPop() +{ + this->Makefile->PopMacroScope(this->ReportError); +} + +cmMakefileCall::cmMakefileCall(cmMakefile* mf, const cmCommandContext& lfc, + cmExecutionStatus& status): Makefile(mf) +{ + this->Makefile->ContextStack.push_back(&lfc); + this->Makefile->ExecutionStatusStack.push_back(&status); +} + +cmMakefileCall::~cmMakefileCall() +{ + this->Makefile->ExecutionStatusStack.pop_back(); + this->Makefile->ContextStack.pop_back(); +} diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 27ef075..3cf20a6 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -14,8 +14,6 @@ #include "cmExecutionStatus.h" #include "cmListFileCache.h" -#include "cmPolicies.h" -#include "cmPropertyMap.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmNewLineStyle.h" @@ -23,6 +21,7 @@ #include "cmExpandedCommandArgument.h" #include "cmake.h" #include "cmState.h" +#include "cmAlgorithms.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmSourceGroup.h" @@ -43,7 +42,6 @@ class cmFunctionBlocker; class cmCommand; class cmInstallGenerator; -class cmLocalGenerator; class cmMakeDepend; class cmSourceFile; class cmTest; @@ -52,6 +50,7 @@ class cmVariableWatch; class cmake; class cmMakefileCall; class cmCMakePolicyCommand; +class cmGeneratorExpressionEvaluationFile; /** \class cmMakefile * \brief Process the input CMakeLists.txt file. @@ -62,8 +61,6 @@ class cmCMakePolicyCommand; */ class cmMakefile { - class Internals; - cmsys::auto_ptr<Internals> Internal; public: /* Mark a variable as used */ void MarkVariableAsUsed(const std::string& var); @@ -73,24 +70,28 @@ public: /** * Construct an empty makefile. */ - cmMakefile(cmLocalGenerator* localGenerator); + cmMakefile(cmGlobalGenerator* globalGenerator, + const cmState::Snapshot& snapshot); /** * Destructor. */ ~cmMakefile(); - bool ReadListFile(const char* listfile); + bool ReadListFile(const char* filename); - bool ReadDependentFile(const char* listfile, bool noPolicyScope = true); + bool ReadDependentFile(const char* filename, bool noPolicyScope = true); - bool ProcessBuildsystemFile(const char* listfile); + bool ProcessBuildsystemFile(const char* filename); /** * Add a function blocker to this makefile */ void AddFunctionBlocker(cmFunctionBlocker* fb); + /// @return whether we are processing the top CMakeLists.txt file. + bool IsRootMakefile() const; + /** * Remove the function blocker whose scope ends with the given command. * This returns ownership of the function blocker object. @@ -98,19 +99,6 @@ public: cmsys::auto_ptr<cmFunctionBlocker> RemoveFunctionBlocker(cmFunctionBlocker* fb, const cmListFileFunction& lff); - /** Push/pop a lexical (function blocker) barrier automatically. */ - class LexicalPushPop - { - public: - LexicalPushPop(cmMakefile* mf); - ~LexicalPushPop(); - void Quiet() { this->ReportError = false; } - private: - cmMakefile* Makefile; - bool ReportError; - }; - friend class LexicalPushPop; - /** * Try running cmake and building a file. This is used for dynalically * loaded commands, not as part of the usual build process. @@ -123,10 +111,6 @@ public: bool GetIsSourceFileTryCompile() const; - ///! Get the current makefile generator. - cmLocalGenerator* GetLocalGenerator() const - { return this->LocalGenerator;} - /** * Help enforce global target name uniqueness. */ @@ -204,14 +188,15 @@ public: * Add a utility to the build. A utiltity target is a command that * is run every time the target is built. */ - void AddUtilityCommand(const std::string& utilityName, bool excludeFromAll, - const std::vector<std::string>& depends, - const char* workingDirectory, - const char* command, - const char* arg1=0, - const char* arg2=0, - const char* arg3=0, - const char* arg4=0); + cmTarget* AddUtilityCommand(const std::string& utilityName, + bool excludeFromAll, + const std::vector<std::string>& depends, + const char* workingDirectory, + const char* command, + const char* arg1=0, + const char* arg2=0, + const char* arg3=0, + const char* arg4=0); cmTarget* AddUtilityCommand(const std::string& utilityName, bool excludeFromAll, const char* workingDirectory, @@ -240,20 +225,6 @@ public: void AddLinkDirectoryForTarget(const std::string& tgt, const std::string& d); /** - * Add a link directory to the build. - */ - void AddLinkDirectory(const std::string&); - - const std::vector<std::string>& GetLinkDirectories() const - { - return this->LinkDirectories; - } - void SetLinkDirectories(const std::vector<std::string>& vec) - { - this->LinkDirectories = vec; - } - - /** * Add a subdirectory to the build. */ void AddSubDirectory(const std::string& fullSrcDir, @@ -261,10 +232,12 @@ public: bool excludeFromAll, bool immediate); + void Configure(); + /** * Configure a subdirectory */ - void ConfigureSubDirectory(cmLocalGenerator *); + void ConfigureSubDirectory(cmMakefile* mf); /** * Add an include directory to the build. @@ -299,15 +272,12 @@ public: /** * Specify the name of the project for this build. */ - void SetProjectName(const char*); + void SetProjectName(std::string const& name); /** * Get the name of the project for this build. */ - const char* GetProjectName() const - { - return this->ProjectName.c_str(); - } + std::string GetProjectName() const; /** Get the configurations to be generated. */ std::string GetConfigurations(std::vector<std::string>& configs, @@ -363,13 +333,6 @@ public: friend class PolicyPushPop; /** - * Get the Policies Instance - */ - cmPolicies *GetPolicies() const; - - mutable std::set<cmListFileContext> CMP0054ReportedIds; - - /** * Determine if the given context, name pair has already been reported * in context of CMP0054. */ @@ -403,11 +366,11 @@ public: */ void SetIncludeRegularExpression(const char* regex) { - this->IncludeFileRegularExpression = regex; + this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex); } const char* GetIncludeRegularExpression() const { - return this->IncludeFileRegularExpression.c_str(); + return this->GetProperty("INCLUDE_REGULAR_EXPRESSION"); } /** @@ -445,6 +408,7 @@ public: { this->GeneratorTargets = targets; } + void AddGeneratorTarget(cmTarget* t, cmGeneratorTarget* gt); cmTarget* FindTarget(const std::string& name, bool excludeAliases = false) const; @@ -506,7 +470,7 @@ public: * cacheonly is specified and is greater than 0, then only cache * variables will be listed. */ - std::vector<std::string> GetDefinitions(int cacheonly=0) const; + std::vector<std::string> GetDefinitions() const; /** * Test a boolean variable to see if it is true or false. @@ -520,6 +484,9 @@ public: /** Return whether the target platform is 64-bit. */ bool PlatformIs64Bit() const; + /** Return whether the target platform is Apple iOS. */ + bool PlatformIsAppleIos() const; + /** Retrieve soname flag for the specified language if supported */ const char* GetSONameFlag(const std::string& language) const; @@ -563,6 +530,7 @@ public: * Get the current context backtrace. */ cmListFileBacktrace GetBacktrace() const; + cmListFileBacktrace GetBacktrace(cmCommandContext const& lfc) const; cmListFileContext GetExecutionContext() const; /** @@ -658,10 +626,12 @@ public: * variable replacement and list expansion. */ bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs, - std::vector<std::string>& outArgs) const; + std::vector<std::string>& outArgs, + const char* filename = 0) const; bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs, - std::vector<cmExpandedCommandArgument>& outArgs) const; + std::vector<cmExpandedCommandArgument>& outArgs, + const char* filename = 0) const; /** * Get the instance @@ -682,12 +652,6 @@ public: */ cmSourceFile *GetSourceFileWithOutput(const std::string& outName) const; - /** - * Add a macro to the list of macros. The arguments should be name of the - * macro and a documentation signature of it - */ - void AddMacro(const char* name); - ///! Add a new cmTest to the list of tests for this makefile. cmTest* CreateTest(const std::string& testName); @@ -697,11 +661,6 @@ public: cmTest* GetTest(const std::string& testName) const; /** - * Get a list of macros as a ; separated string - */ - void GetListOfMacros(std::string& macros) const; - - /** * Return a location of a file in cmake or custom modules directory */ std::string GetModulesFile(const char* name) const; @@ -711,18 +670,12 @@ public: void AppendProperty(const std::string& prop, const char *value, bool asString=false); const char *GetProperty(const std::string& prop) const; - const char *GetProperty(const std::string& prop, - cmProperty::ScopeType scope) const; + const char *GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; - - const char* GetFeature(const std::string& feature, - const std::string& config); - - // Get the properties - cmPropertyMap &GetProperties() { return this->Properties; } + std::vector<std::string> GetPropertyKeys() const; ///! Initialize a makefile from its parent - void InitializeFromParent(); + void InitializeFromParent(cmMakefile* parent); void AddInstallGenerator(cmInstallGenerator* g) { if(g) this->InstallGenerators.push_back(g); } @@ -734,7 +687,38 @@ public: const std::vector<cmTestGenerator*>& GetTestGenerators() const { return this->TestGenerators; } - // push and pop variable scopes + class FunctionPushPop + { + public: + FunctionPushPop(cmMakefile* mf, std::string const& fileName, + cmPolicies::PolicyMap const& pm); + ~FunctionPushPop(); + + void Quiet() { this->ReportError = false; } + private: + cmMakefile* Makefile; + bool ReportError; + }; + + class MacroPushPop + { + public: + MacroPushPop(cmMakefile* mf, std::string const& fileName, + cmPolicies::PolicyMap const& pm); + ~MacroPushPop(); + + void Quiet() { this->ReportError = false; } + private: + cmMakefile* Makefile; + bool ReportError; + }; + + void PushFunctionScope(std::string const& fileName, + cmPolicies::PolicyMap const& pm); + void PopFunctionScope(bool reportError); + void PushMacroScope(std::string const& fileName, + cmPolicies::PolicyMap const& pm); + void PopMacroScope(bool reportError); void PushScope(); void PopScope(); void RaiseScope(const std::string& var, const char *value); @@ -759,21 +743,15 @@ public: /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } - const std::vector<cmValueWithOrigin>& GetIncludeDirectoriesEntries() const - { - return this->IncludeDirectoriesEntries; - } - const std::vector<cmValueWithOrigin>& GetCompileOptionsEntries() const - { - return this->CompileOptionsEntries; - } - const std::vector<cmValueWithOrigin>& GetCompileDefinitionsEntries() const - { - return this->CompileDefinitionsEntries; - } + cmStringRange GetIncludeDirectoriesEntries() const; + cmBacktraceRange GetIncludeDirectoriesBacktraces() const; + cmStringRange GetCompileOptionsEntries() const; + cmBacktraceRange GetCompileOptionsBacktraces() const; + cmStringRange GetCompileDefinitionsEntries() const; + cmBacktraceRange GetCompileDefinitionsBacktraces() const; - bool IsGeneratingBuildSystem() const { return this->GeneratingBuildSystem; } - void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; } + bool IsConfigured() const { return this->Configured; } + void SetConfigured(){ this->Configured = true; } void AddQtUiFileWithOptions(cmSourceFile *sf); std::vector<cmSourceFile*> GetQtUiFilesWithOptions() const; @@ -807,6 +785,20 @@ public: void ClearMatches(); void StoreMatches(cmsys::RegularExpression& re); + cmState::Snapshot GetStateSnapshot() const; + + const char* GetDefineFlagsCMP0059() const; + + std::string GetExecutionFilePath() const; + + void EnforceDirectoryLevelRules() const; + + void AddEvaluationFile(const std::string &inputFile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent); + std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const; + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const std::string& name, cmTarget& target); @@ -814,7 +806,7 @@ protected: // Check for a an unused variable void LogUnused(const char* reason, const std::string& name) const; - std::string ProjectName; // project name + mutable std::set<cmListFileContext> CMP0054ReportedIds; // libraries, classes, and executables mutable cmTargets Targets; @@ -849,16 +841,11 @@ protected: std::vector<cmInstallGenerator*> InstallGenerators; std::vector<cmTestGenerator*> TestGenerators; - std::string IncludeFileRegularExpression; std::string ComplainFileRegularExpression; std::vector<std::string> SourceFileExtensions; std::vector<std::string> HeaderFileExtensions; std::string DefineFlags; - std::vector<cmValueWithOrigin> IncludeDirectoriesEntries; - std::vector<cmValueWithOrigin> CompileOptionsEntries; - std::vector<cmValueWithOrigin> CompileDefinitionsEntries; - // Track the value of the computed DEFINITIONS property. void AddDefineFlag(const char*, std::string&); void RemoveDefineFlag(const char*, std::string::size_type, std::string&); @@ -869,7 +856,7 @@ protected: #endif std::vector<cmCommand*> FinalPassCommands; - cmLocalGenerator* LocalGenerator; + cmGlobalGenerator* GlobalGenerator; bool IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus &status); @@ -879,13 +866,8 @@ private: cmState::Snapshot StateSnapshot; - bool ReadListFile(const char* listfile, - bool noPolicyScope, - bool requireProjectCommand); - - bool ReadListFileInternal(const char* filenametoread, - bool noPolicyScope, - bool requireProjectCommand); + void ReadListFile(cmListFile const& listFile, + const std::string& filenametoread); bool ParseDefineFlag(std::string const& definition, bool remove); @@ -904,31 +886,19 @@ private: std::stack<int> LoopBlockCounter; - std::vector<std::string> MacrosList; - mutable cmsys::RegularExpression cmDefineRegex; mutable cmsys::RegularExpression cmDefine01Regex; mutable cmsys::RegularExpression cmAtVarRegex; mutable cmsys::RegularExpression cmNamedCurly; - cmPropertyMap Properties; - - // Unused variable flags - bool WarnUnused; - bool CheckSystemVars; + std::vector<cmMakefile*> UnConfiguredDirectories; - // stack of list files being read - std::vector<std::string> ListFileStack; + std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; - // stack of commands being invoked. - struct CallStackEntry - { - cmListFileContext const* Context; - cmExecutionStatus* Status; - }; - typedef std::vector<CallStackEntry> CallStackType; - CallStackType CallStack; + std::vector<cmCommandContext const*> ContextStack; + std::vector<cmExecutionStatus*> ExecutionStatusStack; friend class cmMakefileCall; + friend class cmParseFileScope; std::vector<cmTarget*> ImportedTargetsOwned; TargetMap ImportedTargets; @@ -937,31 +907,15 @@ private: void PushPolicy(bool weak = false, cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap()); void PopPolicy(); - void PushPolicyBarrier(); void PopPolicyBarrier(bool reportError = true); friend class cmCMakePolicyCommand; class IncludeScope; friend class IncludeScope; + class ListFileScope; + friend class ListFileScope; + class BuildsystemFileScope; + friend class BuildsystemFileScope; - // stack of policy settings - struct PolicyStackEntry: public cmPolicies::PolicyMap - { - typedef cmPolicies::PolicyMap derived; - PolicyStackEntry(bool w = false): derived(), Weak(w) {} - PolicyStackEntry(derived const& d, bool w = false): derived(d), Weak(w) {} - PolicyStackEntry(PolicyStackEntry const& r): derived(r), Weak(r.Weak) {} - bool Weak; - }; - typedef std::vector<PolicyStackEntry> PolicyStackType; - PolicyStackType PolicyStack; - std::vector<PolicyStackType::size_type> PolicyBarriers; - cmPolicies::PolicyStatus - GetPolicyStatusInternal(cmPolicies::PolicyID id) const; - - bool CheckCMP0000; - - // Enforce rules about CMakeLists.txt files. - void EnforceDirectoryLevelRules() const; // CMP0053 == old cmake::MessageType ExpandVariablesInStringOld( @@ -985,7 +939,6 @@ private: long line, bool removeEmpty, bool replaceAt) const; - bool GeneratingBuildSystem; /** * Old version of GetSourceFileWithOutput(const std::string&) kept for * backward-compatibility. It implements a linear search and support @@ -1031,6 +984,12 @@ private: void CheckForUnusedVariables() const; + // Unused variable flags + bool WarnUnused; + bool CheckSystemVars; + bool CheckCMP0000; + bool Configured; + bool IsSourceFileTryCompile; mutable bool SuppressWatches; }; @@ -1040,16 +999,9 @@ class cmMakefileCall { public: cmMakefileCall(cmMakefile* mf, - cmListFileContext const& lfc, - cmExecutionStatus& status): Makefile(mf) - { - cmMakefile::CallStackEntry entry = {&lfc, &status}; - this->Makefile->CallStack.push_back(entry); - } - ~cmMakefileCall() - { - this->Makefile->CallStack.pop_back(); - } + cmCommandContext const& lfc, + cmExecutionStatus& status); + ~cmMakefileCall(); private: cmMakefile* Makefile; }; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 37b297e..ccb0974 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -22,10 +22,10 @@ //---------------------------------------------------------------------------- cmMakefileExecutableTargetGenerator ::cmMakefileExecutableTargetGenerator(cmGeneratorTarget* target): - cmMakefileTargetGenerator(target->Target) + cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnDepends; - this->Target->GetExecutableNames( + this->GeneratorTarget->GetExecutableNames( this->TargetNameOut, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, this->ConfigName); @@ -58,7 +58,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() // write the link rules this->WriteExecutableRule(false); - if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) + if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { // Write rules to link an installable version of the target. this->WriteExecutableRule(true); @@ -94,7 +94,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->GetExecutableNames + this->GeneratorTarget->GetExecutableNames (targetName, targetNameReal, targetNameImport, targetNamePDB, this->ConfigName); @@ -130,7 +130,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } std::string compilePdbOutputPath = - this->Target->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); @@ -161,7 +161,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the language to use for linking this executable. std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); // Make sure we have a link language. if(linkLanguage.empty()) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 450f573..2f995e8 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -18,16 +18,17 @@ #include "cmSourceFile.h" #include "cmTarget.h" #include "cmake.h" +#include "cmAlgorithms.h" //---------------------------------------------------------------------------- cmMakefileLibraryTargetGenerator ::cmMakefileLibraryTargetGenerator(cmGeneratorTarget* target): - cmMakefileTargetGenerator(target->Target) + cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnDepends; if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY) { - this->Target->GetLibraryNames( + this->GeneratorTarget->GetLibraryNames( this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, this->ConfigName); } @@ -68,7 +69,7 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmTarget::SHARED_LIBRARY: this->WriteSharedLibraryRules(false); - if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) + if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { // Write rules to link an installable version of the target. this->WriteSharedLibraryRules(true); @@ -76,7 +77,7 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmTarget::MODULE_LIBRARY: this->WriteModuleLibraryRules(false); - if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) + if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { // Write rules to link an installable version of the target. this->WriteModuleLibraryRules(true); @@ -132,7 +133,7 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_STATIC_LIBRARY"; @@ -158,7 +159,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) return; } std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_SHARED_LIBRARY"; @@ -182,7 +183,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_SHARED_MODULE"; @@ -205,7 +206,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) { std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_MACOSX_FRAMEWORK"; @@ -237,7 +238,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules // Get the language to use for linking this library. std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); // Make sure we have a link language. if(linkLanguage.empty()) @@ -265,7 +266,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->GetLibraryNames( + this->GeneratorTarget->GetLibraryNames( targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB, this->ConfigName); @@ -310,7 +311,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } std::string compilePdbOutputPath = - this->Target->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); @@ -563,6 +564,58 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules useResponseFileForObjects, buildObjs, depends, useWatcomQuote); + // maybe create .def file from list of objects + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if(this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + std::string name_of_def_file = + this->Target->GetSupportDirectory(); + name_of_def_file += std::string("/") + + this->Target->GetName(); + name_of_def_file += ".def"; + std::string cmd = cmSystemTools::GetCMakeCommand(); + cmd = this->Convert(cmd, cmLocalGenerator::NONE, + cmLocalGenerator::SHELL); + cmd += " -E __create_def "; + cmd += this->Convert(name_of_def_file, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + cmd += " "; + std::string objlist_file = name_of_def_file; + objlist_file += ".objs"; + cmd += this->Convert(objlist_file, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + real_link_commands.push_back(cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(objlist_file.c_str()); + for(std::vector<std::string>::const_iterator i = this->Objects.begin(); + i != this->Objects.end(); ++i) + { + if(cmHasLiteralSuffix(*i, ".obj")) + { + fout << *i << "\n"; + } + } + for(std::vector<std::string>::const_iterator i = + this->ExternalObjects.begin(); + i != this->ExternalObjects.end(); ++i) + { + fout << *i << "\n"; + } + // now add the def file link flag + linkFlags += " "; + linkFlags += + this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); + linkFlags += this->Convert(name_of_def_file, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + linkFlags += " "; + } + } + cmLocalGenerator::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); @@ -600,7 +653,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); - if (this->Target->HasSOName(this->ConfigName)) + if (this->GeneratorTarget->HasSOName(this->ConfigName)) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); vars.TargetSOName= targetNameSO.c_str(); @@ -613,7 +666,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules { // Get the install_name directory for the build tree. install_name_dir = - this->Target->GetInstallNameDirForBuildTree(this->ConfigName); + this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName); // Set the rule variable replacement value. if(install_name_dir.empty()) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 7b88bc7..cf88a74 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -32,25 +32,20 @@ #include <ctype.h> -cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target) - : OSXBundleGenerator(0) +cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) + : cmCommonTargetGenerator(cmOutputConverter::START_OUTPUT, target) + , OSXBundleGenerator(0) , MacOSXContentGenerator(0) { this->BuildFileStream = 0; this->InfoFileStream = 0; this->FlagFileStream = 0; this->CustomCommandDriver = OnBuild; - this->FortranModuleDirectoryComputed = false; - this->Target = target; - this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = - static_cast<cmLocalUnixMakefileGenerator3*>( - this->Makefile->GetLocalGenerator()); - this->ConfigName = this->LocalGenerator->ConfigurationName.c_str(); + static_cast<cmLocalUnixMakefileGenerator3*>(target->GetLocalGenerator()); this->GlobalGenerator = static_cast<cmGlobalUnixMakefileGenerator3*>( this->LocalGenerator->GetGlobalGenerator()); - this->GeneratorTarget = this->GlobalGenerator->GetGeneratorTarget(target); cmake* cm = this->GlobalGenerator->GetCMakeInstance(); this->NoRuleMessages = false; if(const char* ruleStatus = cm->GetState() @@ -172,7 +167,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() { cmCustomCommandGenerator ccg(*(*si)->GetCustomCommand(), this->ConfigName, - this->Makefile); + this->LocalGenerator); this->GenerateCustomRuleFile(ccg); if (clean) { @@ -277,85 +272,11 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << "\n\n"; } -//---------------------------------------------------------------------------- -std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) -{ - ByLanguageMap::iterator i = this->FlagsByLanguage.find(l); - if (i == this->FlagsByLanguage.end()) - { - std::string flags; - const char *lang = l.c_str(); - - // Add language feature flags. - this->AddFeatureFlags(flags, lang); - - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - lang, this->ConfigName); - - // Fortran-specific flags computed for this target. - if(l == "Fortran") - { - this->AddFortranFlags(flags); - } - - this->LocalGenerator->AddCMP0018Flags(flags, this->Target, - lang, this->ConfigName); - - this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, - lang); - - // Add include directory flags. - this->AddIncludeFlags(flags, lang); - - // Append old-style preprocessor definition flags. - this->LocalGenerator-> - AppendFlags(flags, this->Makefile->GetDefineFlags()); - - // Add include directory flags. - this->LocalGenerator-> - AppendFlags(flags,this->GetFrameworkFlags(l)); - - // Add target-specific flags. - this->LocalGenerator->AddCompileOptions(flags, this->Target, - lang, this->ConfigName); - - ByLanguageMap::value_type entry(l, flags); - i = this->FlagsByLanguage.insert(entry).first; - } - return i->second; -} - -std::string cmMakefileTargetGenerator::GetDefines(const std::string &l) -{ - ByLanguageMap::iterator i = this->DefinesByLanguage.find(l); - if (i == this->DefinesByLanguage.end()) - { - std::set<std::string> defines; - const char *lang = l.c_str(); - // Add the export symbol definition for shared library objects. - if(const char* exportMacro = this->Target->GetExportMacro()) - { - this->LocalGenerator->AppendDefines(defines, exportMacro); - } - - // Add preprocessor definitions for this target and configuration. - this->LocalGenerator->AddCompileDefinitions(defines, this->Target, - this->LocalGenerator->ConfigurationName, l); - - std::string definesString; - this->LocalGenerator->JoinDefines(defines, definesString, lang); - - ByLanguageMap::value_type entry(l, definesString); - i = this->DefinesByLanguage.insert(entry).first; - } - return i->second; -} - void cmMakefileTargetGenerator::WriteTargetLanguageFlags() { // write language flags for target std::set<std::string> languages; - this->Target->GetLanguages(languages, + this->GeneratorTarget->GetLanguages(languages, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); // put the compiler in the rules.make file so that if it changes // things rebuild @@ -374,11 +295,14 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() { std::string flags = this->GetFlags(*l); std::string defines = this->GetDefines(*l); + std::string includes = this->GetIncludes(*l); // Escape comment characters so they do not terminate assignment. cmSystemTools::ReplaceString(flags, "#", "\\#"); cmSystemTools::ReplaceString(defines, "#", "\\#"); + cmSystemTools::ReplaceString(includes, "#", "\\#"); *this->FlagFileStream << *l << "_FLAGS = " << flags << "\n\n"; *this->FlagFileStream << *l << "_DEFINES = " << defines << "\n\n"; + *this->FlagFileStream << *l << "_INCLUDES = " << includes << "\n\n"; } } @@ -389,7 +313,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator() (cmSourceFile const& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(!this->Generator->GetTarget()->IsBundleOnApple()) + if(!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { return; } @@ -490,7 +414,6 @@ void cmMakefileTargetGenerator // we compute some depends when writing the depend.make that we will also // use in the build.make, same with depMakeFile std::vector<std::string> depends; - std::string depMakeFile; // generate the build rule file this->WriteObjectBuildFile(obj, lang, source, depends); @@ -512,35 +435,6 @@ void cmMakefileTargetGenerator //---------------------------------------------------------------------------- void cmMakefileTargetGenerator -::AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source) -{ - const char* srcfmt = source.GetProperty("Fortran_FORMAT"); - cmLocalGenerator::FortranFormat format = - this->LocalGenerator->GetFortranFormat(srcfmt); - if(format == cmLocalGenerator::FortranFormatNone) - { - const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT"); - format = this->LocalGenerator->GetFortranFormat(tgtfmt); - } - const char* var = 0; - switch (format) - { - case cmLocalGenerator::FortranFormatFixed: - var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break; - case cmLocalGenerator::FortranFormatFree: - var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break; - default: break; - } - if(var) - { - this->LocalGenerator->AppendFlags( - flags, this->Makefile->GetDefinition(var)); - } -} - -//---------------------------------------------------------------------------- -void -cmMakefileTargetGenerator ::WriteObjectBuildFile(std::string &obj, const std::string& lang, cmSourceFile const& source, @@ -568,7 +462,7 @@ cmMakefileTargetGenerator this->LocalGenerator->AppendFlags(flags, langFlags); std::string configUpper = - cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); + cmSystemTools::UpperCase(this->LocalGenerator->GetConfigName()); // Add Fortran format flags. if(lang == "Fortran") @@ -614,13 +508,7 @@ cmMakefileTargetGenerator } // Get the output paths for source and object files. - std::string sourceFile = source.GetFullPath(); - if(this->LocalGenerator->UseRelativePaths) - { - sourceFile = this->Convert(sourceFile, - cmLocalGenerator::START_OUTPUT); - } - sourceFile = this->Convert(sourceFile, + std::string sourceFile = this->Convert(source.GetFullPath(), cmLocalGenerator::NONE, cmLocalGenerator::SHELL); @@ -657,15 +545,15 @@ cmMakefileTargetGenerator this->Target->GetType() == cmTarget::MODULE_LIBRARY) { targetFullPathReal = - this->Target->GetFullPath(this->ConfigName, false, true); + this->GeneratorTarget->GetFullPath(this->ConfigName, false, true); targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName); targetFullPathPDB += "/"; - targetFullPathPDB += this->Target->GetPDBName(this->ConfigName); + targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName); } if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) { targetFullPathCompilePDB = - this->Target->GetCompilePDBPath(this->ConfigName); + this->GeneratorTarget->GetCompilePDBPath(this->ConfigName); if(targetFullPathCompilePDB.empty()) { targetFullPathCompilePDB = this->Target->GetSupportDirectory() + "/"; @@ -725,6 +613,9 @@ cmMakefileTargetGenerator vars.Defines = definesString.c_str(); + std::string const includesString = "$(" + lang + "_INCLUDES)"; + vars.Includes = includesString.c_str(); + // At the moment, it is assumed that C, C++, and Fortran have both // assembly and preprocessor capabilities. The same is true for the // ability to export compile commands @@ -757,6 +648,9 @@ cmMakefileTargetGenerator std::string langDefines = std::string("$(") + lang + "_DEFINES)"; compileCommand.replace(compileCommand.find(langDefines), langDefines.size(), this->GetDefines(lang)); + std::string langIncludes = std::string("$(") + lang + "_INCLUDES)"; + compileCommand.replace(compileCommand.find(langIncludes), + langIncludes.size(), this->GetIncludes(lang)); this->GlobalGenerator->AddCXXCompileCommand( source.GetFullPath(), workingDirectory, compileCommand); } @@ -775,6 +669,25 @@ cmMakefileTargetGenerator } } + // Maybe insert a compiler launcher like ccache or distcc + if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) + { + std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; + const char *clauncher = this->Target->GetProperty(clauncher_prop); + if (clauncher && *clauncher) + { + std::vector<std::string> launcher_cmd; + cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true); + for (std::vector<std::string>::iterator i = launcher_cmd.begin(), + e = launcher_cmd.end(); i != e; ++i) + { + *i = this->LocalGenerator->EscapeForShell(*i); + } + std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " "; + compileCommands.front().insert(0, run_launcher); + } + } + // Expand placeholders in the commands. for(std::vector<std::string>::iterator i = compileCommands.begin(); i != compileCommands.end(); ++i) @@ -1132,8 +1045,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() pi != this->MultipleOutputPairs.end(); ++pi) { *this->InfoFileStream - << " " << cmLocalGenerator::EscapeForCMake(pi->first) - << " " << cmLocalGenerator::EscapeForCMake(pi->second) + << " " << cmOutputConverter::EscapeForCMake(pi->first) + << " " << cmOutputConverter::EscapeForCMake(pi->second) << "\n"; } *this->InfoFileStream << " )\n\n"; @@ -1145,44 +1058,21 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "\n" << "# Targets to which this target links.\n" << "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; - std::set<cmTarget const*> emitted; - const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) + std::vector<std::string> dirs = this->GetLinkedTargetDirectories(); + for (std::vector<std::string>::iterator i = dirs.begin(); + i != dirs.end(); ++i) { - cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); - for(cmComputeLinkInformation::ItemVector::const_iterator - i = items.begin(); i != items.end(); ++i) - { - cmTarget const* linkee = i->Target; - if(linkee && !linkee->IsImported() - // We can ignore the INTERFACE_LIBRARY items because - // Target->GetLinkInformation already processed their - // link interface and they don't have any output themselves. - && linkee->GetType() != cmTarget::INTERFACE_LIBRARY - && emitted.insert(linkee).second) - { - cmMakefile* mf = linkee->GetMakefile(); - cmLocalGenerator* lg = mf->GetLocalGenerator(); - std::string di = mf->GetCurrentBinaryDirectory(); - di += "/"; - di += lg->GetTargetDirectory(*linkee); - di += "/DependInfo.cmake"; - *this->InfoFileStream << " \"" << di << "\"\n"; - } - } + *this->InfoFileStream << " \"" << *i << "/DependInfo.cmake\"\n"; } *this->InfoFileStream << " )\n"; } - // Check for a target-specific module output directory. - if(const char* mdir = this->GetFortranModuleDirectory()) - { - *this->InfoFileStream - << "\n" - << "# Fortran module output directory.\n" - << "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n"; - } + *this->InfoFileStream + << "\n" + << "# Fortran module output directory.\n" + << "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" + << this->GetFortranModuleDirectory() << "\")\n"; // and now write the rule to use it std::vector<std::string> depends; @@ -1266,7 +1156,8 @@ cmMakefileTargetGenerator { if(cmCustomCommand* cc = (*source)->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->ConfigName, this->Makefile); + cmCustomCommandGenerator ccg(*cc, this->ConfigName, + this->LocalGenerator); const std::vector<std::string>& outputs = ccg.GetOutputs(); depends.insert(depends.end(), outputs.begin(), outputs.end()); } @@ -1544,68 +1435,6 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule( } //---------------------------------------------------------------------------- -std::string cmMakefileTargetGenerator::GetFrameworkFlags(std::string const& l) -{ - if(!this->Makefile->IsOn("APPLE")) - { - return std::string(); - } - - std::string fwSearchFlagVar = "CMAKE_" + l + "_FRAMEWORK_SEARCH_FLAG"; - const char* fwSearchFlag = - this->Makefile->GetDefinition(fwSearchFlagVar); - if(!(fwSearchFlag && *fwSearchFlag)) - { - return std::string(); - } - - std::set<std::string> emitted; -#ifdef __APPLE__ /* don't insert this when crosscompiling e.g. to iphone */ - emitted.insert("/System/Library/Frameworks"); -#endif - std::vector<std::string> includes; - - const std::string& config = - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - this->LocalGenerator->GetIncludeDirectories(includes, - this->GeneratorTarget, - "C", config); - // check all include directories for frameworks as this - // will already have added a -F for the framework - for(std::vector<std::string>::iterator i = includes.begin(); - i != includes.end(); ++i) - { - if(this->Target->NameResolvesToFramework(*i)) - { - std::string frameworkDir = *i; - frameworkDir += "/../"; - frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); - emitted.insert(frameworkDir); - } - } - - std::string flags; - const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) - { - std::vector<std::string> const& frameworks = cli->GetFrameworkPaths(); - for(std::vector<std::string>::const_iterator i = frameworks.begin(); - i != frameworks.end(); ++i) - { - if(emitted.insert(*i).second) - { - flags += fwSearchFlag; - flags += this->Convert(*i, - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL, true); - flags += " "; - } - } - } - return flags; -} - -//---------------------------------------------------------------------------- void cmMakefileTargetGenerator ::AppendTargetDepends(std::vector<std::string>& depends) { @@ -1616,8 +1445,9 @@ void cmMakefileTargetGenerator } // Loop over all library dependencies. - const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) + const char* cfg = this->LocalGenerator->GetConfigName().c_str(); + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(cfg)) { std::vector<std::string> const& libDeps = cli->GetDepends(); depends.insert(depends.end(), libDeps.begin(), libDeps.end()); @@ -1658,11 +1488,9 @@ void cmMakefileTargetGenerator this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. - std::string def = this->GeneratorTarget->GetModuleDefinitionFile( - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); - if(!def.empty()) + if(!this->ModuleDefinitionFile.empty()) { - depends.push_back(def); + depends.push_back(this->ModuleDefinitionFile); } // Add user-specified dependencies. @@ -1681,7 +1509,7 @@ std::string cmMakefileTargetGenerator::GetLinkRule( if(this->Target->HasImplibGNUtoMS()) { std::string ruleVar = "CMAKE_"; - ruleVar += this->Target->GetLinkerLanguage(this->ConfigName); + ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); ruleVar += "_GNUtoMS_RULE"; if(const char* rule = this->Makefile->GetDefinition(ruleVar)) { @@ -1835,7 +1663,8 @@ cmMakefileTargetGenerator { // Lookup the response file reference flag. std::string responseFlagVar = "CMAKE_"; - responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName); + responseFlagVar += this->GeneratorTarget + ->GetLinkerLanguage(this->ConfigName); responseFlagVar += "_RESPONSE_FILE_LINK_FLAG"; const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); @@ -1879,7 +1708,8 @@ cmMakefileTargetGenerator // Lookup the response file reference flag. std::string responseFlagVar = "CMAKE_"; - responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName); + responseFlagVar += this->GeneratorTarget + ->GetLinkerLanguage(this->ConfigName); responseFlagVar += "_RESPONSE_FILE_LINK_FLAG"; const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); @@ -1969,149 +1799,3 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, this->LocalGenerator->AppendFlags(flags, includeFlags); } } - -//---------------------------------------------------------------------------- -const char* cmMakefileTargetGenerator::GetFortranModuleDirectory() -{ - // Compute the module directory. - if(!this->FortranModuleDirectoryComputed) - { - const char* target_mod_dir = - this->Target->GetProperty("Fortran_MODULE_DIRECTORY"); - const char* moddir_flag = - this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG"); - if(target_mod_dir && moddir_flag) - { - // Compute the full path to the module directory. - if(cmSystemTools::FileIsFullPath(target_mod_dir)) - { - // Already a full path. - this->FortranModuleDirectory = target_mod_dir; - } - else - { - // Interpret relative to the current output directory. - this->FortranModuleDirectory = - this->Makefile->GetCurrentBinaryDirectory(); - this->FortranModuleDirectory += "/"; - this->FortranModuleDirectory += target_mod_dir; - } - - // Make sure the module output directory exists. - cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str()); - } - this->FortranModuleDirectoryComputed = true; - } - - // Return the computed directory. - if(this->FortranModuleDirectory.empty()) - { - return 0; - } - else - { - return this->FortranModuleDirectory.c_str(); - } -} - -//---------------------------------------------------------------------------- -void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) -{ - // Enable module output if necessary. - if(const char* modout_flag = - this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG")) - { - this->LocalGenerator->AppendFlags(flags, modout_flag); - } - - // Add a module output directory flag if necessary. - const char* mod_dir = this->GetFortranModuleDirectory(); - if(!mod_dir) - { - mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT"); - } - if(mod_dir) - { - const char* moddir_flag = - this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"); - std::string modflag = moddir_flag; - modflag += this->Convert(mod_dir, - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL); - this->LocalGenerator->AppendFlags(flags, modflag); - } - - // If there is a separate module path flag then duplicate the - // include path with it. This compiler does not search the include - // path for modules. - if(const char* modpath_flag = - this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) - { - std::vector<std::string> includes; - const std::string& config = - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - this->LocalGenerator->GetIncludeDirectories(includes, - this->GeneratorTarget, - "C", config); - for(std::vector<std::string>::const_iterator idi = includes.begin(); - idi != includes.end(); ++idi) - { - std::string flg = modpath_flag; - flg += this->Convert(*idi, - cmLocalGenerator::NONE, - cmLocalGenerator::SHELL); - this->LocalGenerator->AppendFlags(flags, flg); - } - } -} - -//---------------------------------------------------------------------------- -void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) -{ - std::string def = this->GeneratorTarget->GetModuleDefinitionFile( - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); - if(def.empty()) - { - return; - } - - // TODO: Create a per-language flag variable. - const char* defFileFlag = - this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); - if(!defFileFlag) - { - return; - } - - // Append the flag and value. Use ConvertToLinkReference to help - // vs6's "cl -link" pass it to the linker. - std::string flag = defFileFlag; - flag += (this->LocalGenerator->ConvertToLinkReference(def)); - this->LocalGenerator->AppendFlags(flags, flag); -} - -//---------------------------------------------------------------------------- -const char* cmMakefileTargetGenerator::GetFeature(const std::string& feature) -{ - return this->Target->GetFeature(feature, this->ConfigName); -} - -//---------------------------------------------------------------------------- -bool cmMakefileTargetGenerator::GetFeatureAsBool(const std::string& feature) -{ - return this->Target->GetFeatureAsBool(feature, this->ConfigName); -} - -//---------------------------------------------------------------------------- -void cmMakefileTargetGenerator::AddFeatureFlags( - std::string& flags, const std::string& lang - ) -{ - // Add language-specific flags. - this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName); - - if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) - { - this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); - } -} diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 58044e8..fd4527b 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -12,6 +12,8 @@ #ifndef cmMakefileTargetGenerator_h #define cmMakefileTargetGenerator_h +#include "cmCommonTargetGenerator.h" + #include "cmLocalUnixMakefileGenerator3.h" #include "cmOSXBundleGenerator.h" @@ -30,11 +32,11 @@ class cmSourceFile; * \brief Support Routines for writing makefiles * */ -class cmMakefileTargetGenerator +class cmMakefileTargetGenerator: public cmCommonTargetGenerator { public: // constructor to set the ivars - cmMakefileTargetGenerator(cmTarget* target); + cmMakefileTargetGenerator(cmGeneratorTarget* target); virtual ~cmMakefileTargetGenerator(); // construct using this factory call @@ -51,6 +53,7 @@ public: { return this->ProgressFileNameFull; } cmTarget* GetTarget() { return this->Target;} + cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget;} protected: @@ -124,12 +127,6 @@ protected: void DriveCustomCommands(std::vector<std::string>& depends); - // Return the a string with -F flags on apple - std::string GetFrameworkFlags(std::string const& l); - - void AppendFortranFormatFlags(std::string& flags, - cmSourceFile const& source); - // append intertarget dependencies void AppendTargetDepends(std::vector<std::string>& depends); @@ -173,12 +170,8 @@ protected: virtual void CloseFileStreams(); void RemoveForbiddenFlags(const char* flagVar, const std::string& linkLang, std::string& linkFlags); - cmTarget *Target; - cmGeneratorTarget* GeneratorTarget; cmLocalUnixMakefileGenerator3 *LocalGenerator; cmGlobalUnixMakefileGenerator3 *GlobalGenerator; - cmMakefile *Makefile; - std::string ConfigName; enum CustomCommandDriveType { OnBuild, OnDepends, OnUtility }; CustomCommandDriveType CustomCommandDriver; @@ -242,43 +235,6 @@ protected: std::set<std::string> MacContentFolders; cmOSXBundleGenerator* OSXBundleGenerator; MacOSXContentGeneratorType* MacOSXContentGenerator; - - typedef std::map<std::string, std::string> ByLanguageMap; - std::string GetFlags(const std::string &l); - ByLanguageMap FlagsByLanguage; - std::string GetDefines(const std::string &l); - ByLanguageMap DefinesByLanguage; - - // Target-wide Fortran module output directory. - bool FortranModuleDirectoryComputed; - std::string FortranModuleDirectory; - const char* GetFortranModuleDirectory(); - - // Compute target-specific Fortran language flags. - void AddFortranFlags(std::string& flags); - - // Helper to add flag for windows .def file. - void AddModuleDefinitionFlag(std::string& flags); - - // Add language feature flags. - void AddFeatureFlags(std::string& flags, const std::string& lang); - - // Feature query methods. - const char* GetFeature(const std::string& feature); - bool GetFeatureAsBool(const std::string& feature); - - //================================================================== - // Convenience routines that do nothing more than forward to - // implementaitons - std::string Convert(const std::string& source, - cmLocalGenerator::RelativeRoot relative, - cmLocalGenerator::OutputFormat output = - cmLocalGenerator::UNCHANGED, - bool optional = false) - { - return this->LocalGenerator->Convert(source, relative, output, optional); - } - }; #endif diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 25d929c..303ca63 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -21,7 +21,7 @@ //---------------------------------------------------------------------------- cmMakefileUtilityTargetGenerator ::cmMakefileUtilityTargetGenerator(cmGeneratorTarget* target): - cmMakefileTargetGenerator(target->Target) + cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnUtility; this->OSXBundleGenerator = new cmOSXBundleGenerator(target, diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 0449c50..467555f 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -43,7 +43,19 @@ bool cmMessageCommand } else if (*i == "AUTHOR_WARNING") { - type = cmake::AUTHOR_WARNING; + if (this->Makefile->IsOn("CMAKE_ERROR_DEVELOPER_WARNINGS")) + { + fatal = true; + type = cmake::AUTHOR_ERROR; + } + else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) + { + type = cmake::AUTHOR_WARNING; + } + else + { + return true; + } ++i; } else if (*i == "STATUS") @@ -69,7 +81,7 @@ bool cmMessageCommand ++i; } - std::string message = cmJoin(cmRange(i, args.end()), std::string()); + std::string message = cmJoin(cmMakeRange(i, args.end()), std::string()); if (type != cmake::MESSAGE) { diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index bbf03ff..b855bea 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -32,7 +32,7 @@ cmNinjaNormalTargetGenerator:: cmNinjaNormalTargetGenerator(cmGeneratorTarget* target) - : cmNinjaTargetGenerator(target->Target) + : cmNinjaTargetGenerator(target) , TargetNameOut() , TargetNameSO() , TargetNameReal() @@ -40,16 +40,15 @@ cmNinjaNormalTargetGenerator(cmGeneratorTarget* target) , TargetNamePDB() , TargetLinkLanguage("") { - this->TargetLinkLanguage = target->Target - ->GetLinkerLanguage(this->GetConfigName()); + this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); if (target->GetType() == cmTarget::EXECUTABLE) - target->Target->GetExecutableNames(this->TargetNameOut, + this->GetGeneratorTarget()->GetExecutableNames(this->TargetNameOut, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, GetLocalGenerator()->GetConfigName()); else - target->Target->GetLibraryNames(this->TargetNameOut, + this->GetGeneratorTarget()->GetLibraryNames(this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, this->TargetNameImport, @@ -398,15 +397,16 @@ static int calculateCommandLineLengthLimit(int linkRuleLength) void cmNinjaNormalTargetGenerator::WriteLinkStatement() { cmTarget& target = *this->GetTarget(); + cmGeneratorTarget& gt = *this->GetGeneratorTarget(); const std::string cfgName = this->GetConfigName(); std::string targetOutput = ConvertToNinjaPath( - target.GetFullPath(cfgName)); + gt.GetFullPath(cfgName)); std::string targetOutputReal = ConvertToNinjaPath( - target.GetFullPath(cfgName, + gt.GetFullPath(cfgName, /*implib=*/false, /*realpath=*/true)); std::string targetOutputImplib = ConvertToNinjaPath( - target.GetFullPath(cfgName, + gt.GetFullPath(cfgName, /*implib=*/true)); if (target.IsAppBundleOnApple()) @@ -486,6 +486,22 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() linkPath, &genTarget, useWatcomQuote); + if(this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") + && target.GetType() == cmTarget::SHARED_LIBRARY) + { + if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + std::string dllname = targetOutput; + std::string name_of_def_file + = target.GetSupportDirectory(); + name_of_def_file += "/" + target.GetName(); + name_of_def_file += ".def "; + vars["LINK_FLAGS"] += " /DEF:"; + vars["LINK_FLAGS"] += this->GetLocalGenerator() + ->ConvertToOutputFormat(name_of_def_file.c_str(), + cmLocalGenerator::SHELL); + } + } this->addPoolNinjaVariable("JOB_POOL_LINK", &target, vars); @@ -514,13 +530,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (target.HasSOName(cfgName)) + if (this->GetGeneratorTarget()->HasSOName(cfgName)) { vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage); vars["SONAME"] = this->TargetNameSO; if (targetType == cmTarget::SHARED_LIBRARY) { - std::string install_dir = target.GetInstallNameDirForBuildTree(cfgName); + std::string install_dir = + this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.Convert(install_dir, @@ -530,6 +547,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } } + cmNinjaDeps byproducts; + if (!this->TargetNameImport.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( @@ -539,7 +558,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() EnsureParentDirectoryExists(impLibPath); if(target.HasImportLibrary()) { - outputs.push_back(targetOutputImplib); + byproducts.push_back(targetOutputImplib); } } @@ -550,7 +569,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string prefix; std::string base; std::string suffix; - target.GetFullNameComponents(prefix, base, suffix); + this->GetGeneratorTarget()->GetFullNameComponents(prefix, base, suffix); std::string dbg_suffix = ".dbg"; // TODO: Where to document? if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) @@ -585,14 +604,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() &postBuildCmdLines }; - cmNinjaDeps byproducts; for (unsigned i = 0; i != 3; ++i) { for (std::vector<cmCustomCommand>::const_iterator ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) { - cmCustomCommandGenerator ccg(*ci, cfgName, mf); + cmCustomCommandGenerator ccg(*ci, cfgName, this->GetLocalGenerator()); localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); std::transform(ccByproducts.begin(), ccByproducts.end(), @@ -600,6 +618,44 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } } + // maybe create .def file from list of objects + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + std::string cmakeCommand = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); + std::string dllname = targetOutput; + std::string name_of_def_file + = target.GetSupportDirectory(); + name_of_def_file += "/" + target.GetName(); + name_of_def_file += ".def"; + std::string cmd = cmakeCommand; + cmd += " -E __create_def "; + cmd += this->GetLocalGenerator() + ->ConvertToOutputFormat(name_of_def_file.c_str(), + cmLocalGenerator::SHELL); + cmd += " "; + cmNinjaDeps objs = this->GetObjects(); + std::string obj_list_file = name_of_def_file; + obj_list_file += ".objs"; + cmd += this->GetLocalGenerator() + ->ConvertToOutputFormat(obj_list_file.c_str(), + cmLocalGenerator::SHELL); + preLinkCmdLines.push_back(cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(obj_list_file.c_str()); + for(cmNinjaDeps::iterator i=objs.begin(); i != objs.end(); ++i) + { + if(cmHasLiteralSuffix(*i, ".obj")) + { + fout << *i << "\n"; + } + } + } + } // If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for // the link commands. if (!preLinkCmdLines.empty()) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 879d6b7..81fdde2 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -22,6 +22,7 @@ #include "cmComputeLinkInformation.h" #include "cmSourceFile.h" #include "cmCustomCommandGenerator.h" +#include "cmAlgorithms.h" #include <algorithm> @@ -56,19 +57,15 @@ cmNinjaTargetGenerator::New(cmGeneratorTarget* target) } } -cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target) - : +cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) + : cmCommonTargetGenerator(cmOutputConverter::HOME_OUTPUT, target), MacOSXContentGenerator(0), OSXBundleGenerator(0), MacContentFolders(), - Target(target), - Makefile(target->GetMakefile()), LocalGenerator( - static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())), + static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator())), Objects() { - this->GeneratorTarget = - this->GetGlobalGenerator()->GetGeneratorTarget(target); MacOSXContentGenerator = new MacOSXContentGeneratorType(this); } @@ -92,11 +89,6 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const return this->LocalGenerator->GetGlobalNinjaGenerator(); } -std::string const& cmNinjaTargetGenerator::GetConfigName() const -{ - return this->LocalGenerator->GetConfigName(); -} - std::string cmNinjaTargetGenerator::LanguageCompilerRule( const std::string& lang) const { @@ -104,31 +96,6 @@ std::string cmNinjaTargetGenerator::LanguageCompilerRule( cmGlobalNinjaGenerator::EncodeRuleName(this->Target->GetName()); } -// TODO: Picked up from cmMakefileTargetGenerator. Refactor it. -const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature) -{ - return this->Target->GetFeature(feature, this->GetConfigName()); -} - -// TODO: Picked up from cmMakefileTargetGenerator. Refactor it. -bool cmNinjaTargetGenerator::GetFeatureAsBool(const std::string& feature) -{ - return this->Target->GetFeatureAsBool(feature, this->GetConfigName()); -} - -// TODO: Picked up from cmMakefileTargetGenerator. Refactor it. -void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags, - const std::string& lang) -{ - // Add language-specific flags. - this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName()); - - if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) - { - this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); - } -} - std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() { @@ -143,71 +110,43 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile const* source, const std::string& language) { - // TODO: Fortran support. - // // Fortran-specific flags computed for this target. - // if(*l == "Fortran") - // { - // this->AddFortranFlags(flags); - // } - - bool hasLangCached = this->LanguageFlags.count(language) != 0; - std::string& languageFlags = this->LanguageFlags[language]; - if(!hasLangCached) - { - this->AddFeatureFlags(languageFlags, language); - - this->GetLocalGenerator()->AddArchitectureFlags(languageFlags, - this->GeneratorTarget, - language, - this->GetConfigName()); + std::string flags = this->GetFlags(language); - // Add shared-library flags if needed. - this->LocalGenerator->AddCMP0018Flags(languageFlags, this->Target, - language, - this->GetConfigName()); - - this->LocalGenerator->AddVisibilityPresetFlags(languageFlags, this->Target, - language); - - std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, - this->GeneratorTarget, - language, - this->GetConfigName()); - // Add include directory flags. - std::string includeFlags = - this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, - language, - language == "RC" ? true : false, // full include paths for RC - // needed by cmcldeps - false, - this->GetConfigName()); - if (this->GetGlobalGenerator()->IsGCCOnWindows()) - cmSystemTools::ReplaceString(includeFlags, "\\", "/"); - - this->LocalGenerator->AppendFlags(languageFlags, includeFlags); - - // Append old-style preprocessor definition flags. - this->LocalGenerator->AppendFlags(languageFlags, - this->Makefile->GetDefineFlags()); - - // Add target-specific flags. - this->LocalGenerator->AddCompileOptions(languageFlags, this->Target, - language, - this->GetConfigName()); + // Add Fortran format flags. + if(language == "Fortran") + { + this->AppendFortranFormatFlags(flags, *source); } - std::string flags = languageFlags; - // Add source file specific flags. this->LocalGenerator->AppendFlags(flags, source->GetProperty("COMPILE_FLAGS")); - // TODO: Handle Apple frameworks. - return flags; } +void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, + std::string const& language) +{ + std::vector<std::string> includes; + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + language, + this->GetConfigName()); + // Add include directory flags. + std::string includeFlags = + this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, + language, + language == "RC" ? true : false, // full include paths for RC + // needed by cmcldeps + false, + this->GetConfigName()); + if (this->GetGlobalGenerator()->IsGCCOnWindows()) + cmSystemTools::ReplaceString(includeFlags, "\\", "/"); + + this->LocalGenerator->AppendFlags(languageFlags, includeFlags); +} + bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const { if (lang == "C" || lang == "CXX") @@ -230,16 +169,6 @@ cmNinjaTargetGenerator:: ComputeDefines(cmSourceFile const* source, const std::string& language) { std::set<std::string> defines; - - // Add the export symbol definition for shared library objects. - if(const char* exportMacro = this->Target->GetExportMacro()) - { - this->LocalGenerator->AppendDefines(defines, exportMacro); - } - - // Add preprocessor definitions for this target and configuration. - this->LocalGenerator->AddCompileDefinitions(defines, this->Target, - this->GetConfigName(), language); this->LocalGenerator->AppendDefines (defines, source->GetProperty("COMPILE_DEFINITIONS")); @@ -251,7 +180,7 @@ ComputeDefines(cmSourceFile const* source, const std::string& language) source->GetProperty(defPropName)); } - std::string definesString; + std::string definesString = this->GetDefines(language); this->LocalGenerator->JoinDefines(defines, definesString, language); @@ -266,7 +195,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const return cmNinjaDeps(); cmComputeLinkInformation* cli = - this->Target->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); if(!cli) return cmNinjaDeps(); @@ -277,7 +206,16 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const // Add a dependency on the link definitions file, if any. if(!this->ModuleDefinitionFile.empty()) { - result.push_back(this->ModuleDefinitionFile); + result.push_back(this->ConvertToNinjaPath(this->ModuleDefinitionFile)); + } + + // Add user-specified dependencies. + if (const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS")) + { + std::vector<std::string> linkDeps; + cmSystemTools::ExpandListArgument(linkDepends, linkDeps); + std::transform(linkDeps.begin(), linkDeps.end(), + std::back_inserter(result), MapToNinjaPath()); } return result; @@ -344,11 +282,12 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const { pdbPath = this->Target->GetPDBDirectory(this->GetConfigName()); pdbPath += "/"; - pdbPath += this->Target->GetPDBName(this->GetConfigName()); + pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName()); } if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) { - compilePdbPath = this->Target->GetCompilePDBPath(this->GetConfigName()); + compilePdbPath = + this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName()); if(compilePdbPath.empty()) { compilePdbPath = this->Target->GetSupportDirectory() + "/"; @@ -392,6 +331,7 @@ cmNinjaTargetGenerator vars.Source = "$in"; vars.Object = "$out"; vars.Defines = "$DEFINES"; + vars.Includes = "$INCLUDES"; vars.TargetPDB = "$TARGET_PDB"; vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; @@ -475,6 +415,25 @@ cmNinjaTargetGenerator } } + // Maybe insert a compiler launcher like ccache or distcc + if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) + { + std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; + const char *clauncher = this->Target->GetProperty(clauncher_prop); + if (clauncher && *clauncher) + { + std::vector<std::string> launcher_cmd; + cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true); + for (std::vector<std::string>::iterator i = launcher_cmd.begin(), + e = launcher_cmd.end(); i != e; ++i) + { + *i = this->LocalGenerator->EscapeForShell(*i); + } + std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " "; + compileCmds.front().insert(0, run_launcher); + } + } + if (!compileCmds.empty()) { compileCmds.front().insert(0, cldeps); @@ -560,7 +519,7 @@ cmNinjaTargetGenerator { cmCustomCommand const* cc = *cci; cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->GetMakefile()); + this->GetLocalGenerator()); const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); const std::vector<std::string>& ccbyproducts= ccg.GetByproducts(); std::transform(ccoutputs.begin(), ccoutputs.end(), @@ -588,11 +547,6 @@ cmNinjaTargetGenerator { this->WriteObjectBuildStatement(*si, !orderOnlyDeps.empty()); } - std::string def = this->GeneratorTarget->GetModuleDefinitionFile(config); - if(!def.empty()) - { - this->ModuleDefinitionFile = this->ConvertToNinjaPath(def); - } this->GetBuildFileStream() << "\n"; } @@ -602,22 +556,39 @@ cmNinjaTargetGenerator ::WriteObjectBuildStatement( cmSourceFile const* source, bool writeOrderDependsTargetForTarget) { + std::string const language = source->GetLanguage(); + std::string const sourceFileName = + language=="RC" ? source->GetFullPath() : this->GetSourceFilePath(source); + std::string const objectDir = this->Target->GetSupportDirectory(); + std::string const objectFileName = this->GetObjectFilePath(source); + std::string const objectFileDir = + cmSystemTools::GetFilenamePath(objectFileName); + + cmNinjaVars vars; + vars["FLAGS"] = this->ComputeFlagsForObject(source, language); + vars["DEFINES"] = this->ComputeDefines(source, language); + vars["INCLUDES"] = this->GetIncludes(language); + if (!this->NeedDepTypeMSVC(language)) + { + vars["DEP_FILE"] = + cmGlobalNinjaGenerator::EncodeDepfileSpace(objectFileName + ".d"); + } + + this->ExportObjectCompileCommand( + language, sourceFileName, + objectDir, objectFileName, objectFileDir, + vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"] + ); + std::string comment; - const std::string language = source->GetLanguage(); std::string rule = this->LanguageCompilerRule(language); cmNinjaDeps outputs; - std::string objectFileName = this->GetObjectFilePath(source); outputs.push_back(objectFileName); // Add this object to the list of object files. this->Objects.push_back(objectFileName); cmNinjaDeps explicitDeps; - std::string sourceFileName; - if (language == "RC") - sourceFileName = source->GetFullPath(); - else - sourceFileName = this->GetSourceFilePath(source); explicitDeps.push_back(sourceFileName); cmNinjaDeps implicitDeps; @@ -652,20 +623,11 @@ cmNinjaTargetGenerator orderOnlyDeps); } - cmNinjaVars vars; - vars["FLAGS"] = this->ComputeFlagsForObject(source, language); - vars["DEFINES"] = this->ComputeDefines(source, language); - if (!this->NeedDepTypeMSVC(language)) { - vars["DEP_FILE"] = - cmGlobalNinjaGenerator::EncodeDepfileSpace(objectFileName + ".d"); - } EnsureParentDirectoryExists(objectFileName); - std::string objectDir = this->Target->GetSupportDirectory(); vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( ConvertToNinjaPath(objectDir), cmLocalGenerator::SHELL); - std::string objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); vars["OBJECT_FILE_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( ConvertToNinjaPath(objectFileDir), cmLocalGenerator::SHELL); @@ -674,53 +636,6 @@ cmNinjaTargetGenerator this->SetMsvcTargetPdbVariable(vars); - if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) - { - cmLocalGenerator::RuleVariables compileObjectVars; - std::string lang = language; - compileObjectVars.Language = lang.c_str(); - - std::string escapedSourceFileName = sourceFileName; - - if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) - { - escapedSourceFileName = cmSystemTools::CollapseFullPath( - escapedSourceFileName, - this->GetGlobalGenerator()->GetCMakeInstance()-> - GetHomeOutputDirectory()); - } - - escapedSourceFileName = - this->LocalGenerator->ConvertToOutputFormat( - escapedSourceFileName, cmLocalGenerator::SHELL); - - compileObjectVars.Source = escapedSourceFileName.c_str(); - compileObjectVars.Object = objectFileName.c_str(); - compileObjectVars.ObjectDir = objectDir.c_str(); - compileObjectVars.ObjectFileDir = objectFileDir.c_str(); - compileObjectVars.Flags = vars["FLAGS"].c_str(); - compileObjectVars.Defines = vars["DEFINES"].c_str(); - - // Rule for compiling object file. - std::string compileCmdVar = "CMAKE_"; - compileCmdVar += language; - compileCmdVar += "_COMPILE_OBJECT"; - std::string compileCmd = - this->GetMakefile()->GetRequiredDefinition(compileCmdVar); - std::vector<std::string> compileCmds; - cmSystemTools::ExpandListArgument(compileCmd, compileCmds); - - for (std::vector<std::string>::iterator i = compileCmds.begin(); - i != compileCmds.end(); ++i) - this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars); - - std::string cmdLine = - this->GetLocalGenerator()->BuildCommandLine(compileCmds); - - this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, - sourceFileName); - } - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), comment, rule, @@ -742,30 +657,67 @@ cmNinjaTargetGenerator } } -//---------------------------------------------------------------------------- void cmNinjaTargetGenerator -::AddModuleDefinitionFlag(std::string& flags) +::ExportObjectCompileCommand( + std::string const& language, + std::string const& sourceFileName, + std::string const& objectDir, + std::string const& objectFileName, + std::string const& objectFileDir, + std::string const& flags, + std::string const& defines, + std::string const& includes + ) { - if(this->ModuleDefinitionFile.empty()) + if(!this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) { return; } - // TODO: Create a per-language flag variable. - const char* defFileFlag = - this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); - if(!defFileFlag) + cmLocalGenerator::RuleVariables compileObjectVars; + compileObjectVars.Language = language.c_str(); + + std::string escapedSourceFileName = sourceFileName; + + if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) { - return; + escapedSourceFileName = cmSystemTools::CollapseFullPath( + escapedSourceFileName, + this->GetGlobalGenerator()->GetCMakeInstance()-> + GetHomeOutputDirectory()); } - // Append the flag and value. Use ConvertToLinkReference to help - // vs6's "cl -link" pass it to the linker. - std::string flag = defFileFlag; - flag += (this->LocalGenerator->ConvertToLinkReference( - this->ModuleDefinitionFile)); - this->LocalGenerator->AppendFlags(flags, flag); + escapedSourceFileName = + this->LocalGenerator->ConvertToOutputFormat( + escapedSourceFileName, cmLocalGenerator::SHELL); + + compileObjectVars.Source = escapedSourceFileName.c_str(); + compileObjectVars.Object = objectFileName.c_str(); + compileObjectVars.ObjectDir = objectDir.c_str(); + compileObjectVars.ObjectFileDir = objectFileDir.c_str(); + compileObjectVars.Flags = flags.c_str(); + compileObjectVars.Defines = defines.c_str(); + compileObjectVars.Includes = includes.c_str(); + + // Rule for compiling object file. + std::string compileCmdVar = "CMAKE_"; + compileCmdVar += language; + compileCmdVar += "_COMPILE_OBJECT"; + std::string compileCmd = + this->GetMakefile()->GetRequiredDefinition(compileCmdVar); + std::vector<std::string> compileCmds; + cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + + for (std::vector<std::string>::iterator i = compileCmds.begin(); + i != compileCmds.end(); ++i) + this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars); + + std::string cmdLine = + this->GetLocalGenerator()->BuildCommandLine(compileCmds); + + this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, + sourceFileName); } void @@ -799,7 +751,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( cmSourceFile const& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(!this->Generator->GetTarget()->IsBundleOnApple()) + if(!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { return; } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4e7d8b3..a10ceba 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -13,6 +13,8 @@ #ifndef cmNinjaTargetGenerator_h #define cmNinjaTargetGenerator_h +#include "cmCommonTargetGenerator.h" + #include "cmStandardIncludes.h" #include "cmNinjaTypes.h" #include "cmLocalNinjaGenerator.h" @@ -26,14 +28,14 @@ class cmMakefile; class cmSourceFile; class cmCustomCommand; -class cmNinjaTargetGenerator +class cmNinjaTargetGenerator: public cmCommonTargetGenerator { public: /// Create a cmNinjaTargetGenerator according to the @a target's type. static cmNinjaTargetGenerator* New(cmGeneratorTarget* target); /// Build a NinjaTargetGenerator. - cmNinjaTargetGenerator(cmTarget* target); + cmNinjaTargetGenerator(cmGeneratorTarget* target); /// Destructor. virtual ~cmNinjaTargetGenerator(); @@ -65,14 +67,8 @@ protected: cmMakefile* GetMakefile() const { return this->Makefile; } - std::string const& GetConfigName() const; - std::string LanguageCompilerRule(const std::string& lang) const; - const char* GetFeature(const std::string& feature); - bool GetFeatureAsBool(const std::string& feature); - void AddFeatureFlags(std::string& flags, const std::string& lang); - std::string OrderDependsTargetForTarget(); std::string ComputeOrderDependsForTarget(); @@ -85,6 +81,8 @@ protected: std::string ComputeFlagsForObject(cmSourceFile const* source, const std::string& language); + void AddIncludeFlags(std::string& flags, std::string const& lang); + std::string ComputeDefines(cmSourceFile const* source, const std::string& language); @@ -116,12 +114,20 @@ protected: void WriteObjectBuildStatement(cmSourceFile const* source, bool writeOrderDependsTargetForTarget); + void ExportObjectCompileCommand( + std::string const& language, + std::string const& sourceFileName, + std::string const& objectDir, + std::string const& objectFileName, + std::string const& objectFileDir, + std::string const& flags, + std::string const& defines, + std::string const& includes + ); + cmNinjaDeps GetObjects() const { return this->Objects; } - // Helper to add flag for windows .def file. - void AddModuleDefinitionFlag(std::string& flags); - void EnsureDirectoryExists(const std::string& dir) const; void EnsureParentDirectoryExists(const std::string& path) const; @@ -150,19 +156,10 @@ protected: cmNinjaVars& vars); private: - cmTarget* Target; - cmGeneratorTarget* GeneratorTarget; - cmMakefile* Makefile; cmLocalNinjaGenerator* LocalGenerator; /// List of object files for this target. cmNinjaDeps Objects; std::vector<cmCustomCommand const*> CustomCommands; - - typedef std::map<std::string, std::string> LanguageFlagMap; - LanguageFlagMap LanguageFlags; - - // The windows module definition source file (.def), if any. - std::string ModuleDefinitionFile; }; #endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 42d6b46..58b901a 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -21,7 +21,7 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmGeneratorTarget *target) - : cmNinjaTargetGenerator(target->Target) {} + : cmNinjaTargetGenerator(target) {} cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {} @@ -44,7 +44,7 @@ void cmNinjaUtilityTargetGenerator::Generate() for (std::vector<cmCustomCommand>::const_iterator ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) { cmCustomCommandGenerator ccg(*ci, this->GetConfigName(), - this->GetMakefile()); + this->GetLocalGenerator()); this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps); this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands); std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); @@ -65,7 +65,7 @@ void cmNinjaUtilityTargetGenerator::Generate() if(cmCustomCommand* cc = (*source)->GetCustomCommand()) { cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->GetMakefile()); + this->GetLocalGenerator()); this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget()); // Depend on all custom command outputs. diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index a8eef82..4fe99e3 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -22,7 +22,7 @@ cmOSXBundleGenerator(cmGeneratorTarget* target, const std::string& configName) : GT(target) , Makefile(target->Target->GetMakefile()) - , LocalGenerator(Makefile->GetLocalGenerator()) + , LocalGenerator(target->GetLocalGenerator()) , ConfigName(configName) , MacContentFolders(0) { @@ -47,7 +47,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // Compute bundle directory names. std::string out = outpath; out += "/"; - out += this->GT->Target->GetAppBundleDirectory(this->ConfigName, false); + out += this->GT->GetAppBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); @@ -57,7 +57,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // to be set. std::string plist = outpath; plist += "/"; - plist += this->GT->Target->GetAppBundleDirectory(this->ConfigName, true); + plist += this->GT->GetAppBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, targetName, @@ -77,11 +77,11 @@ void cmOSXBundleGenerator::CreateFramework( // Compute the location of the top-level foo.framework directory. std::string contentdir = outpath + "/" + - this->GT->Target->GetFrameworkDirectory(this->ConfigName, true); + this->GT->GetFrameworkDirectory(this->ConfigName, true); contentdir += "/"; std::string newoutpath = outpath + "/" + - this->GT->Target->GetFrameworkDirectory(this->ConfigName, false); + this->GT->GetFrameworkDirectory(this->ConfigName, false); std::string frameworkVersion = this->GT->Target->GetFrameworkVersion(); @@ -172,14 +172,14 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, // Compute bundle directory names. std::string out = root; out += "/"; - out += this->GT->Target->GetCFBundleDirectory(this->ConfigName, false); + out += this->GT->GetCFBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. std::string plist = root + "/" + - this->GT->Target->GetCFBundleDirectory(this->ConfigName, true); + this->GT->GetCFBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, @@ -217,7 +217,7 @@ cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc) // Construct the full path to the content subdirectory. std::string macdir = - this->GT->Target->GetMacContentDirectory(this->ConfigName, + this->GT->GetMacContentDirectory(this->ConfigName, /*implib*/ false); macdir += "/"; macdir += pkgloc; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index a612437..35ee127 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -280,7 +280,7 @@ bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir) //---------------------------------------------------------------------------- cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg, - cmTarget const* target, + const cmGeneratorTarget* target, const char* purpose) { this->GlobalGenerator = gg; @@ -554,7 +554,8 @@ void cmOrderDirectories::FindImplicitConflicts() << text << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance() - ->IssueMessage(cmake::WARNING, w.str(), this->Target->GetBacktrace()); + ->IssueMessage(cmake::WARNING, w.str(), + this->Target->Target->GetBacktrace()); } //---------------------------------------------------------------------------- @@ -635,5 +636,6 @@ void cmOrderDirectories::DiagnoseCycle() } e << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance() - ->IssueMessage(cmake::WARNING, e.str(), this->Target->GetBacktrace()); + ->IssueMessage(cmake::WARNING, e.str(), + this->Target->Target->GetBacktrace()); } diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h index 07c85dd..211c786 100644 --- a/Source/cmOrderDirectories.h +++ b/Source/cmOrderDirectories.h @@ -19,7 +19,7 @@ class cmGlobalGenerator; class cmOrderDirectoriesConstraint; class cmOrderDirectoriesConstraintLibrary; -class cmTarget; +class cmGeneratorTarget; /** \class cmOrderDirectories * \brief Compute a safe runtime path order for a set of shared libraries. @@ -27,7 +27,7 @@ class cmTarget; class cmOrderDirectories { public: - cmOrderDirectories(cmGlobalGenerator* gg, cmTarget const* target, + cmOrderDirectories(cmGlobalGenerator* gg, cmGeneratorTarget const* target, const char* purpose); ~cmOrderDirectories(); void AddRuntimeLibrary(std::string const& fullPath, const char* soname = 0); @@ -41,11 +41,9 @@ public: std::vector<std::string> const& GetOrderedDirectories(); private: cmGlobalGenerator* GlobalGenerator; - cmTarget const* Target; + cmGeneratorTarget const* Target; std::string Purpose; - bool Computed; - std::vector<std::string> OrderedDirectories; std::vector<cmOrderDirectoriesConstraint*> ConstraintEntries; @@ -68,8 +66,9 @@ private: void OrderDirectories(); void VisitDirectory(unsigned int i); void DiagnoseCycle(); - bool CycleDiagnosed; int WalkId; + bool CycleDiagnosed; + bool Computed; // Adjacency-list representation of runtime path ordering graph. // This maps from directory to those that must come *before* it. diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx new file mode 100644 index 0000000..7be5b3f --- /dev/null +++ b/Source/cmOutputConverter.cxx @@ -0,0 +1,1056 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmOutputConverter.h" + +#include "cmAlgorithms.h" +#include "cmake.h" + +#include <assert.h> + +#include <string.h> /* strlen */ +#include <ctype.h> /* isalpha */ + +cmOutputConverter::cmOutputConverter(cmState::Snapshot snapshot) + : StateSnapshot(snapshot), LinkScriptShell(false) +{ +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToOutputForExistingCommon(const std::string& remote, + std::string const& result, + OutputFormat format) const +{ + // If this is a windows shell, the result has a space, and the path + // already exists, we can use a short-path to reference it without a + // space. + if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos && + cmSystemTools::FileExists(remote.c_str())) + { + std::string tmp; + if(cmSystemTools::GetShortPath(remote, tmp)) + { + return this->ConvertToOutputFormat(tmp, format); + } + } + + // Otherwise, leave it unchanged. + return result; +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToOutputForExisting(const std::string& remote, + RelativeRoot local, + OutputFormat format) const +{ + static_cast<void>(local); + + // Perform standard conversion. + std::string result = this->ConvertToOutputFormat(remote, format); + + // Consider short-path. + return this->ConvertToOutputForExistingCommon(remote, result, format); +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToOutputForExisting(RelativeRoot remote, + const std::string& local, + OutputFormat format) const +{ + // Perform standard conversion. + std::string result = this->Convert(remote, local, format, true); + + // Consider short-path. + const char* remotePath = this->GetRelativeRootPath(remote); + return this->ConvertToOutputForExistingCommon(remotePath, result, format); +} + +//---------------------------------------------------------------------------- +const char* cmOutputConverter::GetRelativeRootPath(RelativeRoot relroot) const +{ + switch (relroot) + { + case HOME: + return this->GetState()->GetSourceDirectory(); + case START: + return this->StateSnapshot.GetDirectory().GetCurrentSource(); + case HOME_OUTPUT: + return this->GetState()->GetBinaryDirectory(); + case START_OUTPUT: + return this->StateSnapshot.GetDirectory().GetCurrentBinary(); + default: break; + } + return 0; +} + +std::string cmOutputConverter::Convert(const std::string& source, + RelativeRoot relative, + OutputFormat output) const +{ + // Convert the path to a relative path. + std::string result = source; + + switch (relative) + { + case HOME: + result = this->ConvertToRelativePath( + this->GetState()->GetSourceDirectoryComponents(), result); + break; + case START: + result = this->ConvertToRelativePath( + this->StateSnapshot.GetDirectory().GetCurrentSourceComponents(), + result); + break; + case HOME_OUTPUT: + result = this->ConvertToRelativePath( + this->GetState()->GetBinaryDirectoryComponents(), result); + break; + case START_OUTPUT: + result = this->ConvertToRelativePath( + this->StateSnapshot.GetDirectory().GetCurrentBinaryComponents(), + result); + break; + case FULL: + result = cmSystemTools::CollapseFullPath(result); + break; + case NONE: + break; + } + return this->ConvertToOutputFormat(result, output); +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source, + OutputFormat output) const +{ + std::string result = source; + // Convert it to an output path. + if (output == MAKERULE) + { + result = cmSystemTools::ConvertToOutputPath(result.c_str()); + } + else if(output == SHELL || output == WATCOMQUOTE) + { + // For the MSYS shell convert drive letters to posix paths, so + // that c:/some/path becomes /c/some/path. This is needed to + // avoid problems with the shell path translation. + if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) + { + if(result.size() > 2 && result[1] == ':') + { + result[1] = result[0]; + result[0] = '/'; + } + } + if(this->GetState()->UseWindowsShell()) + { + std::replace(result.begin(), result.end(), '/', '\\'); + } + result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); + } + else if(output == RESPONSE) + { + result = this->EscapeForShell(result, false, false, false); + } + return result; +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::Convert(RelativeRoot remote, + const std::string& local, + OutputFormat output, + bool optional) const +{ + const char* remotePath = this->GetRelativeRootPath(remote); + + // The relative root must have a path (i.e. not FULL or NONE) + assert(remotePath != 0); + + if(!local.empty() && !optional) + { + std::vector<std::string> components; + cmSystemTools::SplitPath(local, components); + std::string result = this->ConvertToRelativePath(components, remotePath); + return this->ConvertToOutputFormat(result, output); + } + + return this->ConvertToOutputFormat(remotePath, output); +} + +//---------------------------------------------------------------------------- +static bool cmOutputConverterNotAbove(const char* a, const char* b) +{ + return (cmSystemTools::ComparePath(a, b) || + cmSystemTools::IsSubDirectory(a, b)); +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::ConvertToRelativePath(const std::vector<std::string>& local, + const std::string& in_remote, + bool force) const +{ + // The path should never be quoted. + assert(in_remote[0] != '\"'); + + // The local path should never have a trailing slash. + assert(!local.empty() && !(local[local.size()-1] == "")); + + // If the path is already relative then just return the path. + if(!cmSystemTools::FileIsFullPath(in_remote.c_str())) + { + return in_remote; + } + + if(!force) + { + // Skip conversion if the path and local are not both in the source + // or both in the binary tree. + std::string local_path = cmSystemTools::JoinPath(local); + if(!((cmOutputConverterNotAbove(local_path.c_str(), + this->StateSnapshot.GetDirectory().GetRelativePathTopBinary()) + && cmOutputConverterNotAbove(in_remote.c_str(), + this->StateSnapshot.GetDirectory().GetRelativePathTopBinary())) + || (cmOutputConverterNotAbove(local_path.c_str(), + this->StateSnapshot.GetDirectory().GetRelativePathTopSource()) + && cmOutputConverterNotAbove(in_remote.c_str(), + this->StateSnapshot.GetDirectory().GetRelativePathTopSource())))) + { + return in_remote; + } + } + + // Identify the longest shared path component between the remote + // path and the local path. + std::vector<std::string> remote; + cmSystemTools::SplitPath(in_remote, remote); + unsigned int common=0; + while(common < remote.size() && + common < local.size() && + cmSystemTools::ComparePath(remote[common], + local[common])) + { + ++common; + } + + // If no part of the path is in common then return the full path. + if(common == 0) + { + return in_remote; + } + + // If the entire path is in common then just return a ".". + if(common == remote.size() && + common == local.size()) + { + return "."; + } + + // If the entire path is in common except for a trailing slash then + // just return a "./". + if(common+1 == remote.size() && + remote[common].empty() && + common == local.size()) + { + return "./"; + } + + // Construct the relative path. + std::string relative; + + // First add enough ../ to get up to the level of the shared portion + // of the path. Leave off the trailing slash. Note that the last + // component of local will never be empty because local should never + // have a trailing slash. + for(unsigned int i=common; i < local.size(); ++i) + { + relative += ".."; + if(i < local.size()-1) + { + relative += "/"; + } + } + + // Now add the portion of the destination path that is not included + // in the shared portion of the path. Add a slash the first time + // only if there was already something in the path. If there was a + // trailing slash in the input then the last iteration of the loop + // will add a slash followed by an empty string which will preserve + // the trailing slash in the output. + + if(!relative.empty() && !remote.empty()) + { + relative += "/"; + } + relative += cmJoin(cmMakeRange(remote).advance(common), "/"); + + // Finally return the path. + return relative; +} + +//---------------------------------------------------------------------------- +static bool cmOutputConverterIsShellOperator(const std::string& str) +{ + static std::set<std::string> shellOperators; + if(shellOperators.empty()) + { + shellOperators.insert("<"); + shellOperators.insert(">"); + shellOperators.insert("<<"); + shellOperators.insert(">>"); + shellOperators.insert("|"); + shellOperators.insert("||"); + shellOperators.insert("&&"); + shellOperators.insert("&>"); + shellOperators.insert("1>"); + shellOperators.insert("2>"); + shellOperators.insert("2>&1"); + shellOperators.insert("1>&2"); + } + return shellOperators.count(str) > 0; +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::EscapeForShell(const std::string& str, + bool makeVars, + bool forEcho, + bool useWatcomQuote) const +{ + // Do not escape shell operators. + if(cmOutputConverterIsShellOperator(str)) + { + return str; + } + + // Compute the flags for the target shell environment. + int flags = 0; + if(this->GetState()->UseWindowsVSIDE()) + { + flags |= Shell_Flag_VSIDE; + } + else if(!this->LinkScriptShell) + { + flags |= Shell_Flag_Make; + } + if(makeVars) + { + flags |= Shell_Flag_AllowMakeVariables; + } + if(forEcho) + { + flags |= Shell_Flag_EchoWindows; + } + if(useWatcomQuote) + { + flags |= Shell_Flag_WatcomQuote; + } + if(this->GetState()->UseWatcomWMake()) + { + flags |= Shell_Flag_WatcomWMake; + } + if(this->GetState()->UseMinGWMake()) + { + flags |= Shell_Flag_MinGWMake; + } + if(this->GetState()->UseNMake()) + { + flags |= Shell_Flag_NMake; + } + + // Compute the buffer size needed. + int size = (this->GetState()->UseWindowsShell() ? + Shell_GetArgumentSizeForWindows(str.c_str(), flags) : + Shell_GetArgumentSizeForUnix(str.c_str(), flags)); + + // Compute the shell argument itself. + std::vector<char> arg(size); + if(this->GetState()->UseWindowsShell()) + { + Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags); + } + else + { + Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags); + } + return std::string(&arg[0]); +} + +//---------------------------------------------------------------------------- +std::string cmOutputConverter::EscapeForCMake(const std::string& str) +{ + // Always double-quote the argument to take care of most escapes. + std::string result = "\""; + for(const char* c = str.c_str(); *c; ++c) + { + if(*c == '"') + { + // Escape the double quote to avoid ending the argument. + result += "\\\""; + } + else if(*c == '$') + { + // Escape the dollar to avoid expanding variables. + result += "\\$"; + } + else if(*c == '\\') + { + // Escape the backslash to avoid other escapes. + result += "\\\\"; + } + else + { + // Other characters will be parsed correctly. + result += *c; + } + } + result += "\""; + return result; +} + +//---------------------------------------------------------------------------- +std::string +cmOutputConverter::EscapeWindowsShellArgument(const char* arg, int shell_flags) +{ + char local_buffer[1024]; + char* buffer = local_buffer; + int size = Shell_GetArgumentSizeForWindows(arg, shell_flags); + if(size > 1024) + { + buffer = new char[size]; + } + Shell_GetArgumentForWindows(arg, buffer, shell_flags); + std::string result(buffer); + if(buffer != local_buffer) + { + delete [] buffer; + } + return result; +} + +//---------------------------------------------------------------------------- +cmOutputConverter::FortranFormat +cmOutputConverter::GetFortranFormat(const char* value) +{ + FortranFormat format = FortranFormatNone; + if(value && *value) + { + std::vector<std::string> fmt; + cmSystemTools::ExpandListArgument(value, fmt); + for(std::vector<std::string>::iterator fi = fmt.begin(); + fi != fmt.end(); ++fi) + { + if(*fi == "FIXED") + { + format = FortranFormatFixed; + } + if(*fi == "FREE") + { + format = FortranFormatFree; + } + } + } + return format; +} + +void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell) +{ + this->LinkScriptShell = linkScriptShell; +} + +cmState* cmOutputConverter::GetState() const +{ + return this->StateSnapshot.GetState(); +} + +//---------------------------------------------------------------------------- +/* + +Notes: + +Make variable replacements open a can of worms. Sometimes they should +be quoted and sometimes not. Sometimes their replacement values are +already quoted. + +VS variables cause problems. In order to pass the referenced value +with spaces the reference must be quoted. If the variable value ends +in a backslash then it will escape the ending quote! In order to make +the ending backslash appear we need this: + + "$(InputDir)\" + +However if there is not a trailing backslash then this will put a +quote in the value so we need: + + "$(InputDir)" + +Make variable references are platform specific so we should probably +just NOT quote them and let the listfile author deal with it. + +*/ + +/* +TODO: For windows echo: + +To display a pipe (|) or redirection character (< or >) when using the +echo command, use a caret character immediately before the pipe or +redirection character (for example, ^>, ^<, or ^| ). If you need to +use the caret character itself (^), use two in a row (^^). +*/ + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__CharIsWhitespace(char c) +{ + return ((c == ' ') || (c == '\t')); +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c) +{ + return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') || + (c == '&') || (c == '$') || (c == '(') || (c == ')') || + (c == '~') || (c == '<') || (c == '>') || (c == '|') || + (c == '*') || (c == '^') || (c == '\\')); +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c) +{ + return ((c == '\'') || (c == '#') || (c == '&') || + (c == '<') || (c == '>') || (c == '|') || (c == '^')); +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__CharNeedsQuotes(char c, int isUnix, int flags) +{ + /* On Windows the built-in command shell echo never needs quotes. */ + if(!isUnix && (flags & Shell_Flag_EchoWindows)) + { + return 0; + } + + /* On all platforms quotes are needed to preserve whitespace. */ + if(Shell__CharIsWhitespace(c)) + { + return 1; + } + + if(isUnix) + { + /* On UNIX several special characters need quotes to preserve them. */ + if(Shell__CharNeedsQuotesOnUnix(c)) + { + return 1; + } + } + else + { + /* On Windows several special characters need quotes to preserve them. */ + if(Shell__CharNeedsQuotesOnWindows(c)) + { + return 1; + } + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__CharIsMakeVariableName(char c) +{ + return c && (c == '_' || isalpha(((int)c))); +} + +/*--------------------------------------------------------------------------*/ +const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c) +{ + while(*c == '$' && *(c+1) == '(') + { + const char* skip = c+2; + while(Shell__CharIsMakeVariableName(*skip)) + { + ++skip; + } + if(*skip == ')') + { + c = skip+1; + } + else + { + break; + } + } + return c; +} + +/* +Allowing make variable replacements opens a can of worms. Sometimes +they should be quoted and sometimes not. Sometimes their replacement +values are already quoted or contain escapes. + +Some Visual Studio variables cause problems. In order to pass the +referenced value with spaces the reference must be quoted. If the +variable value ends in a backslash then it will escape the ending +quote! In order to make the ending backslash appear we need this: + + "$(InputDir)\" + +However if there is not a trailing backslash then this will put a +quote in the value so we need: + + "$(InputDir)" + +This macro decides whether we quote an argument just because it +contains a make variable reference. This should be replaced with a +flag later when we understand applications of this better. +*/ +#define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0 + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, + int isUnix, int flags) +{ + /* The empty string needs quotes. */ + if(!*in) + { + return 1; + } + + /* Scan the string for characters that require quoting. */ + { + const char* c; + for(c=in; *c; ++c) + { + /* Look for $(MAKEVAR) syntax if requested. */ + if(flags & Shell_Flag_AllowMakeVariables) + { +#if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES + const char* skip = Shell__SkipMakeVariables(c); + if(skip != c) + { + /* We need to quote make variable references to preserve the + string with contents substituted in its place. */ + return 1; + } +#else + /* Skip over the make variable references if any are present. */ + c = Shell__SkipMakeVariables(c); + + /* Stop if we have reached the end of the string. */ + if(!*c) + { + break; + } +#endif + } + + /* Check whether this character needs quotes. */ + if(Shell__CharNeedsQuotes(*c, isUnix, flags)) + { + return 1; + } + } + } + + /* On Windows some single character arguments need quotes. */ + if(!isUnix && *in && !*(in+1)) + { + char c = *in; + if((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) + { + return 1; + } + } + + return 0; +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell__GetArgumentSize(const char* in, + int isUnix, int flags) +{ + /* Start with the length of the original argument, plus one for + either a terminating null or a separating space. */ + int size = (int)strlen(in) + 1; + + /* String iterator. */ + const char* c; + + /* Keep track of how many backslashes have been encountered in a row. */ + int windows_backslashes = 0; + + /* Scan the string for characters that require escaping or quoting. */ + for(c=in; *c; ++c) + { + /* Look for $(MAKEVAR) syntax if requested. */ + if(flags & Shell_Flag_AllowMakeVariables) + { + /* Skip over the make variable references if any are present. */ + c = Shell__SkipMakeVariables(c); + + /* Stop if we have reached the end of the string. */ + if(!*c) + { + break; + } + } + + /* Check whether this character needs escaping for the shell. */ + if(isUnix) + { + /* On Unix a few special characters need escaping even inside a + quoted argument. */ + if(*c == '\\' || *c == '"' || *c == '`' || *c == '$') + { + /* This character needs a backslash to escape it. */ + ++size; + } + } + else if(flags & Shell_Flag_EchoWindows) + { + /* On Windows the built-in command shell echo never needs escaping. */ + } + else + { + /* On Windows only backslashes and double-quotes need escaping. */ + if(*c == '\\') + { + /* Found a backslash. It may need to be escaped later. */ + ++windows_backslashes; + } + else if(*c == '"') + { + /* Found a double-quote. We need to escape it and all + immediately preceding backslashes. */ + size += windows_backslashes + 1; + windows_backslashes = 0; + } + else + { + /* Found another character. This eliminates the possibility + that any immediately preceding backslashes will be + escaped. */ + windows_backslashes = 0; + } + } + + /* Check whether this character needs escaping for a make tool. */ + if(*c == '$') + { + if(flags & Shell_Flag_Make) + { + /* In Makefiles a dollar is written $$ so we need one extra + character. */ + ++size; + } + else if(flags & Shell_Flag_VSIDE) + { + /* In a VS IDE a dollar is written "$" so we need two extra + characters. */ + size += 2; + } + } + else if(*c == '#') + { + if((flags & Shell_Flag_Make) && + (flags & Shell_Flag_WatcomWMake)) + { + /* In Watcom WMake makefiles a pound is written $# so we need + one extra character. */ + ++size; + } + } + else if(*c == '%') + { + if((flags & Shell_Flag_VSIDE) || + ((flags & Shell_Flag_Make) && + ((flags & Shell_Flag_MinGWMake) || + (flags & Shell_Flag_NMake)))) + { + /* In the VS IDE, NMake, or MinGW make a percent is written %% + so we need one extra characters. */ + size += 1; + } + } + else if(*c == ';') + { + if(flags & Shell_Flag_VSIDE) + { + /* In a VS IDE a semicolon is written ";" so we need two extra + characters. */ + size += 2; + } + } + } + + /* Check whether the argument needs surrounding quotes. */ + if(Shell__ArgumentNeedsQuotes(in, isUnix, flags)) + { + /* Surrounding quotes are needed. Allocate space for them. */ + if((flags & Shell_Flag_WatcomQuote) && (isUnix)) + { + size += 2; + } + size += 2; + + /* We must escape all ending backslashes when quoting on windows. */ + size += windows_backslashes; + } + + return size; +} + +/*--------------------------------------------------------------------------*/ +char* cmOutputConverter::Shell__GetArgument(const char* in, char* out, + int isUnix, int flags) +{ + /* String iterator. */ + const char* c; + + /* Keep track of how many backslashes have been encountered in a row. */ + int windows_backslashes = 0; + + /* Whether the argument must be quoted. */ + int needQuotes = Shell__ArgumentNeedsQuotes(in, isUnix, flags); + if(needQuotes) + { + /* Add the opening quote for this argument. */ + if(flags & Shell_Flag_WatcomQuote) + { + if(isUnix) + { + *out++ = '"'; + } + *out++ = '\''; + } + else + { + *out++ = '"'; + } + } + + /* Scan the string for characters that require escaping or quoting. */ + for(c=in; *c; ++c) + { + /* Look for $(MAKEVAR) syntax if requested. */ + if(flags & Shell_Flag_AllowMakeVariables) + { + const char* skip = Shell__SkipMakeVariables(c); + if(skip != c) + { + /* Copy to the end of the make variable references. */ + while(c != skip) + { + *out++ = *c++; + } + + /* The make variable reference eliminates any escaping needed + for preceding backslashes. */ + windows_backslashes = 0; + + /* Stop if we have reached the end of the string. */ + if(!*c) + { + break; + } + } + } + + /* Check whether this character needs escaping for the shell. */ + if(isUnix) + { + /* On Unix a few special characters need escaping even inside a + quoted argument. */ + if(*c == '\\' || *c == '"' || *c == '`' || *c == '$') + { + /* This character needs a backslash to escape it. */ + *out++ = '\\'; + } + } + else if(flags & Shell_Flag_EchoWindows) + { + /* On Windows the built-in command shell echo never needs escaping. */ + } + else + { + /* On Windows only backslashes and double-quotes need escaping. */ + if(*c == '\\') + { + /* Found a backslash. It may need to be escaped later. */ + ++windows_backslashes; + } + else if(*c == '"') + { + /* Found a double-quote. Escape all immediately preceding + backslashes. */ + while(windows_backslashes > 0) + { + --windows_backslashes; + *out++ = '\\'; + } + + /* Add the backslash to escape the double-quote. */ + *out++ = '\\'; + } + else + { + /* We encountered a normal character. This eliminates any + escaping needed for preceding backslashes. */ + windows_backslashes = 0; + } + } + + /* Check whether this character needs escaping for a make tool. */ + if(*c == '$') + { + if(flags & Shell_Flag_Make) + { + /* In Makefiles a dollar is written $$. The make tool will + replace it with just $ before passing it to the shell. */ + *out++ = '$'; + *out++ = '$'; + } + else if(flags & Shell_Flag_VSIDE) + { + /* In a VS IDE a dollar is written "$". If this is written in + an un-quoted argument it starts a quoted segment, inserts + the $ and ends the segment. If it is written in a quoted + argument it ends quoting, inserts the $ and restarts + quoting. Either way the $ is isolated from surrounding + text to avoid looking like a variable reference. */ + *out++ = '"'; + *out++ = '$'; + *out++ = '"'; + } + else + { + /* Otherwise a dollar is written just $. */ + *out++ = '$'; + } + } + else if(*c == '#') + { + if((flags & Shell_Flag_Make) && + (flags & Shell_Flag_WatcomWMake)) + { + /* In Watcom WMake makefiles a pound is written $#. The make + tool will replace it with just # before passing it to the + shell. */ + *out++ = '$'; + *out++ = '#'; + } + else + { + /* Otherwise a pound is written just #. */ + *out++ = '#'; + } + } + else if(*c == '%') + { + if((flags & Shell_Flag_VSIDE) || + ((flags & Shell_Flag_Make) && + ((flags & Shell_Flag_MinGWMake) || + (flags & Shell_Flag_NMake)))) + { + /* In the VS IDE, NMake, or MinGW make a percent is written %%. */ + *out++ = '%'; + *out++ = '%'; + } + else + { + /* Otherwise a percent is written just %. */ + *out++ = '%'; + } + } + else if(*c == ';') + { + if(flags & Shell_Flag_VSIDE) + { + /* In a VS IDE a semicolon is written ";". If this is written + in an un-quoted argument it starts a quoted segment, + inserts the ; and ends the segment. If it is written in a + quoted argument it ends quoting, inserts the ; and restarts + quoting. Either way the ; is isolated. */ + *out++ = '"'; + *out++ = ';'; + *out++ = '"'; + } + else + { + /* Otherwise a semicolon is written just ;. */ + *out++ = ';'; + } + } + else + { + /* Store this character. */ + *out++ = *c; + } + } + + if(needQuotes) + { + /* Add enough backslashes to escape any trailing ones. */ + while(windows_backslashes > 0) + { + --windows_backslashes; + *out++ = '\\'; + } + + /* Add the closing quote for this argument. */ + if(flags & Shell_Flag_WatcomQuote) + { + *out++ = '\''; + if(isUnix) + { + *out++ = '"'; + } + } + else + { + *out++ = '"'; + } + } + + /* Store a terminating null without incrementing. */ + *out = 0; + + return out; +} + +/*--------------------------------------------------------------------------*/ +char* cmOutputConverter::Shell_GetArgumentForWindows(const char* in, + char* out, int flags) +{ + return Shell__GetArgument(in, out, 0, flags); +} + +/*--------------------------------------------------------------------------*/ +char* cmOutputConverter::Shell_GetArgumentForUnix(const char* in, + char* out, int flags) +{ + return Shell__GetArgument(in, out, 1, flags); +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell_GetArgumentSizeForWindows(const char* in, + int flags) +{ + return Shell__GetArgumentSize(in, 0, flags); +} + +/*--------------------------------------------------------------------------*/ +int cmOutputConverter::Shell_GetArgumentSizeForUnix(const char* in, + int flags) +{ + return Shell__GetArgumentSize(in, 1, flags); +} diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h new file mode 100644 index 0000000..ed7739e --- /dev/null +++ b/Source/cmOutputConverter.h @@ -0,0 +1,181 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmOutputConverter_h +#define cmOutputConverter_h + +#include "cmStandardIncludes.h" + +#include "cmGlobalGenerator.h" +#include "cmState.h" + +class cmOutputConverter +{ +public: + cmOutputConverter(cmState::Snapshot snapshot); + + /** + * Convert something to something else. This is a centralized conversion + * routine used by the generators to handle relative paths and the like. + * The flags determine what is actually done. + * + * relative: treat the argument as a directory and convert it to make it + * relative or full or unchanged. If relative (HOME, START etc) then that + * specifies what it should be relative to. + * + * output: make the result suitable for output to a... + * + * optional: should any relative path operation be controlled by the rel + * path setting + */ + enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; + enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE }; + std::string ConvertToOutputFormat(const std::string& source, + OutputFormat output) const; + std::string Convert(const std::string& remote, RelativeRoot local, + OutputFormat output = UNCHANGED) const; + std::string Convert(RelativeRoot remote, const std::string& local, + OutputFormat output = UNCHANGED, + bool optional = false) const; + + /** + * Get path for the specified relative root. + */ + const char* GetRelativeRootPath(RelativeRoot relroot) const; + + ///! for existing files convert to output path and short path if spaces + std::string ConvertToOutputForExisting(const std::string& remote, + RelativeRoot local = START_OUTPUT, + OutputFormat format = SHELL) const; + + /** For existing path identified by RelativeRoot convert to output + path and short path if spaces. */ + std::string ConvertToOutputForExisting(RelativeRoot remote, + const std::string& local = "", + OutputFormat format = SHELL) const; + + void SetLinkScriptShell(bool linkScriptShell); + + /** + * Flags to pass to Shell_GetArgumentForWindows or + * Shell_GetArgumentForUnix. These modify the generated + * quoting and escape sequences to work under alternative + * environments. + */ + enum Shell_Flag_e + { + /** The target shell is in a makefile. */ + Shell_Flag_Make = (1<<0), + + /** The target shell is in a VS project file. Do not use with + Shell_Flag_Make. */ + Shell_Flag_VSIDE = (1<<1), + + /** In a windows shell the argument is being passed to "echo". */ + Shell_Flag_EchoWindows = (1<<2), + + /** The target shell is in a Watcom WMake makefile. */ + Shell_Flag_WatcomWMake = (1<<3), + + /** The target shell is in a MinGW Make makefile. */ + Shell_Flag_MinGWMake = (1<<4), + + /** The target shell is in a NMake makefile. */ + Shell_Flag_NMake = (1<<5), + + /** Make variable reference syntax $(MAKEVAR) should not be escaped + to allow a build tool to replace it. Replacement values + containing spaces, quotes, backslashes, or other + non-alphanumeric characters that have significance to some makes + or shells produce undefined behavior. */ + Shell_Flag_AllowMakeVariables = (1<<6), + + /** The target shell quoting uses extra single Quotes for Watcom tools. */ + Shell_Flag_WatcomQuote = (1<<7) + }; + + /** + * Transform the given command line argument for use in a Windows or + * Unix shell. Returns a pointer to the end of the command line + * argument in the provided output buffer. Flags may be passed to + * modify the generated quoting and escape sequences to work under + * alternative environments. + */ + static char* Shell_GetArgumentForWindows(const char* in, char* out, + int flags); + static char* Shell_GetArgumentForUnix(const char* in, char* out, int flags); + + /** + * Compute the size of the buffer required to store the output from + * Shell_GetArgumentForWindows or Shell_GetArgumentForUnix. The flags + * passed must be identical between the two calls. + */ + static int Shell_GetArgumentSizeForWindows(const char* in, int flags); + static int Shell_GetArgumentSizeForUnix(const char* in, int flags); + + std::string EscapeForShell(const std::string& str, + bool makeVars = false, + bool forEcho = false, + bool useWatcomQuote = false) const; + + static std::string EscapeForCMake(const std::string& str); + + /** Compute an escaped version of the given argument for use in a + windows shell. */ + static std::string EscapeWindowsShellArgument(const char* arg, + int shell_flags); + + enum FortranFormat + { + FortranFormatNone, + FortranFormatFixed, + FortranFormatFree + }; + static FortranFormat GetFortranFormat(const char* value); + + /** + * Convert the given remote path to a relative path with respect to + * the given local path. The local path must be given in component + * form (see SystemTools::SplitPath) without a trailing slash. The + * remote path must use forward slashes and not already be escaped + * or quoted. + */ + std::string ConvertToRelativePath(const std::vector<std::string>& local, + const std::string& in_remote, + bool force = false) const; + +private: + cmState* GetState() const; + + std::string ConvertToOutputForExistingCommon(const std::string& remote, + std::string const& result, + OutputFormat format) const; + + static int Shell__CharIsWhitespace(char c); + static int Shell__CharNeedsQuotesOnUnix(char c); + static int Shell__CharNeedsQuotesOnWindows(char c); + static int Shell__CharNeedsQuotes(char c, int isUnix, int flags); + static int Shell__CharIsMakeVariableName(char c); + static const char* Shell__SkipMakeVariables(const char* c); + static int Shell__ArgumentNeedsQuotes(const char* in, + int isUnix, int flags); + static int Shell__GetArgumentSize(const char* in, + int isUnix, int flags); + static char* Shell__GetArgument(const char* in, char* out, + int isUnix, int flags); + +private: + cmState::Snapshot StateSnapshot; + + bool LinkScriptShell; +}; + +#endif diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index f8d61db..3eb19bb 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -255,6 +255,22 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf, { return false; } + if(pid == cmPolicies::CMP0001 && + (status == cmPolicies::WARN || status == cmPolicies::OLD)) + { + if(!(mf->GetState() + ->GetInitializedCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))) + { + // Set it to 2.4 because that is the last version where the + // variable had meaning. + mf->AddCacheDefinition + ("CMAKE_BACKWARDS_COMPATIBILITY", "2.4", + "For backwards compatibility, what version of CMake " + "commands and " + "syntax should this version of CMake try to support.", + cmState::STRING); + } + } } } else @@ -343,51 +359,38 @@ cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id) return e.str(); } -cmPolicies::PolicyMap::PolicyMap() -{ - this->UNDEFINED.set(); -} - cmPolicies::PolicyStatus cmPolicies::PolicyMap::Get(cmPolicies::PolicyID id) const { PolicyStatus status = cmPolicies::WARN; - if (this->OLD[id]) + if (this->Status[(POLICY_STATUS_COUNT * id) + OLD]) { status = cmPolicies::OLD; } - else if (this->NEW[id]) + else if (this->Status[(POLICY_STATUS_COUNT * id) + NEW]) { status = cmPolicies::NEW; } - else if (this->REQUIRED_ALWAYS[id]) - { - status = cmPolicies::REQUIRED_ALWAYS; - } - else if (this->REQUIRED_IF_USED[id]) - { - status = cmPolicies::REQUIRED_IF_USED; - } return status; } void cmPolicies::PolicyMap::Set(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status) { - this->UNDEFINED.reset(id); - this->OLD[id] = (status == cmPolicies::OLD); - this->NEW[id] = (status == cmPolicies::NEW); - this->REQUIRED_ALWAYS[id] = (status == cmPolicies::REQUIRED_ALWAYS); - this->REQUIRED_IF_USED[id] = (status == cmPolicies::REQUIRED_IF_USED); + this->Status[(POLICY_STATUS_COUNT * id) + OLD] = (status == OLD); + this->Status[(POLICY_STATUS_COUNT * id) + WARN] = (status == WARN); + this->Status[(POLICY_STATUS_COUNT * id) + NEW] = (status == NEW); } bool cmPolicies::PolicyMap::IsDefined(cmPolicies::PolicyID id) const { - return !this->UNDEFINED[id]; + return this->Status[(POLICY_STATUS_COUNT * id) + OLD] + || this->Status[(POLICY_STATUS_COUNT * id) + WARN] + || this->Status[(POLICY_STATUS_COUNT * id) + NEW]; } bool cmPolicies::PolicyMap::IsEmpty() const { - return !this->UNDEFINED.none(); + return this->Status.none(); } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 00d857a..a791b89 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -12,7 +12,7 @@ #ifndef cmPolicies_h #define cmPolicies_h -#include "cmCustomCommand.h" +#include "cmStandardIncludes.h" #include <bitset> @@ -217,6 +217,9 @@ class cmPolicy; 3, 3, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0063, \ "Honor visibility properties for all target types.", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0064, \ + "Support new TEST if() operator.", \ 3, 3, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) @@ -281,18 +284,14 @@ public: /** Represent a set of policy values. */ struct PolicyMap { - PolicyMap(); PolicyStatus Get(PolicyID id) const; void Set(PolicyID id, PolicyStatus status); bool IsDefined(PolicyID id) const; bool IsEmpty() const; private: - std::bitset<cmPolicies::CMPCOUNT> UNDEFINED; - std::bitset<cmPolicies::CMPCOUNT> OLD; - std::bitset<cmPolicies::CMPCOUNT> NEW; - std::bitset<cmPolicies::CMPCOUNT> REQUIRED_IF_USED; - std::bitset<cmPolicies::CMPCOUNT> REQUIRED_ALWAYS; +#define POLICY_STATUS_COUNT 3 + std::bitset<cmPolicies::CMPCOUNT * POLICY_STATUS_COUNT> Status; }; }; diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index d2f7bf3..15d9ed0 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -44,7 +44,7 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, //---------------------------------------------------------------------------- cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR): - Separator(sep), IgnoreCR(ignoreCR), Log(0), Prefix(0), LineEnd('\0') + Log(0), Prefix(0), Separator(sep), LineEnd('\0'), IgnoreCR(ignoreCR) { } diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h index 439726d..23833ca 100644 --- a/Source/cmProcessTools.h +++ b/Source/cmProcessTools.h @@ -51,12 +51,12 @@ public: /** Configure logging of lines as they are extracted. */ void SetLog(std::ostream* log, const char* prefix); protected: - char Separator; - bool IgnoreCR; std::ostream* Log; const char* Prefix; - char LineEnd; std::string Line; + char Separator; + char LineEnd; + bool IgnoreCR; virtual bool ProcessChunk(const char* data, int length); /** Implement in a subclass to process one line of input. It diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 176cb0d..7123125 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -20,7 +20,7 @@ bool cmProjectCommand this->SetError("PROJECT called with incorrect number of arguments"); return false; } - this->Makefile->SetProjectName(args[0].c_str()); + this->Makefile->SetProjectName(args[0]); std::string bindir = args[0]; bindir += "_BINARY_DIR"; @@ -53,7 +53,7 @@ bool cmProjectCommand // CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build // will work. if(!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") - || (this->Makefile->GetLocalGenerator()->IsRootMakefile())) + || (this->Makefile->IsRootMakefile())) { this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str()); this->Makefile->AddCacheDefinition @@ -233,7 +233,6 @@ bool cmProjectCommand const char* include = this->Makefile->GetDefinition(extraInclude); if(include) { - std::string fullFilePath; bool readit = this->Makefile->ReadDependentFile(include); if(!readit && !cmSystemTools::GetFatalErrorOccured()) diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx index 40976db..ef57068 100644 --- a/Source/cmProperty.cxx +++ b/Source/cmProperty.cxx @@ -12,17 +12,14 @@ #include "cmProperty.h" #include "cmSystemTools.h" -void cmProperty::Set(const std::string& name, const char *value) +void cmProperty::Set(const char *value) { - this->Name = name; this->Value = value; this->ValueHasBeenSet = true; } -void cmProperty::Append(const std::string& name, const char *value, - bool asString) +void cmProperty::Append(const char *value, bool asString) { - this->Name = name; if(!this->Value.empty() && *value && !asString) { this->Value += ";"; diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 659c4c3..e026372 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -21,11 +21,10 @@ public: TEST, VARIABLE, CACHED_VARIABLE, INSTALL }; // set this property - void Set(const std::string& name, const char *value); + void Set(const char *value); // append to this property - void Append(const std::string& name, const char *value, - bool asString = false); + void Append(const char *value, bool asString = false); // get the value const char *GetValue() const; @@ -34,7 +33,6 @@ public: cmProperty() { this->ValueHasBeenSet = false; } protected: - std::string Name; std::string Value; bool ValueHasBeenSet; }; diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx index 3875318..776fad1 100644 --- a/Source/cmPropertyDefinitionMap.cxx +++ b/Source/cmPropertyDefinitionMap.cxx @@ -29,9 +29,9 @@ void cmPropertyDefinitionMap } } -bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) +bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) const { - cmPropertyDefinitionMap::iterator it = this->find(name); + cmPropertyDefinitionMap::const_iterator it = this->find(name); if (it == this->end()) { return false; @@ -40,9 +40,9 @@ bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) return true; } -bool cmPropertyDefinitionMap::IsPropertyChained(const std::string& name) +bool cmPropertyDefinitionMap::IsPropertyChained(const std::string& name) const { - cmPropertyDefinitionMap::iterator it = this->find(name); + cmPropertyDefinitionMap::const_iterator it = this->find(name); if (it == this->end()) { return false; diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h index 00c7328..f95c721 100644 --- a/Source/cmPropertyDefinitionMap.h +++ b/Source/cmPropertyDefinitionMap.h @@ -27,10 +27,10 @@ public: bool chain); // has a named property been defined - bool IsPropertyDefined(const std::string& name); + bool IsPropertyDefined(const std::string& name) const; // is a named property set to chain - bool IsPropertyChained(const std::string& name); + bool IsPropertyChained(const std::string& name) const; }; #endif diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index 070f6f1..ef09dbc 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -14,6 +14,8 @@ #include "cmake.h" #include "cmState.h" +#include <assert.h> + cmProperty *cmPropertyMap::GetOrCreateProperty(const std::string& name) { cmPropertyMap::iterator it = this->find(name); @@ -29,54 +31,39 @@ cmProperty *cmPropertyMap::GetOrCreateProperty(const std::string& name) return prop; } -void cmPropertyMap::SetProperty(const std::string& name, const char *value, - cmProperty::ScopeType scope) +void cmPropertyMap::SetProperty(const std::string& name, const char *value) { if(!value) { this->erase(name); return; } - (void)scope; cmProperty *prop = this->GetOrCreateProperty(name); - prop->Set(name,value); + prop->Set(value); } void cmPropertyMap::AppendProperty(const std::string& name, const char* value, - cmProperty::ScopeType scope, bool asString) + bool asString) { // Skip if nothing to append. if(!value || !*value) { return; } - (void)scope; cmProperty *prop = this->GetOrCreateProperty(name); - prop->Append(name,value,asString); + prop->Append(value,asString); } const char *cmPropertyMap -::GetPropertyValue(const std::string& name, - cmProperty::ScopeType scope, - bool &chain) const +::GetPropertyValue(const std::string& name) const { - chain = false; - if (name.empty()) - { - return 0; - } + assert(!name.empty()); cmPropertyMap::const_iterator it = this->find(name); if (it == this->end()) { - // should we chain up? - if (this->CMakeInstance) - { - chain = this->CMakeInstance->GetState()-> - IsPropertyChained(name,scope); - } return 0; } return it->second.GetValue(); diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index 02d4235..a9062db 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -14,29 +14,17 @@ #include "cmProperty.h" -class cmake; - class cmPropertyMap : public std::map<std::string,cmProperty> { public: cmProperty *GetOrCreateProperty(const std::string& name); - void SetProperty(const std::string& name, const char *value, - cmProperty::ScopeType scope); + void SetProperty(const std::string& name, const char *value); void AppendProperty(const std::string& name, const char* value, - cmProperty::ScopeType scope, bool asString=false); - - const char *GetPropertyValue(const std::string& name, - cmProperty::ScopeType scope, - bool &chain) const; - - void SetCMakeInstance(cmake *cm) { this->CMakeInstance = cm; } - - cmPropertyMap() { this->CMakeInstance = 0;} + bool asString=false); -private: - cmake *CMakeInstance; + const char *GetPropertyValue(const std::string& name) const; }; #endif diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index cbb06cd..becfeba 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -26,7 +26,6 @@ #include <sys/stat.h> #include <cmsys/Terminal.h> -#include <cmsys/ios/sstream> #include <cmsys/FStream.hxx> #include <assert.h> @@ -122,7 +121,7 @@ static void copyTargetProperty(cmTarget* destinationTarget, static std::string ReadAll(const std::string& filename) { cmsys::ifstream file(filename.c_str()); - cmsys_ios::stringstream stream; + std::stringstream stream; stream << file.rdbuf(); file.close(); return stream.str(); @@ -190,7 +189,7 @@ std::string cmQtAutoGenerators::ListQt5RccInputs(cmSourceFile* sf, std::vector<std::string> command; command.push_back(rccCommand); - command.push_back("--list"); + command.push_back("-list"); std::string absFile = cmsys::SystemTools::GetRealPath( sf->GetFullPath()); @@ -287,7 +286,8 @@ std::string cmQtAutoGenerators::ListQt4RccInputs(cmSourceFile* sf, return entriesList; } -bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) +bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg, + cmTarget* target) { cmMakefile* makefile = target->GetMakefile(); // don't do anything if there is no Qt4 or Qt5Core (which contains moc): @@ -368,8 +368,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) #if defined(_WIN32) && !defined(__CYGWIN__) bool usePRE_BUILD = false; - cmLocalGenerator* localGen = makefile->GetLocalGenerator(); - cmGlobalGenerator* gg = localGen->GetGlobalGenerator(); + cmGlobalGenerator* gg = lg->GetGlobalGenerator(); if(gg->GetName().find("Visual Studio") != std::string::npos) { cmGlobalVisualStudioGenerator* vsgg = @@ -396,7 +395,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) std::vector<std::string> rcc_output; bool const isNinja = - makefile->GetGlobalGenerator()->GetName() == "Ninja"; + lg->GetGlobalGenerator()->GetName() == "Ninja"; if(isNinja #if defined(_WIN32) && !defined(__CYGWIN__) || usePRE_BUILD @@ -404,7 +403,9 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) ) { std::vector<cmSourceFile*> srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); + cmGeneratorTarget* gtgt = + lg->GetGlobalGenerator()->GetGeneratorTarget(target); + gtgt->GetConfigCommonSourceFiles(srcFiles); for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) @@ -440,6 +441,9 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) this->ListQt4RccInputs(sf, depends); } #if defined(_WIN32) && !defined(__CYGWIN__) + // Cannot use PRE_BUILD because the resource files themselves + // may not be sources within the target so VS may not know the + // target needs to re-build at all. usePRE_BUILD = false; #endif } @@ -466,31 +470,14 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) else #endif { - cmTarget* autogenTarget = 0; - if (!rcc_output.empty() && !isNinja) - { - std::vector<std::string> no_byproducts; - makefile->AddCustomCommandToOutput(rcc_output, no_byproducts, - depends, "", - commandLines, 0, - workingDirectory.c_str(), - false, false); - - cmCustomCommandLines no_commands; - autogenTarget = makefile->AddUtilityCommand( - autogenTargetName, true, - workingDirectory.c_str(), rcc_output, - no_commands, false, autogenComment.c_str()); - - } - else - { - autogenTarget = makefile->AddUtilityCommand( + cmTarget* autogenTarget = makefile->AddUtilityCommand( autogenTargetName, true, workingDirectory.c_str(), /*byproducts=*/rcc_output, depends, commandLines, false, autogenComment.c_str()); - } + + cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg); + makefile->AddGeneratorTarget(autogenTarget, gt); // Set target folder const char* autogenFolder = makefile->GetState() @@ -522,10 +509,10 @@ static void GetCompileDefinitionsAndDirectories(cmTarget const* target, std::string &defs) { cmMakefile* makefile = target->GetMakefile(); - cmLocalGenerator* localGen = makefile->GetLocalGenerator(); + cmGlobalGenerator* globalGen = makefile->GetGlobalGenerator(); std::vector<std::string> includeDirs; - cmGeneratorTarget *gtgt = localGen->GetGlobalGenerator() - ->GetGeneratorTarget(target); + cmGeneratorTarget *gtgt = globalGen->GetGeneratorTarget(target); + cmLocalGenerator *localGen = gtgt->GetLocalGenerator(); // Get the include dirs for this target, without stripping the implicit // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 localGen->GetIncludeDirectories(includeDirs, gtgt, "CXX", config, false); @@ -550,9 +537,9 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) std::string autogenTargetName = getAutogenTargetName(target); makefile->AddDefinition("_moc_target_name", - cmLocalGenerator::EscapeForCMake(autogenTargetName).c_str()); + cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); makefile->AddDefinition("_origin_target_name", - cmLocalGenerator::EscapeForCMake(target->GetName()).c_str()); + cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); std::string targetDir = getAutogenTargetDir(target); @@ -561,8 +548,11 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) { qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); } + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); if (const char *targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) + gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) { qtVersion = targetQtVersion; } @@ -582,7 +572,7 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) this->SetupSourceFiles(target); } makefile->AddDefinition("_cpp_files", - cmLocalGenerator::EscapeForCMake(this->Sources).c_str()); + cmOutputConverter::EscapeForCMake(this->Sources).c_str()); if (target->GetPropertyAsBool("AUTOMOC")) { this->SetupAutoMocTarget(target, autogenTargetName, @@ -609,7 +599,7 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) // Ensure we have write permission in case .in was read-only. mode_t perm = 0; -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) mode_t mode_write = S_IWRITE; #else mode_t mode_write = S_IWUSR; @@ -673,7 +663,10 @@ void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target) const char* sepHeaders = ""; std::vector<cmSourceFile*> srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + gtgt->GetConfigCommonSourceFiles(srcFiles); const char *skipMocSep = ""; const char *skipUicSep = ""; @@ -764,11 +757,11 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); std::string _moc_options = (tmp!=0 ? tmp : ""); makefile->AddDefinition("_moc_options", - cmLocalGenerator::EscapeForCMake(_moc_options).c_str()); + cmOutputConverter::EscapeForCMake(_moc_options).c_str()); makefile->AddDefinition("_skip_moc", - cmLocalGenerator::EscapeForCMake(this->SkipMoc).c_str()); + cmOutputConverter::EscapeForCMake(this->SkipMoc).c_str()); makefile->AddDefinition("_moc_headers", - cmLocalGenerator::EscapeForCMake(this->Headers).c_str()); + cmOutputConverter::EscapeForCMake(this->Headers).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -780,9 +773,9 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, _moc_incs, _moc_compile_defs); makefile->AddDefinition("_moc_incs", - cmLocalGenerator::EscapeForCMake(_moc_incs).c_str()); + cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); makefile->AddDefinition("_moc_compile_defs", - cmLocalGenerator::EscapeForCMake(_moc_compile_defs).c_str()); + cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); for (std::vector<std::string>::const_iterator li = configs.begin(); li != configs.end(); ++li) @@ -795,7 +788,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, if (config_moc_incs != _moc_incs) { configIncludes[*li] = - cmLocalGenerator::EscapeForCMake(config_moc_incs); + cmOutputConverter::EscapeForCMake(config_moc_incs); if(_moc_incs.empty()) { _moc_incs = config_moc_incs; @@ -804,7 +797,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, if (config_moc_compile_defs != _moc_compile_defs) { configDefines[*li] = - cmLocalGenerator::EscapeForCMake(config_moc_compile_defs); + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); if(_moc_compile_defs.empty()) { _moc_compile_defs = config_moc_compile_defs; @@ -822,7 +815,8 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, autogenTargetName.c_str()); return; } - makefile->AddDefinition("_qt_moc_executable", qt5Moc->GetLocation("")); + makefile->AddDefinition("_qt_moc_executable", + qt5Moc->ImportedGetLocation("")); } else if (strcmp(qtVersion, "4") == 0) { @@ -833,7 +827,8 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, autogenTargetName.c_str()); return; } - makefile->AddDefinition("_qt_moc_executable", qt4Moc->GetLocation("")); + makefile->AddDefinition("_qt_moc_executable", + qt4Moc->ImportedGetLocation("")); } else { @@ -890,8 +885,11 @@ void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts, static void GetUicOpts(cmTarget const* target, const std::string& config, std::string &optString) { + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); std::vector<std::string> opts; - target->GetAutoUicOptions(opts, config); + gtgt->GetAutoUicOptions(opts, config); optString = cmJoin(opts, ";"); } @@ -906,7 +904,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, skipped.insert(skipVec.begin(), skipVec.end()); makefile->AddDefinition("_skip_uic", - cmLocalGenerator::EscapeForCMake(this->SkipUic).c_str()); + cmOutputConverter::EscapeForCMake(this->SkipUic).c_str()); std::vector<cmSourceFile*> uiFilesWithOptions = makefile->GetQtUiFilesWithOptions(); @@ -920,7 +918,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, if (!_uic_opts.empty()) { - _uic_opts = cmLocalGenerator::EscapeForCMake(_uic_opts); + _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); } for (std::vector<std::string>::const_iterator li = configs.begin(); @@ -931,7 +929,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, if (config_uic_opts != _uic_opts) { configUicOptions[*li] = - cmLocalGenerator::EscapeForCMake(config_uic_opts); + cmOutputConverter::EscapeForCMake(config_uic_opts); if(_uic_opts.empty()) { _uic_opts = config_uic_opts; @@ -966,9 +964,9 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, } makefile->AddDefinition("_qt_uic_options_files", - cmLocalGenerator::EscapeForCMake(uiFileFiles).c_str()); + cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); makefile->AddDefinition("_qt_uic_options_options", - cmLocalGenerator::EscapeForCMake(uiFileOptions).c_str()); + cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); std::string targetName = target->GetName(); if (strcmp(qtVersion, "5") == 0) @@ -980,7 +978,8 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, } else { - makefile->AddDefinition("_qt_uic_executable", qt5Uic->GetLocation("")); + makefile->AddDefinition("_qt_uic_executable", + qt5Uic->ImportedGetLocation("")); } } else if (strcmp(qtVersion, "4") == 0) @@ -992,7 +991,8 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, targetName.c_str()); return; } - makefile->AddDefinition("_qt_uic_executable", qt4Uic->GetLocation("")); + makefile->AddDefinition("_qt_uic_executable", + qt4Uic->ImportedGetLocation("")); } else { @@ -1051,7 +1051,10 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) cmMakefile *makefile = target->GetMakefile(); std::vector<cmSourceFile*> srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + gtgt->GetConfigCommonSourceFiles(srcFiles); std::string qrcInputs; const char* qrcInputsSep = ""; @@ -1141,15 +1144,15 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) } } makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(), - cmLocalGenerator::EscapeForCMake(qrcInputs).c_str()); + cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); makefile->AddDefinition("_rcc_files", - cmLocalGenerator::EscapeForCMake(_rcc_files).c_str()); + cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); makefile->AddDefinition("_qt_rcc_options_files", - cmLocalGenerator::EscapeForCMake(rccFileFiles).c_str()); + cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); makefile->AddDefinition("_qt_rcc_options_options", - cmLocalGenerator::EscapeForCMake(rccFileOptions).c_str()); + cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); makefile->AddDefinition("_qt_rcc_executable", this->GetRccExecutable(target).c_str()); @@ -1157,6 +1160,9 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) { + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); cmMakefile *makefile = target->GetMakefile(); const char *qtVersion = makefile->GetDefinition("_target_qt_version"); if (!qtVersion) @@ -1167,8 +1173,7 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); } if (const char *targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", - "")) + gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) { qtVersion = targetQtVersion; } @@ -1184,7 +1189,7 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) targetName.c_str()); return std::string(); } - return qt5Rcc->GetLocation(""); + return qt5Rcc->ImportedGetLocation(""); } else if (strcmp(qtVersion, "4") == 0) { @@ -1195,7 +1200,7 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) targetName.c_str()); return std::string(); } - return qt4Rcc->GetLocation(""); + return qt4Rcc->ImportedGetLocation(""); } cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " @@ -1212,10 +1217,12 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, cm.SetHomeDirectory(targetDirectory); cmGlobalGenerator gg(&cm); - cmLocalGenerator* lg = gg.MakeLocalGenerator(); + cmState::Snapshot snapshot = cm.GetCurrentSnapshot(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, snapshot)); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator(mf.get())); lg->GetMakefile()->SetCurrentBinaryDirectory(targetDirectory); lg->GetMakefile()->SetCurrentSourceDirectory(targetDirectory); - gg.SetCurrentLocalGenerator(lg); + gg.SetCurrentMakefile(lg->GetMakefile()); this->ReadAutogenInfoFile(lg->GetMakefile(), targetDirectory, config); this->ReadOldMocDefinitionsFile(lg->GetMakefile(), targetDirectory); @@ -1229,7 +1236,6 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, this->WriteOldMocDefinitionsFile(targetDirectory); - delete lg; return success; } @@ -1434,7 +1440,7 @@ cmQtAutoGenerators::WriteOldMocDefinitionsFile( outfile.open(filename.c_str(), std::ios::trunc); outfile << "set(AM_OLD_COMPILE_SETTINGS " - << cmLocalGenerator::EscapeForCMake( + << cmOutputConverter::EscapeForCMake( this->CurrentCompileSettingsStr) << ")\n"; outfile.close(); @@ -1640,7 +1646,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) this->GenerateQrc(); } - cmsys_ios::stringstream outStream; + std::stringstream outStream; outStream << "/* This file is autogenerated, do not edit*/\n"; bool automocCppChanged = false; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index f74e3c5..4f03348 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -18,6 +18,7 @@ class cmGlobalGenerator; class cmMakefile; +class cmLocalGenerator; class cmQtAutoGenerators { @@ -25,7 +26,7 @@ public: cmQtAutoGenerators(); bool Run(const std::string& targetDirectory, const std::string& config); - bool InitializeAutogenTarget(cmTarget* target); + bool InitializeAutogenTarget(cmLocalGenerator* lg, cmTarget* target); void SetupAutoGenerateTarget(cmTarget const* target); void SetupSourceFiles(cmTarget const* target); @@ -105,7 +106,6 @@ private: std::string SkipMoc; std::string SkipUic; std::string Headers; - bool IncludeProjectDirsBefore; std::string Srcdir; std::string Builddir; std::string MocExecutable; @@ -131,6 +131,7 @@ private: std::map<std::string, std::string> RccOptions; std::map<std::string, std::vector<std::string> > RccInputs; + bool IncludeProjectDirsBefore; bool Verbose; bool ColorOutput; bool RunMocFailed; @@ -138,7 +139,6 @@ private: bool RunRccFailed; bool GenerateAll; bool RelaxedMode; - }; #endif diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index 9ab04f1..bc9372f 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -54,9 +54,6 @@ public: void Generate(std::ostream& os, const std::string& config, std::vector<std::string> const& configurationTypes); - const std::vector<std::string>& GetConfigurations() const - { return this->Configurations; } - protected: typedef cmScriptGeneratorIndent Indent; virtual void GenerateScript(std::ostream& os); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index bf9f42c..306276b 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -108,7 +108,7 @@ bool cmSetCommand } // collect any values into a single semi-colon separated value list - value = cmJoin(cmRange(args).advance(1).retreat(ignoreLastArgs), ";"); + value = cmJoin(cmMakeRange(args).advance(1).retreat(ignoreLastArgs), ";"); if (parentScope) { diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 31e460f..17ad475 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -205,14 +205,8 @@ bool cmSetPropertyCommand::HandleDirectoryMode() // The local generators are associated with collapsed paths. dir = cmSystemTools::CollapseFullPath(dir); - // Lookup the generator. - if(cmLocalGenerator* lg = - this->Makefile->GetGlobalGenerator()->FindLocalGenerator(dir)) - { - // Use the makefile for the directory found. - mf = lg->GetMakefile(); - } - else + mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir); + if (!mf) { // Could not find the directory. this->SetError diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index e9cfacc..53dc5a8 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -85,8 +85,10 @@ bool cmSetTestsPropertiesCommand unsigned int k; for (k = 0; k < propertyPairs.size(); k = k + 2) { - test->SetProperty(propertyPairs[k], - propertyPairs[k+1].c_str()); + if (!propertyPairs[k].empty()) + { + test->SetProperty(propertyPairs[k], propertyPairs[k+1].c_str()); + } } } else diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 724ab39..86f0a7a 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -22,7 +22,6 @@ cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name): Location(mf, name) { this->CustomCommand = 0; - this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); this->FindFullPathFailed = false; this->IsUiFile = (".ui" == cmSystemTools::GetFilenameLastExtension(this->Location.GetName())); @@ -299,7 +298,7 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc) //---------------------------------------------------------------------------- void cmSourceFile::SetProperty(const std::string& prop, const char* value) { - this->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE); + this->Properties.SetProperty(prop, value); if (this->IsUiFile) { @@ -315,8 +314,7 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value) void cmSourceFile::AppendProperty(const std::string& prop, const char* value, bool asString) { - this->Properties.AppendProperty(prop, value, cmProperty::SOURCE_FILE, - asString); + this->Properties.AppendProperty(prop, value, asString); } //---------------------------------------------------------------------------- @@ -362,13 +360,16 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const } } - bool chain = false; - const char *retVal = - this->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE, chain); - if (chain) + const char *retVal = this->Properties.GetPropertyValue(prop); + if (!retVal) { cmMakefile const* mf = this->Location.GetMakefile(); - return mf->GetProperty(prop,cmProperty::SOURCE_FILE); + const bool chain = mf->GetState()-> + IsPropertyChained(prop, cmProperty::SOURCE_FILE); + if (chain) + { + return mf->GetProperty(prop, chain); + } } return retVal; diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index f898260..1433b54 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -107,8 +107,9 @@ private: std::string Extension; std::string Language; std::string FullPath; - bool FindFullPathFailed; std::string ObjectLibrary; + std::vector<std::string> Depends; + bool FindFullPathFailed; bool IsUiFile; bool FindFullPath(std::string* error); @@ -116,7 +117,6 @@ private: void CheckExtension(); void CheckLanguage(std::string const& ext); - std::vector<std::string> Depends; static const std::string propLANGUAGE; }; diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h index a9796b9..468a589 100644 --- a/Source/cmStandardIncludes.h +++ b/Source/cmStandardIncludes.h @@ -33,14 +33,6 @@ // Provide fixed-size integer types. #include <cmIML/INT.h> -// Include stream compatibility layer from KWSys. -// This is needed to work with large file support -// on some platforms whose stream operators do not -// support the large integer types. -#if defined(CMAKE_BUILD_WITH_CMAKE) -# include <cmsys/IOStream.hxx> -#endif - #include <fstream> #include <iostream> #include <iomanip> diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 042fabe..b30c10b 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -15,9 +15,73 @@ #include "cmCacheManager.h" #include "cmCommand.h" #include "cmAlgorithms.h" +#include "cmDefinitions.h" #include <assert.h> +struct cmState::SnapshotDataType +{ + cmState::PositionType ScopeParent; + cmState::PositionType DirectoryParent; + cmLinkedTree<cmState::PolicyStackEntry>::iterator Policies; + cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyRoot; + cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyScope; + cmState::SnapshotType SnapshotType; + cmLinkedTree<std::string>::iterator ExecutionListFile; + cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator + BuildSystemDirectory; + cmLinkedTree<cmDefinitions>::iterator Vars; + cmLinkedTree<cmDefinitions>::iterator Root; + cmLinkedTree<cmDefinitions>::iterator Parent; + std::string EntryPointCommand; + long EntryPointLine; + std::vector<std::string>::size_type IncludeDirectoryPosition; + std::vector<std::string>::size_type CompileDefinitionsPosition; + std::vector<std::string>::size_type CompileOptionsPosition; +}; + +struct cmState::PolicyStackEntry: public cmPolicies::PolicyMap +{ + typedef cmPolicies::PolicyMap derived; + PolicyStackEntry(bool w = false): derived(), Weak(w) {} + PolicyStackEntry(derived const& d, bool w): derived(d), Weak(w) {} + PolicyStackEntry(PolicyStackEntry const& r): derived(r), Weak(r.Weak) {} + bool Weak; +}; + +struct cmState::BuildsystemDirectoryStateType +{ + cmState::PositionType DirectoryEnd; + + std::string Location; + std::string OutputLocation; + + std::vector<std::string> CurrentSourceDirectoryComponents; + std::vector<std::string> CurrentBinaryDirectoryComponents; + // The top-most directories for relative path conversion. Both the + // source and destination location of a relative path conversion + // must be underneath one of these directories (both under source or + // both under binary) in order for the relative path to be evaluated + // safely by the build tools. + std::string RelativePathTopSource; + std::string RelativePathTopBinary; + + std::vector<std::string> IncludeDirectories; + std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces; + + std::vector<std::string> CompileDefinitions; + std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; + + std::vector<std::string> CompileOptions; + std::vector<cmListFileBacktrace> CompileOptionsBacktraces; + + std::string ProjectName; + + cmPropertyMap Properties; + + std::vector<cmState::Snapshot> Children; +}; + cmState::cmState(cmake* cm) : CMakeInstance(cm), IsInTryCompile(false), @@ -195,34 +259,38 @@ void cmState::RemoveCacheEntryProperty(std::string const& key, ->GetCacheIterator(key.c_str()).SetProperty(propertyName, (void*)0); } -void cmState::Reset() +cmState::Snapshot cmState::Reset() { this->GlobalProperties.clear(); this->PropertyDefinitions.clear(); - assert(this->Locations.size() > 0); - assert(this->OutputLocations.size() > 0); - assert(this->ParentPositions.size() > 0); - assert(this->CurrentSourceDirectoryComponents.size() > 0); - assert(this->CurrentBinaryDirectoryComponents.size() > 0); - assert(this->RelativePathTopSource.size() > 0); - assert(this->RelativePathTopBinary.size() > 0); - - this->Locations.erase(this->Locations.begin() + 1, this->Locations.end()); - this->OutputLocations.erase(this->OutputLocations.begin() + 1, - this->OutputLocations.end()); - this->ParentPositions.erase(this->ParentPositions.begin() + 1, - this->ParentPositions.end()); - this->CurrentSourceDirectoryComponents.erase( - this->CurrentSourceDirectoryComponents.begin() + 1, - this->CurrentSourceDirectoryComponents.end()); - this->CurrentBinaryDirectoryComponents.erase( - this->CurrentBinaryDirectoryComponents.begin() + 1, - this->CurrentBinaryDirectoryComponents.end()); - this->RelativePathTopSource.erase(this->RelativePathTopSource.begin() + 1, - this->RelativePathTopSource.end()); - this->RelativePathTopBinary.erase(this->RelativePathTopBinary.begin() + 1, - this->RelativePathTopBinary.end()); + PositionType pos = this->SnapshotData.Truncate(); + this->ExecutionListFiles.Truncate(); + + { + cmLinkedTree<BuildsystemDirectoryStateType>::iterator it = + this->BuildsystemDirectory.Truncate(); + it->IncludeDirectories.clear(); + it->IncludeDirectoryBacktraces.clear(); + it->CompileDefinitions.clear(); + it->CompileDefinitionsBacktraces.clear(); + it->CompileOptions.clear(); + it->CompileOptionsBacktraces.clear(); + it->DirectoryEnd = pos; + it->Properties.clear(); + it->Children.clear(); + } + + this->PolicyStack.Clear(); + pos->Policies = this->PolicyStack.Root(); + pos->PolicyRoot = this->PolicyStack.Root(); + pos->PolicyScope = this->PolicyStack.Root(); + assert(pos->Policies.IsValid()); + assert(pos->PolicyRoot.IsValid()); + this->VarTree.Clear(); + pos->Vars = this->VarTree.Extend(this->VarTree.Root()); + pos->Parent = this->VarTree.Root(); + pos->Root = this->VarTree.Root(); this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, @@ -243,6 +311,8 @@ void cmState::Reset() this->DefineProperty ("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true); + + return Snapshot(this, pos); } void cmState::DefineProperty(const std::string& name, @@ -256,27 +326,41 @@ void cmState::DefineProperty(const std::string& name, chained); } -cmPropertyDefinition *cmState +cmPropertyDefinition const* cmState ::GetPropertyDefinition(const std::string& name, - cmProperty::ScopeType scope) + cmProperty::ScopeType scope) const { if (this->IsPropertyDefined(name,scope)) { - return &(this->PropertyDefinitions[scope][name]); + cmPropertyDefinitionMap const& defs = + this->PropertyDefinitions.find(scope)->second; + return &defs.find(name)->second; } return 0; } bool cmState::IsPropertyDefined(const std::string& name, - cmProperty::ScopeType scope) + cmProperty::ScopeType scope) const { - return this->PropertyDefinitions[scope].IsPropertyDefined(name); + std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it + = this->PropertyDefinitions.find(scope); + if (it == this->PropertyDefinitions.end()) + { + return false; + } + return it->second.IsPropertyDefined(name); } bool cmState::IsPropertyChained(const std::string& name, - cmProperty::ScopeType scope) + cmProperty::ScopeType scope) const { - return this->PropertyDefinitions[scope].IsPropertyChained(name); + std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it + = this->PropertyDefinitions.find(scope); + if (it == this->PropertyDefinitions.end()) + { + return false; + } + return it->second.IsPropertyChained(name); } void cmState::SetLanguageEnabled(std::string const& l) @@ -435,20 +519,17 @@ void cmState::RemoveUserDefinedCommands() void cmState::SetGlobalProperty(const std::string& prop, const char* value) { - this->GlobalProperties.SetProperty(prop, value, cmProperty::GLOBAL); + this->GlobalProperties.SetProperty(prop, value); } void cmState::AppendGlobalProperty(const std::string& prop, const char* value, bool asString) { - this->GlobalProperties.AppendProperty(prop, value, - cmProperty::GLOBAL, asString); + this->GlobalProperties.AppendProperty(prop, value, asString); } const char *cmState::GetGlobalProperty(const std::string& prop) { - // watch for special properties - std::string output = ""; if ( prop == "CACHE_VARIABLES" ) { std::vector<std::string> cacheKeys = this->GetCacheEntryKeys(); @@ -480,9 +561,7 @@ const char *cmState::GetGlobalProperty(const std::string& prop) return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1; } #undef STRING_LIST_ELEMENT - bool dummy = false; - return this->GlobalProperties.GetPropertyValue(prop, cmProperty::GLOBAL, - dummy); + return this->GlobalProperties.GetPropertyValue(prop); } bool cmState::GetGlobalPropertyAsBool(const std::string& prop) @@ -590,18 +669,18 @@ std::vector<std::string> const& cmState::GetBinaryDirectoryComponents() const return this->BinaryDirectoryComponents; } -void cmState::Snapshot::ComputeRelativePathTopSource() +void cmState::Directory::ComputeRelativePathTopSource() { // Relative path conversion inside the source tree is not used to // construct relative paths passed to build tools so it is safe to use // even when the source is a network path. - cmState::Snapshot snapshot = *this; + cmState::Snapshot snapshot = this->Snapshot_; std::vector<cmState::Snapshot> snapshots; snapshots.push_back(snapshot); while (true) { - snapshot = snapshot.GetParent(); + snapshot = snapshot.GetBuildsystemDirectoryParent(); if (snapshot.IsValid()) { snapshots.push_back(snapshot); @@ -612,28 +691,28 @@ void cmState::Snapshot::ComputeRelativePathTopSource() } } - std::string result = snapshots.front().GetCurrentSourceDirectory(); + std::string result = snapshots.front().GetDirectory().GetCurrentSource(); for (std::vector<cmState::Snapshot>::const_iterator it = snapshots.begin() + 1; it != snapshots.end(); ++it) { - std::string currentSource = it->GetCurrentSourceDirectory(); + std::string currentSource = it->GetDirectory().GetCurrentSource(); if(cmSystemTools::IsSubDirectory(result, currentSource)) { result = currentSource; } } - this->State->RelativePathTopSource[this->Position] = result; + this->DirectoryState->RelativePathTopSource = result; } -void cmState::Snapshot::ComputeRelativePathTopBinary() +void cmState::Directory::ComputeRelativePathTopBinary() { - cmState::Snapshot snapshot = *this; + cmState::Snapshot snapshot = this->Snapshot_; std::vector<cmState::Snapshot> snapshots; snapshots.push_back(snapshot); while (true) { - snapshot = snapshot.GetParent(); + snapshot = snapshot.GetBuildsystemDirectoryParent(); if (snapshot.IsValid()) { snapshots.push_back(snapshot); @@ -645,12 +724,12 @@ void cmState::Snapshot::ComputeRelativePathTopBinary() } std::string result = - snapshots.front().GetCurrentBinaryDirectory(); + snapshots.front().GetDirectory().GetCurrentBinary(); for (std::vector<cmState::Snapshot>::const_iterator it = snapshots.begin() + 1; it != snapshots.end(); ++it) { - std::string currentBinary = it->GetCurrentBinaryDirectory(); + std::string currentBinary = it->GetDirectory().GetCurrentBinary(); if(cmSystemTools::IsSubDirectory(result, currentBinary)) { result = currentBinary; @@ -662,33 +741,215 @@ void cmState::Snapshot::ComputeRelativePathTopBinary() // is a network path. if(result.size() < 2 || result.substr(0, 2) != "//") { - this->State->RelativePathTopBinary[this->Position] = result; + this->DirectoryState->RelativePathTopBinary = result; } else { - this->State->RelativePathTopBinary[this->Position] = ""; + this->DirectoryState->RelativePathTopBinary = ""; } } -cmState::Snapshot cmState::CreateSnapshot(Snapshot originSnapshot) +cmState::Snapshot cmState::CreateBaseSnapshot() +{ + PositionType pos = this->SnapshotData.Extend(this->SnapshotData.Root()); + pos->DirectoryParent = this->SnapshotData.Root(); + pos->ScopeParent = this->SnapshotData.Root(); + pos->SnapshotType = BaseType; + pos->BuildSystemDirectory = + this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root()); + pos->ExecutionListFile = + this->ExecutionListFiles.Extend(this->ExecutionListFiles.Root()); + pos->IncludeDirectoryPosition = 0; + pos->CompileDefinitionsPosition = 0; + pos->CompileOptionsPosition = 0; + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->Policies = this->PolicyStack.Root(); + pos->PolicyRoot = this->PolicyStack.Root(); + pos->PolicyScope = this->PolicyStack.Root(); + assert(pos->Policies.IsValid()); + assert(pos->PolicyRoot.IsValid()); + pos->Vars = this->VarTree.Extend(this->VarTree.Root()); + assert(pos->Vars.IsValid()); + pos->Parent = this->VarTree.Root(); + pos->Root = this->VarTree.Root(); + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot +cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine) +{ + assert(originSnapshot.IsValid()); + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position); + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->DirectoryParent = originSnapshot.Position; + pos->ScopeParent = originSnapshot.Position; + pos->SnapshotType = BuildsystemDirectoryType; + pos->BuildSystemDirectory = + this->BuildsystemDirectory.Extend( + originSnapshot.Position->BuildSystemDirectory); + pos->ExecutionListFile = + this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile); + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->Policies = originSnapshot.Position->Policies; + pos->PolicyRoot = originSnapshot.Position->Policies; + pos->PolicyScope = originSnapshot.Position->Policies; + assert(pos->Policies.IsValid()); + assert(pos->PolicyRoot.IsValid()); + + cmLinkedTree<cmDefinitions>::iterator origin = + originSnapshot.Position->Vars; + pos->Parent = origin; + pos->Root = origin; + pos->Vars = this->VarTree.Extend(origin); + cmState::Snapshot snapshot = cmState::Snapshot(this, pos); + originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot); + return snapshot; +} + +cmState::Snapshot +cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->ScopeParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = FunctionCallType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->PolicyScope = originSnapshot.Position->Policies; + assert(originSnapshot.Position->Vars.IsValid()); + cmLinkedTree<cmDefinitions>::iterator origin = + originSnapshot.Position->Vars; + pos->Parent = origin; + pos->Vars = this->VarTree.Extend(origin); + return cmState::Snapshot(this, pos); +} + + +cmState::Snapshot +cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName) { - if (!originSnapshot.IsValid()) - { - originSnapshot.State = this; - } - PositionType pos = this->ParentPositions.size(); - this->ParentPositions.push_back(originSnapshot.Position); - this->Locations.resize(this->Locations.size() + 1); - this->OutputLocations.resize(this->OutputLocations.size() + 1); - this->CurrentSourceDirectoryComponents.resize( - this->CurrentSourceDirectoryComponents.size() + 1); - this->CurrentBinaryDirectoryComponents.resize( - this->CurrentBinaryDirectoryComponents.size() + 1); - this->RelativePathTopSource.resize(this->RelativePathTopSource.size() + 1); - this->RelativePathTopBinary.resize(this->RelativePathTopBinary.size() + 1); + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = MacroCallType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + assert(originSnapshot.Position->Vars.IsValid()); + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->PolicyScope = originSnapshot.Position->Policies; + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot +cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot, + const std::string& entryPointCommand, + long entryPointLine, + const std::string& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = CallStackType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + assert(originSnapshot.Position->Vars.IsValid()); + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->PolicyScope = originSnapshot.Position->Policies; + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot +cmState::CreateVariableScopeSnapshot(cmState::Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->ScopeParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = VariableScopeType; + assert(originSnapshot.Position->Vars.IsValid()); + + cmLinkedTree<cmDefinitions>::iterator origin = + originSnapshot.Position->Vars; + pos->Parent = origin; + pos->Vars = this->VarTree.Extend(origin); + assert(pos->Vars.IsValid()); return cmState::Snapshot(this, pos); } +cmState::Snapshot +cmState::CreateInlineListFileSnapshot(cmState::Snapshot originSnapshot, + const std::string& entryPointCommand, + long entryPointLine, + const std::string& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = InlineListFileType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->PolicyScope = originSnapshot.Position->Policies; + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot +cmState::CreatePolicyScopeSnapshot(cmState::Snapshot originSnapshot) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->SnapshotType = PolicyScopeType; + pos->BuildSystemDirectory->DirectoryEnd = pos; + pos->PolicyScope = originSnapshot.Position->Policies; + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot) +{ + PositionType pos = originSnapshot.Position; + PositionType prevPos = pos; + ++prevPos; + prevPos->IncludeDirectoryPosition = + prevPos->BuildSystemDirectory->IncludeDirectories.size(); + prevPos->CompileDefinitionsPosition = + prevPos->BuildSystemDirectory->CompileDefinitions.size(); + prevPos->CompileOptionsPosition = + prevPos->BuildSystemDirectory->CompileOptions.size(); + prevPos->BuildSystemDirectory->DirectoryEnd = prevPos; + + return Snapshot(this, prevPos); +} + +cmState::Snapshot::Snapshot(cmState* state) + : State(state) + , Position() +{ +} + +std::vector<cmState::Snapshot> cmState::Snapshot::GetChildren() +{ + return this->Position->BuildSystemDirectory->Children; +} + cmState::Snapshot::Snapshot(cmState* state, PositionType position) : State(state), Position(position) @@ -696,94 +957,779 @@ cmState::Snapshot::Snapshot(cmState* state, PositionType position) } -const char* cmState::Snapshot::GetCurrentSourceDirectory() const +cmState::SnapshotType cmState::Snapshot::GetType() const { - return this->State->Locations[this->Position].c_str(); + return this->Position->SnapshotType; } -void cmState::Snapshot::SetCurrentSourceDirectory(std::string const& dir) +const char* cmState::Directory::GetCurrentSource() const { - assert(this->State); - assert(this->State->Locations.size() > this->Position); - this->State->Locations[this->Position] = dir; - cmSystemTools::ConvertToUnixSlashes( - this->State->Locations[this->Position]); - this->State->Locations[this->Position] = - cmSystemTools::CollapseFullPath(this->State->Locations[this->Position]); + return this->DirectoryState->Location.c_str(); +} + +void cmState::Directory::SetCurrentSource(std::string const& dir) +{ + std::string& loc = this->DirectoryState->Location; + loc = dir; + cmSystemTools::ConvertToUnixSlashes(loc); + loc = cmSystemTools::CollapseFullPath(loc); cmSystemTools::SplitPath( - this->State->Locations[this->Position], - this->State->CurrentSourceDirectoryComponents[this->Position]); + loc, + this->DirectoryState->CurrentSourceDirectoryComponents); this->ComputeRelativePathTopSource(); } -const char* cmState::Snapshot::GetCurrentBinaryDirectory() const +const char* cmState::Directory::GetCurrentBinary() const { - return this->State->OutputLocations[this->Position].c_str(); + return this->DirectoryState->OutputLocation.c_str(); } -void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir) +void cmState::Directory::SetCurrentBinary(std::string const& dir) { - assert(this->State->OutputLocations.size() > this->Position); - this->State->OutputLocations[this->Position] = dir; - cmSystemTools::ConvertToUnixSlashes( - this->State->OutputLocations[this->Position]); - this->State->OutputLocations[this->Position] = - cmSystemTools::CollapseFullPath( - this->State->OutputLocations[this->Position]); + std::string& loc = this->DirectoryState->OutputLocation; + loc = dir; + cmSystemTools::ConvertToUnixSlashes(loc); + loc = cmSystemTools::CollapseFullPath(loc); cmSystemTools::SplitPath( - this->State->OutputLocations[this->Position], - this->State->CurrentBinaryDirectoryComponents[this->Position]); + loc, + this->DirectoryState->CurrentBinaryDirectoryComponents); this->ComputeRelativePathTopBinary(); } +void cmState::Snapshot::SetListFile(const std::string& listfile) +{ + *this->Position->ExecutionListFile = listfile; +} + std::vector<std::string> const& -cmState::Snapshot::GetCurrentSourceDirectoryComponents() +cmState::Directory::GetCurrentSourceComponents() const { - return this->State->CurrentSourceDirectoryComponents[this->Position]; + return this->DirectoryState->CurrentSourceDirectoryComponents; } std::vector<std::string> const& -cmState::Snapshot::GetCurrentBinaryDirectoryComponents() +cmState::Directory::GetCurrentBinaryComponents() const +{ + return this->DirectoryState->CurrentBinaryDirectoryComponents; +} + +const char* cmState::Directory::GetRelativePathTopSource() const +{ + return this->DirectoryState->RelativePathTopSource.c_str(); +} + +const char* cmState::Directory::GetRelativePathTopBinary() const +{ + return this->DirectoryState->RelativePathTopBinary.c_str(); +} + +void cmState::Directory::SetRelativePathTopSource(const char* dir) { - return this->State->CurrentBinaryDirectoryComponents[this->Position]; + this->DirectoryState->RelativePathTopSource = dir; } -const char* cmState::Snapshot::GetRelativePathTopSource() const +void cmState::Directory::SetRelativePathTopBinary(const char* dir) { - return this->State->RelativePathTopSource[this->Position].c_str(); + this->DirectoryState->RelativePathTopBinary = dir; } -const char* cmState::Snapshot::GetRelativePathTopBinary() const +std::string cmState::Snapshot::GetExecutionListFile() const { - return this->State->RelativePathTopBinary[this->Position].c_str(); + return *this->Position->ExecutionListFile; } -void cmState::Snapshot::SetRelativePathTopSource(const char* dir) +std::string cmState::Snapshot::GetEntryPointCommand() const { - this->State->RelativePathTopSource[this->Position] = dir; + return this->Position->EntryPointCommand; } -void cmState::Snapshot::SetRelativePathTopBinary(const char* dir) +long cmState::Snapshot::GetEntryPointLine() const { - this->State->RelativePathTopBinary[this->Position] = dir; + return this->Position->EntryPointLine; } bool cmState::Snapshot::IsValid() const { - return this->State ? true : false; + return this->State && this->Position.IsValid() + ? this->Position != this->State->SnapshotData.Root() + : false; } -cmState::Snapshot cmState::Snapshot::GetParent() const +cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const { Snapshot snapshot; - if (!this->State || this->Position == 0) + if (!this->State || this->Position == this->State->SnapshotData.Root()) { return snapshot; } - PositionType parentPos = this->State->ParentPositions[this->Position]; - snapshot = Snapshot(this->State, parentPos); + PositionType parentPos = this->Position->DirectoryParent; + if (parentPos != this->State->SnapshotData.Root()) + { + snapshot = Snapshot(this->State, parentPos); + } return snapshot; } + +cmState::Snapshot cmState::Snapshot::GetCallStackParent() const +{ + assert(this->State); + assert(this->Position != this->State->SnapshotData.Root()); + + Snapshot snapshot; + PositionType parentPos = this->Position; + while(parentPos->SnapshotType == cmState::PolicyScopeType) + { + ++parentPos; + } + if (parentPos->SnapshotType == cmState::BuildsystemDirectoryType + || parentPos->SnapshotType == cmState::BaseType) + { + return snapshot; + } + + ++parentPos; + while(parentPos->SnapshotType == cmState::PolicyScopeType) + { + ++parentPos; + } + + if (parentPos == this->State->SnapshotData.Root()) + { + return snapshot; + } + + snapshot = Snapshot(this->State, parentPos); + return snapshot; +} + +void cmState::Snapshot::PushPolicy(cmPolicies::PolicyMap entry, bool weak) +{ + PositionType pos = this->Position; + pos->Policies = + this->State->PolicyStack.Extend(pos->Policies, + PolicyStackEntry(entry, weak)); +} + +bool cmState::Snapshot::PopPolicy() +{ + PositionType pos = this->Position; + if (pos->Policies == pos->PolicyScope) + { + return false; + } + ++pos->Policies; + return true; +} + +bool cmState::Snapshot::CanPopPolicyScope() +{ + return this->Position->Policies == this->Position->PolicyScope; +} + +void cmState::Snapshot::SetPolicy(cmPolicies::PolicyID id, + cmPolicies::PolicyStatus status) +{ + // Update the policy stack from the top to the top-most strong entry. + bool previous_was_weak = true; + for(cmLinkedTree<PolicyStackEntry>::iterator psi = this->Position->Policies; + previous_was_weak && psi != this->Position->PolicyRoot; ++psi) + { + psi->Set(id, status); + previous_was_weak = psi->Weak; + } +} + +cmPolicies::PolicyStatus +cmState::Snapshot::GetPolicy(cmPolicies::PolicyID id) const +{ + cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id); + + if(status == cmPolicies::REQUIRED_ALWAYS || + status == cmPolicies::REQUIRED_IF_USED) + { + return status; + } + + cmLinkedTree<BuildsystemDirectoryStateType>::iterator dir = + this->Position->BuildSystemDirectory; + + while (true) + { + assert(dir.IsValid()); + cmLinkedTree<PolicyStackEntry>::iterator leaf = + dir->DirectoryEnd->Policies; + cmLinkedTree<PolicyStackEntry>::iterator root = + dir->DirectoryEnd->PolicyRoot; + for( ; leaf != root; ++leaf) + { + if(leaf->IsDefined(id)) + { + status = leaf->Get(id); + return status; + } + } + cmState::PositionType e = dir->DirectoryEnd; + cmState::PositionType p = e->DirectoryParent; + if (p == this->State->SnapshotData.Root()) + { + break; + } + dir = p->BuildSystemDirectory; + } + return status; +} + +bool cmState::Snapshot::HasDefinedPolicyCMP0011() +{ + return !this->Position->Policies->IsEmpty(); +} + +const char* cmState::Snapshot::GetDefinition(std::string const& name) const +{ + assert(this->Position->Vars.IsValid()); + return cmDefinitions::Get(name, this->Position->Vars, + this->Position->Root); +} + +bool cmState::Snapshot::IsInitialized(std::string const& name) const +{ + return cmDefinitions::HasKey(name, this->Position->Vars, + this->Position->Root); +} + +void cmState::Snapshot::SetDefinition(std::string const& name, + std::string const& value) +{ + this->Position->Vars->Set(name, value.c_str()); +} + +void cmState::Snapshot::RemoveDefinition(std::string const& name) +{ + this->Position->Vars->Set(name, 0); +} + +std::vector<std::string> cmState::Snapshot::UnusedKeys() const +{ + return this->Position->Vars->UnusedKeys(); +} + +std::vector<std::string> cmState::Snapshot::ClosureKeys() const +{ + return cmDefinitions::ClosureKeys(this->Position->Vars, + this->Position->Root); +} + +bool cmState::Snapshot::RaiseScope(std::string const& var, const char* varDef) +{ + if(this->Position->ScopeParent == this->Position->DirectoryParent) + { + Snapshot parentDir = this->GetBuildsystemDirectoryParent(); + if(!parentDir.IsValid()) + { + return false; + } + // Update the definition in the parent directory top scope. This + // directory's scope was initialized by the closure of the parent + // scope, so we do not need to localize the definition first. + if (varDef) + { + parentDir.SetDefinition(var, varDef); + } + else + { + parentDir.RemoveDefinition(var); + } + return true; + } + // First localize the definition in the current scope. + cmDefinitions::Raise(var, this->Position->Vars, + this->Position->Root); + + // Now update the definition in the parent scope. + this->Position->Parent->Set(var, varDef); + return true; +} + +static const std::string cmPropertySentinal = std::string(); + +template<typename T, typename U, typename V> +void InitializeContentFromParent(T& parentContent, + T& thisContent, + U& parentBacktraces, + U& thisBacktraces, + V& contentEndPosition) +{ + std::vector<std::string>::const_iterator parentBegin = + parentContent.begin(); + std::vector<std::string>::const_iterator parentEnd = + parentContent.end(); + + std::vector<std::string>::const_reverse_iterator parentRbegin = + cmMakeReverseIterator(parentEnd); + std::vector<std::string>::const_reverse_iterator parentRend = + parentContent.rend(); + parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal); + std::vector<std::string>::const_iterator parentIt = parentRbegin.base(); + + thisContent = std::vector<std::string>(parentIt, parentEnd); + + std::vector<cmListFileBacktrace>::const_iterator btIt = + parentBacktraces.begin() + std::distance(parentBegin, parentIt); + std::vector<cmListFileBacktrace>::const_iterator btEnd = + parentBacktraces.end(); + + thisBacktraces = std::vector<cmListFileBacktrace>(btIt, btEnd); + + contentEndPosition = thisContent.size(); +} + +void cmState::Snapshot::InitializeFromParent() +{ + PositionType parent = this->Position->DirectoryParent; + assert(this->Position->Vars.IsValid()); + assert(parent->Vars.IsValid()); + + *this->Position->Vars = + cmDefinitions::MakeClosure(parent->Vars, parent->Root); + + InitializeContentFromParent(parent->BuildSystemDirectory->IncludeDirectories, + this->Position->BuildSystemDirectory->IncludeDirectories, + parent->BuildSystemDirectory->IncludeDirectoryBacktraces, + this->Position->BuildSystemDirectory->IncludeDirectoryBacktraces, + this->Position->IncludeDirectoryPosition); + + InitializeContentFromParent(parent->BuildSystemDirectory->CompileDefinitions, + this->Position->BuildSystemDirectory->CompileDefinitions, + parent->BuildSystemDirectory->CompileDefinitionsBacktraces, + this->Position->BuildSystemDirectory->CompileDefinitionsBacktraces, + this->Position->CompileDefinitionsPosition); + + InitializeContentFromParent(parent->BuildSystemDirectory->CompileOptions, + this->Position->BuildSystemDirectory->CompileOptions, + parent->BuildSystemDirectory->CompileOptionsBacktraces, + this->Position->BuildSystemDirectory->CompileOptionsBacktraces, + this->Position->CompileOptionsPosition); +} + +cmState* cmState::Snapshot::GetState() const +{ + return this->State; +} + +cmState::Directory cmState::Snapshot::GetDirectory() const +{ + return Directory(this->Position->BuildSystemDirectory, *this); +} + +void cmState::Snapshot::SetProjectName(const std::string& name) +{ + this->Position->BuildSystemDirectory->ProjectName = name; +} + +std::string cmState::Snapshot::GetProjectName() const +{ + return this->Position->BuildSystemDirectory->ProjectName; +} + +cmState::Directory::Directory( + cmLinkedTree<BuildsystemDirectoryStateType>::iterator iter, + const cmState::Snapshot& snapshot) + : DirectoryState(iter), Snapshot_(snapshot) +{ + +} + +template <typename T, typename U> +cmStringRange GetPropertyContent(T const& content, U contentEndPosition) +{ + std::vector<std::string>::const_iterator end = + content.begin() + contentEndPosition; + + std::vector<std::string>::const_reverse_iterator rbegin = + cmMakeReverseIterator(end); + rbegin = std::find(rbegin, content.rend(), cmPropertySentinal); + + return cmMakeRange(rbegin.base(), end); +} + +template <typename T, typename U, typename V> +cmBacktraceRange GetPropertyBacktraces(T const& content, + U const& backtraces, + V contentEndPosition) +{ + std::vector<std::string>::const_iterator entryEnd = + content.begin() + contentEndPosition; + + std::vector<std::string>::const_reverse_iterator rbegin = + cmMakeReverseIterator(entryEnd); + rbegin = std::find(rbegin, content.rend(), cmPropertySentinal); + + std::vector<cmListFileBacktrace>::const_iterator it = + backtraces.begin() + std::distance(content.begin(), rbegin.base()); + + std::vector<cmListFileBacktrace>::const_iterator end = backtraces.end(); + return cmMakeRange(it, end); +} + +template <typename T, typename U, typename V> +void AppendEntry(T& content, U& backtraces, V& endContentPosition, + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + assert(endContentPosition == content.size()); + + content.push_back(vec); + backtraces.push_back(lfbt); + + endContentPosition = content.size(); +} + +template <typename T, typename U, typename V> +void SetContent(T& content, U& backtraces, V& endContentPosition, + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + assert(endContentPosition == content.size()); + + content.resize(content.size() + 2); + backtraces.resize(backtraces.size() + 2); + + content.back() = vec; + backtraces.back() = lfbt; + + endContentPosition = content.size(); +} + +template <typename T, typename U, typename V> +void ClearContent(T& content, U& backtraces, V& endContentPosition) +{ + assert(endContentPosition == content.size()); + + content.resize(content.size() + 1); + backtraces.resize(backtraces.size() + 1); + + endContentPosition = content.size(); +} + +cmStringRange +cmState::Directory::GetIncludeDirectoriesEntries() const +{ + return GetPropertyContent(this->DirectoryState->IncludeDirectories, + this->Snapshot_.Position->IncludeDirectoryPosition); +} + +cmBacktraceRange +cmState::Directory::GetIncludeDirectoriesEntryBacktraces() const +{ + return GetPropertyBacktraces(this->DirectoryState->IncludeDirectories, + this->DirectoryState->IncludeDirectoryBacktraces, + this->Snapshot_.Position->IncludeDirectoryPosition); +} + +void cmState::Directory::AppendIncludeDirectoriesEntry( + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + AppendEntry(this->DirectoryState->IncludeDirectories, + this->DirectoryState->IncludeDirectoryBacktraces, + this->Snapshot_.Position->IncludeDirectoryPosition, + vec, lfbt); +} + +void cmState::Directory::PrependIncludeDirectoriesEntry( + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + std::vector<std::string>::iterator entryEnd = + this->DirectoryState->IncludeDirectories.begin() + + this->Snapshot_.Position->IncludeDirectoryPosition; + + std::vector<std::string>::reverse_iterator rend = + this->DirectoryState->IncludeDirectories.rend(); + std::vector<std::string>::reverse_iterator rbegin = + cmMakeReverseIterator(entryEnd); + rbegin = std::find(rbegin, rend, cmPropertySentinal); + + std::vector<std::string>::iterator entryIt = rbegin.base(); + std::vector<std::string>::iterator entryBegin = + this->DirectoryState->IncludeDirectories.begin(); + + std::vector<cmListFileBacktrace>::iterator btIt = + this->DirectoryState->IncludeDirectoryBacktraces.begin() + + std::distance(entryBegin, entryIt); + + this->DirectoryState->IncludeDirectories.insert(entryIt, vec); + this->DirectoryState->IncludeDirectoryBacktraces.insert(btIt, lfbt); + + this->Snapshot_.Position->IncludeDirectoryPosition = + this->DirectoryState->IncludeDirectories.size(); +} + +void cmState::Directory::SetIncludeDirectories( + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + SetContent(this->DirectoryState->IncludeDirectories, + this->DirectoryState->IncludeDirectoryBacktraces, + this->Snapshot_.Position->IncludeDirectoryPosition, + vec, lfbt); +} + +void cmState::Directory::ClearIncludeDirectories() +{ + ClearContent(this->DirectoryState->IncludeDirectories, + this->DirectoryState->IncludeDirectoryBacktraces, + this->Snapshot_.Position->IncludeDirectoryPosition); +} + +cmStringRange cmState::Directory::GetCompileDefinitionsEntries() const +{ + return GetPropertyContent(this->DirectoryState->CompileDefinitions, + this->Snapshot_.Position->CompileDefinitionsPosition); +} + +cmBacktraceRange +cmState::Directory::GetCompileDefinitionsEntryBacktraces() const +{ + return GetPropertyBacktraces(this->DirectoryState->CompileDefinitions, + this->DirectoryState->CompileDefinitionsBacktraces, + this->Snapshot_.Position->CompileDefinitionsPosition); +} + +void cmState::Directory::AppendCompileDefinitionsEntry(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + AppendEntry(this->DirectoryState->CompileDefinitions, + this->DirectoryState->CompileDefinitionsBacktraces, + this->Snapshot_.Position->CompileDefinitionsPosition, + vec, lfbt); +} + +void cmState::Directory::SetCompileDefinitions(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + SetContent(this->DirectoryState->CompileDefinitions, + this->DirectoryState->CompileDefinitionsBacktraces, + this->Snapshot_.Position->CompileDefinitionsPosition, + vec, lfbt); +} + +void cmState::Directory::ClearCompileDefinitions() +{ + ClearContent(this->DirectoryState->CompileDefinitions, + this->DirectoryState->CompileDefinitionsBacktraces, + this->Snapshot_.Position->CompileDefinitionsPosition); +} + +cmStringRange cmState::Directory::GetCompileOptionsEntries() const +{ + return GetPropertyContent(this->DirectoryState->CompileOptions, + this->Snapshot_.Position->CompileOptionsPosition); +} + +cmBacktraceRange cmState::Directory::GetCompileOptionsEntryBacktraces() const +{ + return GetPropertyBacktraces(this->DirectoryState->CompileOptions, + this->DirectoryState->CompileOptionsBacktraces, + this->Snapshot_.Position->CompileOptionsPosition); +} + +void +cmState::Directory::AppendCompileOptionsEntry(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + AppendEntry(this->DirectoryState->CompileOptions, + this->DirectoryState->CompileOptionsBacktraces, + this->Snapshot_.Position->CompileOptionsPosition, + vec, lfbt); +} + +void cmState::Directory::SetCompileOptions(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + SetContent(this->DirectoryState->CompileOptions, + this->DirectoryState->CompileOptionsBacktraces, + this->Snapshot_.Position->CompileOptionsPosition, + vec, lfbt); +} + +void cmState::Directory::ClearCompileOptions() +{ + ClearContent(this->DirectoryState->CompileOptions, + this->DirectoryState->CompileOptionsBacktraces, + this->Snapshot_.Position->CompileOptionsPosition); +} + +bool cmState::Snapshot::StrictWeakOrder::operator()( + const cmState::Snapshot& lhs, const cmState::Snapshot& rhs) const +{ + return lhs.Position.StrictWeakOrdered(rhs.Position); +} + +void cmState::Directory::SetProperty(const std::string& prop, + const char* value, + cmListFileBacktrace lfbt) +{ + if (prop == "INCLUDE_DIRECTORIES") + { + if (!value) + { + this->ClearIncludeDirectories(); + return; + } + this->SetIncludeDirectories(value, lfbt); + return; + } + if (prop == "COMPILE_OPTIONS") + { + if (!value) + { + this->ClearCompileOptions(); + return; + } + this->SetCompileOptions(value, lfbt); + return; + } + if (prop == "COMPILE_DEFINITIONS") + { + if (!value) + { + this->ClearCompileDefinitions(); + return; + } + this->SetCompileDefinitions(value, lfbt); + return; + } + + this->DirectoryState->Properties.SetProperty(prop, value); +} + +void cmState::Directory::AppendProperty(const std::string& prop, + const char* value, + bool asString, + cmListFileBacktrace lfbt) +{ + if (prop == "INCLUDE_DIRECTORIES") + { + this->AppendIncludeDirectoriesEntry(value, lfbt); + return; + } + if (prop == "COMPILE_OPTIONS") + { + this->AppendCompileOptionsEntry(value, lfbt); + return; + } + if (prop == "COMPILE_DEFINITIONS") + { + this->AppendCompileDefinitionsEntry(value, lfbt); + return; + } + + this->DirectoryState->Properties.AppendProperty(prop, value, asString); +} + +const char*cmState::Directory::GetProperty(const std::string& prop) const +{ + const bool chain = this->Snapshot_.State-> + IsPropertyChained(prop, cmProperty::DIRECTORY); + return this->GetProperty(prop, chain); +} + +const char* +cmState::Directory::GetProperty(const std::string& prop, bool chain) const +{ + static std::string output; + output = ""; + if (prop == "PARENT_DIRECTORY") + { + cmState::Snapshot parent = + this->Snapshot_.GetBuildsystemDirectoryParent(); + if(parent.IsValid()) + { + return parent.GetDirectory().GetCurrentSource(); + } + return ""; + } + else if (prop == "LISTFILE_STACK") + { + std::vector<std::string> listFiles; + cmState::Snapshot snp = this->Snapshot_; + while (snp.IsValid()) + { + listFiles.push_back(snp.GetExecutionListFile()); + snp = snp.GetCallStackParent(); + } + std::reverse(listFiles.begin(), listFiles.end()); + output = cmJoin(listFiles, ";"); + return output.c_str(); + } + else if ( prop == "CACHE_VARIABLES" ) + { + output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";"); + return output.c_str(); + } + else if (prop == "VARIABLES") + { + std::vector<std::string> res = this->Snapshot_.ClosureKeys(); + std::vector<std::string> cacheKeys = + this->Snapshot_.State->GetCacheEntryKeys(); + res.insert(res.end(), cacheKeys.begin(), cacheKeys.end()); + std::sort(res.begin(), res.end()); + output = cmJoin(res, ";"); + return output.c_str(); + } + else if (prop == "INCLUDE_DIRECTORIES") + { + output = cmJoin(this->GetIncludeDirectoriesEntries(), ";"); + return output.c_str(); + } + else if (prop == "COMPILE_OPTIONS") + { + output = cmJoin(this->GetCompileOptionsEntries(), ";"); + return output.c_str(); + } + else if (prop == "COMPILE_DEFINITIONS") + { + output = cmJoin(this->GetCompileDefinitionsEntries(), ";"); + return output.c_str(); + } + + const char *retVal = this->DirectoryState->Properties.GetPropertyValue(prop); + if (!retVal && chain) + { + Snapshot parentSnapshot = this->Snapshot_.GetBuildsystemDirectoryParent(); + if (parentSnapshot.IsValid()) + { + return parentSnapshot.GetDirectory().GetProperty(prop, chain); + } + return this->Snapshot_.State->GetGlobalProperty(prop); + } + + return retVal; +} + +bool cmState::Directory::GetPropertyAsBool(const std::string& prop) const +{ + return cmSystemTools::IsOn(this->GetProperty(prop)); +} + +std::vector<std::string> cmState::Directory::GetPropertyKeys() const +{ + std::vector<std::string> keys; + keys.reserve(this->DirectoryState->Properties.size()); + for(cmPropertyMap::const_iterator it = + this->DirectoryState->Properties.begin(); + it != this->DirectoryState->Properties.end(); ++it) + { + keys.push_back(it->first); + } + return keys; +} + +bool operator==(const cmState::Snapshot& lhs, const cmState::Snapshot& rhs) +{ + return lhs.Position == rhs.Position; +} + +bool operator!=(const cmState::Snapshot& lhs, const cmState::Snapshot& rhs) +{ + return lhs.Position != rhs.Position; +} diff --git a/Source/cmState.h b/Source/cmState.h index 77a066f..99e537c 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -15,49 +15,191 @@ #include "cmStandardIncludes.h" #include "cmPropertyDefinitionMap.h" #include "cmPropertyMap.h" +#include "cmLinkedTree.h" +#include "cmAlgorithms.h" +#include "cmPolicies.h" class cmake; class cmCommand; +class cmDefinitions; +class cmListFileBacktrace; class cmState { - typedef std::vector<std::string>::size_type PositionType; + struct SnapshotDataType; + struct PolicyStackEntry; + struct BuildsystemDirectoryStateType; + typedef cmLinkedTree<SnapshotDataType>::iterator PositionType; friend class Snapshot; public: cmState(cmake* cm); ~cmState(); + enum SnapshotType + { + BaseType, + BuildsystemDirectoryType, + FunctionCallType, + MacroCallType, + CallStackType, + InlineListFileType, + PolicyScopeType, + VariableScopeType + }; + + class Directory; + class Snapshot { public: - Snapshot(cmState* state = 0, PositionType position = 0); + Snapshot(cmState* state = 0); + Snapshot(cmState* state, PositionType position); + + const char* GetDefinition(std::string const& name) const; + bool IsInitialized(std::string const& name) const; + void SetDefinition(std::string const& name, std::string const& value); + void RemoveDefinition(std::string const& name); + std::vector<std::string> UnusedKeys() const; + std::vector<std::string> ClosureKeys() const; + bool RaiseScope(std::string const& var, const char* varDef); + + void SetListFile(std::string const& listfile); + + std::string GetExecutionListFile() const; + + std::vector<Snapshot> GetChildren(); + std::string GetEntryPointCommand() const; + long GetEntryPointLine() const; + + bool IsValid() const; + Snapshot GetBuildsystemDirectoryParent() const; + Snapshot GetCallStackParent() const; + SnapshotType GetType() const; - const char* GetCurrentSourceDirectory() const; - void SetCurrentSourceDirectory(std::string const& dir); - const char* GetCurrentBinaryDirectory() const; - void SetCurrentBinaryDirectory(std::string const& dir); + void InitializeFromParent(); - std::vector<std::string> const& GetCurrentSourceDirectoryComponents(); - std::vector<std::string> const& GetCurrentBinaryDirectoryComponents(); + void SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status); + cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id) const; + bool HasDefinedPolicyCMP0011(); + void PushPolicy(cmPolicies::PolicyMap entry, bool weak); + bool PopPolicy(); + bool CanPopPolicyScope(); + + cmState* GetState() const; + + Directory GetDirectory() const; + + void SetProjectName(std::string const& name); + std::string GetProjectName() const; + + struct StrictWeakOrder + { + bool operator()(const cmState::Snapshot& lhs, + const cmState::Snapshot& rhs) const; + }; + + private: + friend bool operator==(const cmState::Snapshot& lhs, + const cmState::Snapshot& rhs); + friend bool operator!=(const cmState::Snapshot& lhs, + const cmState::Snapshot& rhs); + friend class cmState; + friend class Directory; + friend struct StrictWeakOrder; + cmState* State; + cmState::PositionType Position; + }; + + class Directory + { + Directory(cmLinkedTree<BuildsystemDirectoryStateType>::iterator iter, + Snapshot const& snapshot); + public: + const char* GetCurrentSource() const; + void SetCurrentSource(std::string const& dir); + const char* GetCurrentBinary() const; + void SetCurrentBinary(std::string const& dir); + + std::vector<std::string> const& + GetCurrentSourceComponents() const; + std::vector<std::string> const& + GetCurrentBinaryComponents() const; const char* GetRelativePathTopSource() const; const char* GetRelativePathTopBinary() const; void SetRelativePathTopSource(const char* dir); void SetRelativePathTopBinary(const char* dir); - bool IsValid() const; - Snapshot GetParent() const; + cmStringRange GetIncludeDirectoriesEntries() const; + cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const; + void AppendIncludeDirectoriesEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void PrependIncludeDirectoriesEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void SetIncludeDirectories(std::string const& vec, + cmListFileBacktrace const& lfbt); + void ClearIncludeDirectories(); + + cmStringRange GetCompileDefinitionsEntries() const; + cmBacktraceRange GetCompileDefinitionsEntryBacktraces() const; + void AppendCompileDefinitionsEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void SetCompileDefinitions(std::string const& vec, + cmListFileBacktrace const& lfbt); + void ClearCompileDefinitions(); + + cmStringRange GetCompileOptionsEntries() const; + cmBacktraceRange GetCompileOptionsEntryBacktraces() const; + void AppendCompileOptionsEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void SetCompileOptions(std::string const& vec, + cmListFileBacktrace const& lfbt); + void ClearCompileOptions(); + + void SetProperty(const std::string& prop, const char *value, + cmListFileBacktrace lfbt); + void AppendProperty(const std::string& prop, const char *value, + bool asString, cmListFileBacktrace lfbt); + const char *GetProperty(const std::string& prop) const; + const char *GetProperty(const std::string& prop, bool chain) const; + bool GetPropertyAsBool(const std::string& prop) const; + std::vector<std::string> GetPropertyKeys() const; private: void ComputeRelativePathTopSource(); void ComputeRelativePathTopBinary(); private: - friend class cmState; - cmState* State; - cmState::PositionType Position; + cmLinkedTree<BuildsystemDirectoryStateType>::iterator DirectoryState; + Snapshot Snapshot_; + friend class Snapshot; }; - Snapshot CreateSnapshot(Snapshot originSnapshot); + Snapshot CreateBaseSnapshot(); + Snapshot + CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine); + Snapshot CreateFunctionCallSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreateMacroCallSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreateCallStackSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreateVariableScopeSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine); + Snapshot CreateInlineListFileSnapshot(Snapshot originSnapshot, + const std::string& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreatePolicyScopeSnapshot(Snapshot originSnapshot); + Snapshot Pop(Snapshot originSnapshot); enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL,STATIC, UNINITIALIZED }; @@ -93,7 +235,7 @@ public: void RemoveCacheEntryProperty(std::string const& key, std::string const& propertyName); - void Reset(); + Snapshot Reset(); // Define a property void DefineProperty(const std::string& name, cmProperty::ScopeType scope, const char *ShortDescription, @@ -101,12 +243,14 @@ public: bool chain = false); // get property definition - cmPropertyDefinition *GetPropertyDefinition - (const std::string& name, cmProperty::ScopeType scope); + cmPropertyDefinition const* GetPropertyDefinition + (const std::string& name, cmProperty::ScopeType scope) const; // Is a property defined? - bool IsPropertyDefined(const std::string& name, cmProperty::ScopeType scope); - bool IsPropertyChained(const std::string& name, cmProperty::ScopeType scope); + bool IsPropertyDefined(const std::string& name, + cmProperty::ScopeType scope) const; + bool IsPropertyChained(const std::string& name, + cmProperty::ScopeType scope) const; void SetLanguageEnabled(std::string const& l); bool GetLanguageEnabled(std::string const& l) const; @@ -157,19 +301,14 @@ private: std::map<std::string, cmCommand*> Commands; cmPropertyMap GlobalProperties; cmake* CMakeInstance; - std::vector<std::string> Locations; - std::vector<std::string> OutputLocations; - std::vector<PositionType> ParentPositions; - - std::vector<std::vector<std::string> > CurrentSourceDirectoryComponents; - std::vector<std::vector<std::string> > CurrentBinaryDirectoryComponents; - // The top-most directories for relative path conversion. Both the - // source and destination location of a relative path conversion - // must be underneath one of these directories (both under source or - // both under binary) in order for the relative path to be evaluated - // safely by the build tools. - std::vector<std::string> RelativePathTopSource; - std::vector<std::string> RelativePathTopBinary; + + cmLinkedTree<BuildsystemDirectoryStateType> BuildsystemDirectory; + + cmLinkedTree<std::string> ExecutionListFiles; + + cmLinkedTree<PolicyStackEntry> PolicyStack; + cmLinkedTree<SnapshotDataType> SnapshotData; + cmLinkedTree<cmDefinitions> VarTree; std::vector<std::string> SourceDirectoryComponents; std::vector<std::string> BinaryDirectoryComponents; @@ -184,4 +323,7 @@ private: bool MSYSShell; }; +bool operator==(const cmState::Snapshot& lhs, const cmState::Snapshot& rhs); +bool operator!=(const cmState::Snapshot& lhs, const cmState::Snapshot& rhs); + #endif diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index edc6afc..649fb39 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -74,6 +74,10 @@ bool cmStringCommand { return this->HandleLengthCommand(args); } + else if(subCommand == "APPEND") + { + return this->HandleAppendCommand(args); + } else if(subCommand == "CONCAT") { return this->HandleConcatCommand(args); @@ -315,7 +319,7 @@ bool cmStringCommand::RegexMatch(std::vector<std::string> const& args) } // Concatenate all the last arguments together. - std::string input = cmJoin(cmRange(args).advance(4), std::string()); + std::string input = cmJoin(cmMakeRange(args).advance(4), std::string()); // Scan through the input for all matches. std::string output; @@ -361,7 +365,7 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args) } // Concatenate all the last arguments together. - std::string input = cmJoin(cmRange(args).advance(4), std::string()); + std::string input = cmJoin(cmMakeRange(args).advance(4), std::string()); // Scan through the input for all matches. std::string output; @@ -461,7 +465,7 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args) } // Concatenate all the last arguments together. - std::string input = cmJoin(cmRange(args).advance(5), std::string()); + std::string input = cmJoin(cmMakeRange(args).advance(5), std::string()); // Scan through the input for all matches. std::string output; @@ -661,7 +665,7 @@ bool cmStringCommand::HandleReplaceCommand(std::vector<std::string> const& const std::string& replaceExpression = args[2]; const std::string& variableName = args[3]; - std::string input = cmJoin(cmRange(args).advance(4), std::string()); + std::string input = cmJoin(cmMakeRange(args).advance(4), std::string()); cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(), replaceExpression.c_str()); @@ -730,6 +734,34 @@ bool cmStringCommand } //---------------------------------------------------------------------------- +bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args) +{ + if(args.size() < 2) + { + this->SetError("sub-command APPEND requires at least one argument."); + return false; + } + + // Skip if nothing to append. + if(args.size() < 3) + { + return true; + } + + const std::string& variable = args[1]; + + std::string value; + const char* oldValue = this->Makefile->GetDefinition(variable); + if(oldValue) + { + value = oldValue; + } + value += cmJoin(cmMakeRange(args).advance(2), std::string()); + this->Makefile->AddDefinition(variable, value.c_str()); + return true; +} + +//---------------------------------------------------------------------------- bool cmStringCommand ::HandleConcatCommand(std::vector<std::string> const& args) { @@ -740,7 +772,7 @@ bool cmStringCommand } std::string const& variableName = args[1]; - std::string value = cmJoin(cmRange(args).advance(2), std::string()); + std::string value = cmJoin(cmMakeRange(args).advance(2), std::string()); this->Makefile->AddDefinition(variableName, value.c_str()); return true; diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 9c75095..3ed17eb 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -67,6 +67,7 @@ protected: bool HandleReplaceCommand(std::vector<std::string> const& args); bool HandleLengthCommand(std::vector<std::string> const& args); bool HandleSubstringCommand(std::vector<std::string> const& args); + bool HandleAppendCommand(std::vector<std::string> const& args); bool HandleConcatCommand(std::vector<std::string> const& args); bool HandleStripCommand(std::vector<std::string> const& args); bool HandleRandomCommand(std::vector<std::string> const& args); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index b440a17..f711016 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -30,7 +30,6 @@ # include "cmLocale.h" # include <cm_libarchive.h> #endif -#include <cmsys/stl/algorithm> #include <cmsys/FStream.hxx> #include <cmsys/Terminal.h> @@ -556,25 +555,6 @@ void cmSystemTools::ParseUnixCommandLine(const char* command, argv.Store(args); } -std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg, - int shell_flags) -{ - char local_buffer[1024]; - char* buffer = local_buffer; - int size = cmsysSystem_Shell_GetArgumentSizeForWindows(arg, shell_flags); - if(size > 1024) - { - buffer = new char[size]; - } - cmsysSystem_Shell_GetArgumentForWindows(arg, buffer, shell_flags); - std::string result(buffer); - if(buffer != local_buffer) - { - delete [] buffer; - } - return result; -} - std::vector<std::string> cmSystemTools::ParseArguments(const char* command) { std::vector<std::string> args; @@ -969,8 +949,9 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname) Try multiple times since we may be racing against another process creating/opening the destination file just before our MoveFileEx. */ WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); - while(!MoveFileExW(cmsys::Encoding::ToWide(oldname).c_str(), - cmsys::Encoding::ToWide(newname).c_str(), + while(!MoveFileExW( + SystemTools::ConvertToWindowsExtendedPath(oldname).c_str(), + SystemTools::ConvertToWindowsExtendedPath(newname).c_str(), MOVEFILE_REPLACE_EXISTING) && --retry.Count) { DWORD last_error = GetLastError(); @@ -981,12 +962,14 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname) return false; } DWORD attrs = - GetFileAttributesW(cmsys::Encoding::ToWide(newname).c_str()); + GetFileAttributesW( + SystemTools::ConvertToWindowsExtendedPath(newname).c_str()); if((attrs != INVALID_FILE_ATTRIBUTES) && (attrs & FILE_ATTRIBUTE_READONLY)) { // Remove the read-only attribute from the destination file. - SetFileAttributesW(cmsys::Encoding::ToWide(newname).c_str(), + SetFileAttributesW( + SystemTools::ConvertToWindowsExtendedPath(newname).c_str(), attrs & ~FILE_ATTRIBUTE_READONLY); } else @@ -1029,6 +1012,94 @@ std::string cmSystemTools::ComputeStringMD5(const std::string& input) #endif } +//---------------------------------------------------------------------------- +std::string cmSystemTools::ComputeCertificateThumbprint( + const std::string& source) +{ + std::string thumbprint; + +#ifdef _WIN32 + BYTE* certData = NULL; + CRYPT_INTEGER_BLOB cryptBlob; + HCERTSTORE certStore = NULL; + PCCERT_CONTEXT certContext = NULL; + + HANDLE certFile = CreateFile(cmsys::Encoding::ToWide(source.c_str()).c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (certFile != INVALID_HANDLE_VALUE && certFile != NULL) + { + DWORD fileSize = GetFileSize(certFile, NULL); + if (fileSize != INVALID_FILE_SIZE) + { + certData = new BYTE[fileSize]; + if (certData != NULL) + { + DWORD dwRead = 0; + if (ReadFile(certFile, certData, fileSize, &dwRead, NULL)) + { + cryptBlob.cbData = fileSize; + cryptBlob.pbData = certData; + + // Verify that this is a valid cert + if (PFXIsPFXBlob(&cryptBlob)) + { + // Open the certificate as a store + certStore = PFXImportCertStore( + &cryptBlob, NULL, CRYPT_EXPORTABLE); + if (certStore != NULL) + { + // There should only be 1 cert. + certContext = CertEnumCertificatesInStore(certStore, + certContext); + if (certContext != NULL) + { + // The hash is 20 bytes + BYTE hashData[20]; + DWORD hashLength = 20; + + // Buffer to print the hash. Each byte takes 2 chars + + // terminating character + char hashPrint[41]; + char *pHashPrint = hashPrint; + // Get the hash property from the certificate + if (CertGetCertificateContextProperty(certContext, + CERT_HASH_PROP_ID, hashData, &hashLength)) + { + for (DWORD i = 0; i < hashLength; i++) + { + // Convert each byte to hexadecimal + sprintf(pHashPrint, "%02X", hashData[i]); + pHashPrint += 2; + } + *pHashPrint = '\0'; + thumbprint = hashPrint; + } + CertFreeCertificateContext(certContext); + } + CertCloseStore(certStore, 0); + } + } + } + delete[] certData; + } + } + CloseHandle(certFile); + } +#else + (void)source; + cmSystemTools::Message("ComputeCertificateThumbprint is not implemented", + "Error"); +#endif + + return thumbprint; +} + void cmSystemTools::Glob(const std::string& directory, const std::string& regexp, std::vector<std::string>& files) @@ -1498,7 +1569,7 @@ bool cmSystemTools::CreateTar(const char* outFileName, { #if defined(CMAKE_BUILD_WITH_CMAKE) std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmsys::ofstream fout(outFileName, std::ios::out | cmsys_ios_binary); + cmsys::ofstream fout(outFileName, std::ios::out | std::ios::binary); if(!fout) { std::string e = "Cannot open output file \""; @@ -1721,7 +1792,7 @@ bool extract_tar(const char* outFileName, bool verbose, static_cast<void>(localeRAII); struct archive* a = archive_read_new(); struct archive *ext = archive_write_disk_new(); - archive_read_support_compression_all(a); + archive_read_support_filter_all(a); archive_read_support_format_all(a); struct archive_entry *entry; int r = cm_archive_read_open_file(a, outFileName, 10240); @@ -1808,7 +1879,7 @@ bool extract_tar(const char* outFileName, bool verbose, } archive_write_free(ext); archive_read_close(a); - archive_read_finish(a); + archive_read_free(a); return r == ARCHIVE_EOF || r == ARCHIVE_OK; } } @@ -1975,11 +2046,11 @@ bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile) { #if defined(_WIN32) && !defined(__CYGWIN__) cmSystemToolsWindowsHandle hFrom = - CreateFileW(cmsys::Encoding::ToWide(fromFile).c_str(), + CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fromFile).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); cmSystemToolsWindowsHandle hTo = - CreateFileW(cmsys::Encoding::ToWide(toFile).c_str(), + CreateFileW(SystemTools::ConvertToWindowsExtendedPath(toFile).c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if(!hFrom || !hTo) { @@ -2031,7 +2102,7 @@ bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t) { #if defined(_WIN32) && !defined(__CYGWIN__) cmSystemToolsWindowsHandle h = - CreateFileW(cmsys::Encoding::ToWide(fname).c_str(), + CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fname).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(!h) { @@ -2058,7 +2129,7 @@ bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t) { #if defined(_WIN32) && !defined(__CYGWIN__) cmSystemToolsWindowsHandle h = - CreateFileW(cmsys::Encoding::ToWide(fname).c_str(), + CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fname).c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if(!h) { @@ -2955,3 +3026,12 @@ bool cmSystemTools::StringToLong(const char* str, long* value) *value = strtol(str, &endp, 10); return (*endp == '\0') && (endp != str) && (errno == 0); } + +//---------------------------------------------------------------------------- +bool cmSystemTools::StringToULong(const char* str, unsigned long* value) +{ + errno = 0; + char *endp; + *value = strtoul(str, &endp, 10); + return (*endp == '\0') && (endp != str) && (errno == 0); +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 6feb6c5..c12a1db 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -194,6 +194,9 @@ public: /** Compute the md5sum of a string. */ static std::string ComputeStringMD5(const std::string& input); + ///! Get the SHA thumbprint for a certificate file + static std::string ComputeCertificateThumbprint(const std::string& source); + /** * Run a single executable command * @@ -256,11 +259,6 @@ public: static void ParseUnixCommandLine(const char* command, std::vector<std::string>& args); - /** Compute an escaped version of the given argument for use in a - windows shell. See kwsys/System.h.in for details. */ - static std::string EscapeWindowsShellArgument(const char* arg, - int shell_flags); - static void EnableMessages() { s_DisableMessages = false; } static void DisableMessages() { s_DisableMessages = true; } static void DisableRunCommandOutput() {s_DisableRunCommandOutput = true; } @@ -469,6 +467,7 @@ public: /** Convert string to long. Expected that the whole string is an integer */ static bool StringToLong(const char* str, long* value); + static bool StringToULong(const char* str, unsigned long* value); #ifdef _WIN32 struct WindowsFileRetry diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 20d3208..4affc8d 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -13,7 +13,7 @@ #include "cmake.h" #include "cmMakefile.h" #include "cmSourceFile.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmGlobalGenerator.h" #include "cmComputeLinkInformation.h" #include "cmListFileCache.h" @@ -66,27 +66,8 @@ struct cmTarget::OutputInfo std::string OutDir; std::string ImpDir; std::string PdbDir; -}; - -//---------------------------------------------------------------------------- -struct cmTarget::ImportInfo -{ - ImportInfo(): NoSOName(false), Multiplicity(0) {} - bool NoSOName; - int Multiplicity; - std::string Location; - std::string SOName; - std::string ImportLibrary; - std::string Languages; - std::string Libraries; - std::string LibrariesProp; - std::string SharedDeps; -}; - -//---------------------------------------------------------------------------- -struct cmTarget::CompileInfo -{ - std::string CompilePdbDir; + bool empty() const + { return OutDir.empty() && ImpDir.empty() && PdbDir.empty(); } }; //---------------------------------------------------------------------------- @@ -94,15 +75,13 @@ class cmTargetInternals { public: cmTargetInternals() - : Backtrace(NULL) + : Backtrace() { - this->PolicyWarnedCMP0022 = false; this->UtilityItemsDone = false; } cmTargetInternals(cmTargetInternals const&) - : Backtrace(NULL) + : Backtrace() { - this->PolicyWarnedCMP0022 = false; this->UtilityItemsDone = false; } ~cmTargetInternals(); @@ -110,88 +89,18 @@ public: // The backtrace when the target was created. cmListFileBacktrace Backtrace; - // Cache link interface computation from each configuration. - struct OptionalLinkInterface: public cmTarget::LinkInterface - { - OptionalLinkInterface(): - LibrariesDone(false), AllDone(false), - Exists(false), HadHeadSensitiveCondition(false), - ExplicitLibraries(0) {} - bool LibrariesDone; - bool AllDone; - bool Exists; - bool HadHeadSensitiveCondition; - const char* ExplicitLibraries; - }; - void ComputeLinkInterface(cmTarget const* thisTarget, - const std::string& config, - OptionalLinkInterface& iface, - cmTarget const* head) const; - void ComputeLinkInterfaceLibraries(cmTarget const* thisTarget, - const std::string& config, - OptionalLinkInterface& iface, - cmTarget const* head, - bool usage_requirements_only); - - struct HeadToLinkInterfaceMap: - public std::map<cmTarget const*, OptionalLinkInterface> {}; - typedef std::map<std::string, HeadToLinkInterfaceMap> - LinkInterfaceMapType; - LinkInterfaceMapType LinkInterfaceMap; - LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap; - bool PolicyWarnedCMP0022; - typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType; OutputInfoMapType OutputInfoMap; typedef std::map<std::string, cmTarget::ImportInfo> ImportInfoMapType; ImportInfoMapType ImportInfoMap; - typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType; - CompileInfoMapType CompileInfoMap; - - // Cache link implementation computation from each configuration. - struct OptionalLinkImplementation: public cmTarget::LinkImplementation - { - OptionalLinkImplementation(): - LibrariesDone(false), LanguagesDone(false), - HadHeadSensitiveCondition(false) {} - bool LibrariesDone; - bool LanguagesDone; - bool HadHeadSensitiveCondition; - }; - void ComputeLinkImplementationLibraries(cmTarget const* thisTarget, - const std::string& config, - OptionalLinkImplementation& impl, - cmTarget const* head) const; - void ComputeLinkImplementationLanguages(cmTarget const* thisTarget, - const std::string& config, - OptionalLinkImplementation& impl - ) const; - struct HeadToLinkImplementationMap: - public std::map<cmTarget const*, OptionalLinkImplementation> {}; + public std::map<cmTarget const*, cmOptionalLinkImplementation> {}; typedef std::map<std::string, HeadToLinkImplementationMap> LinkImplMapType; LinkImplMapType LinkImplMap; - typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType; - LinkClosureMapType LinkClosureMap; - - struct LinkImplClosure: public std::vector<cmTarget const*> - { - LinkImplClosure(): Done(false) {} - bool Done; - }; - std::map<std::string, LinkImplClosure> LinkImplClosureMap; - - struct CompatibleInterfaces: public cmTarget::CompatibleInterfaces - { - CompatibleInterfaces(): Done(false) {} - bool Done; - }; - std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; - typedef std::map<std::string, std::vector<cmSourceFile*> > SourceFilesMapType; SourceFilesMapType SourceFilesMap; @@ -209,10 +118,14 @@ public: const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; cmLinkImplItem const& LinkImplItem; }; - std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; - std::vector<TargetPropertyEntry*> CompileOptionsEntries; - std::vector<TargetPropertyEntry*> CompileFeaturesEntries; - std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; + std::vector<std::string> IncludeDirectoriesEntries; + std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces; + std::vector<std::string> CompileOptionsEntries; + std::vector<cmListFileBacktrace> CompileOptionsBacktraces; + std::vector<std::string> CompileFeaturesEntries; + std::vector<cmListFileBacktrace> CompileFeaturesBacktraces; + std::vector<std::string> CompileDefinitionsEntries; + std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; std::vector<TargetPropertyEntry*> SourceEntries; std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries; @@ -224,14 +137,6 @@ public: cmLinkImplItem cmTargetInternals::TargetPropertyEntry::NoLinkImplItem; //---------------------------------------------------------------------------- -static void deleteAndClear( - std::vector<cmTargetInternals::TargetPropertyEntry*> &entries) -{ - cmDeleteAll(entries); - entries.clear(); -} - -//---------------------------------------------------------------------------- cmTargetInternals::~cmTargetInternals() { } @@ -239,13 +144,6 @@ cmTargetInternals::~cmTargetInternals() //---------------------------------------------------------------------------- cmTarget::cmTarget() { -#define INITIALIZE_TARGET_POLICY_MEMBER(POLICY) \ - this->PolicyStatus ## POLICY = cmPolicies::WARN; - - CM_FOR_EACH_TARGET_POLICY(INITIALIZE_TARGET_POLICY_MEMBER) - -#undef INITIALIZE_TARGET_POLICY_MEMBER - this->Makefile = 0; #if defined(_WIN32) && !defined(__CYGWIN__) this->LinkLibrariesForVS6Analyzed = false; @@ -256,10 +154,6 @@ cmTarget::cmTarget() this->IsApple = false; this->IsImportedTarget = false; this->BuildInterfaceIncludesAppended = false; - this->DebugIncludesDone = false; - this->DebugCompileOptionsDone = false; - this->DebugCompileFeaturesDone = false; - this->DebugCompileDefinitionsDone = false; this->DebugSourcesDone = false; this->LinkImplementationLanguageIsContextDependent = true; } @@ -286,9 +180,6 @@ void cmTarget::SetMakefile(cmMakefile* mf) // Set our makefile. this->Makefile = mf; - // set the cmake instance of the properties - this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); - // Check whether this is a DLL platform. this->DLLPlatform = (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") || @@ -307,6 +198,20 @@ void cmTarget::SetMakefile(cmMakefile* mf) { this->SetPropertyDefault("ANDROID_API", 0); this->SetPropertyDefault("ANDROID_API_MIN", 0); + this->SetPropertyDefault("ANDROID_ARCH", 0); + this->SetPropertyDefault("ANDROID_STL_TYPE", 0); + this->SetPropertyDefault("ANDROID_SKIP_ANT_STEP", 0); + this->SetPropertyDefault("ANDROID_PROCESS_MAX", 0); + this->SetPropertyDefault("ANDROID_PROGUARD", 0); + this->SetPropertyDefault("ANDROID_PROGUARD_CONFIG_PATH", 0); + this->SetPropertyDefault("ANDROID_SECURE_PROPS_PATH", 0); + this->SetPropertyDefault("ANDROID_NATIVE_LIB_DIRECTORIES", 0); + this->SetPropertyDefault("ANDROID_NATIVE_LIB_DEPENDENCIES", 0); + this->SetPropertyDefault("ANDROID_JAVA_SOURCE_DIR", 0); + this->SetPropertyDefault("ANDROID_JAR_DIRECTORIES", 0); + this->SetPropertyDefault("ANDROID_JAR_DEPENDENCIES", 0); + this->SetPropertyDefault("ANDROID_ASSETS_DIRECTORIES", 0); + this->SetPropertyDefault("ANDROID_ANT_ADDITIONAL_OPTIONS", 0); this->SetPropertyDefault("INSTALL_NAME_DIR", 0); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); @@ -333,14 +238,18 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("MACOSX_BUNDLE", 0); this->SetPropertyDefault("MACOSX_RPATH", 0); this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); + this->SetPropertyDefault("C_COMPILER_LAUNCHER", 0); this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("C_STANDARD", 0); this->SetPropertyDefault("C_STANDARD_REQUIRED", 0); this->SetPropertyDefault("C_EXTENSIONS", 0); + this->SetPropertyDefault("CXX_COMPILER_LAUNCHER", 0); this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("CXX_STANDARD", 0); this->SetPropertyDefault("CXX_STANDARD_REQUIRED", 0); this->SetPropertyDefault("CXX_EXTENSIONS", 0); + this->SetPropertyDefault("LINK_SEARCH_START_STATIC", 0); + this->SetPropertyDefault("LINK_SEARCH_END_STATIC", 0); } // Collect the set of configuration types. @@ -396,28 +305,35 @@ void cmTarget::SetMakefile(cmMakefile* mf) { // Initialize the INCLUDE_DIRECTORIES property based on the current value // of the same directory property: - const std::vector<cmValueWithOrigin> parentIncludes = - this->Makefile->GetIncludeDirectoriesEntries(); + const cmStringRange parentIncludes = + this->Makefile->GetIncludeDirectoriesEntries(); + const cmBacktraceRange parentIncludesBts = + this->Makefile->GetIncludeDirectoriesBacktraces(); + + this->Internal->IncludeDirectoriesEntries.insert( + this->Internal->IncludeDirectoriesEntries.end(), + parentIncludes.begin(), parentIncludes.end()); + this->Internal->IncludeDirectoriesBacktraces.insert( + this->Internal->IncludeDirectoriesBacktraces.end(), + parentIncludesBts.begin(), parentIncludesBts.end()); - for (std::vector<cmValueWithOrigin>::const_iterator it - = parentIncludes.begin(); it != parentIncludes.end(); ++it) - { - this->InsertInclude(*it); - } const std::set<std::string> parentSystemIncludes = this->Makefile->GetSystemIncludeDirectories(); this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(), parentSystemIncludes.end()); - const std::vector<cmValueWithOrigin> parentOptions = + const cmStringRange parentOptions = this->Makefile->GetCompileOptionsEntries(); + const cmBacktraceRange parentOptionsBts = + this->Makefile->GetCompileOptionsBacktraces(); - for (std::vector<cmValueWithOrigin>::const_iterator it - = parentOptions.begin(); it != parentOptions.end(); ++it) - { - this->InsertCompileOption(*it); - } + this->Internal->CompileOptionsEntries.insert( + this->Internal->CompileOptionsEntries.end(), + parentOptions.begin(), parentOptions.end()); + this->Internal->CompileOptionsBacktraces.insert( + this->Internal->CompileOptionsBacktraces.end(), + parentOptionsBts.begin(), parentOptionsBts.end()); } if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) @@ -437,26 +353,25 @@ void cmTarget::SetMakefile(cmMakefile* mf) { this->SetProperty("POSITION_INDEPENDENT_CODE", "True"); } + if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY) + { + this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", 0); + } + if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) { this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0); } // Record current policies for later use. -#define CAPTURE_TARGET_POLICY(POLICY) \ - this->PolicyStatus ## POLICY = \ - this->Makefile->GetPolicyStatus(cmPolicies::POLICY); - - CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY) - -#undef CAPTURE_TARGET_POLICY + this->Makefile->RecordPolicies(this->PolicyMap); if (this->TargetTypeValue == INTERFACE_LIBRARY) { // This policy is checked in a few conditions. The properties relevant // to the policy are always ignored for INTERFACE_LIBRARY targets, // so ensure that the conditions don't lead to nonsense. - this->PolicyStatusCMP0022 = cmPolicies::NEW; + this->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW); } if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) @@ -466,6 +381,21 @@ void cmTarget::SetMakefile(cmMakefile* mf) } } +void CreatePropertyGeneratorExpressions( + std::vector<std::string> const& entries, + std::vector<cmListFileBacktrace> const& backtraces, + std::vector<cmTargetInternals::TargetPropertyEntry*>& items) +{ + std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin(); + for (std::vector<std::string>::const_iterator it = entries.begin(); + it != entries.end(); ++it, ++btIt) + { + cmGeneratorExpression ge(*btIt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*it); + items.push_back(new cmTargetInternals::TargetPropertyEntry(cge)); + } +} + //---------------------------------------------------------------------------- void cmTarget::AddUtility(const std::string& u, cmMakefile *makefile) { @@ -525,12 +455,7 @@ void cmTarget::ClearLinkMaps() { this->LinkImplementationLanguageIsContextDependent = true; this->Internal->LinkImplMap.clear(); - this->Internal->LinkInterfaceMap.clear(); - this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear(); - this->Internal->LinkClosureMap.clear(); this->Internal->SourceFilesMap.clear(); - cmDeleteAll(this->LinkInformation); - this->LinkInformation.clear(); } //---------------------------------------------------------------------------- @@ -612,13 +537,6 @@ bool cmTarget::IsXCTestOnApple() const } //---------------------------------------------------------------------------- -bool cmTarget::IsBundleOnApple() const -{ - return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() || - this->IsCFBundleOnApple(); -} - -//---------------------------------------------------------------------------- static bool processSources(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &srcs, @@ -718,7 +636,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, { assert(this->GetType() != INTERFACE_LIBRARY); - if (this->Makefile->GetGeneratorTargets().empty()) + if (!this->Makefile->IsConfigured()) { // At configure-time, this method can be called as part of getting the // LOCATION property or to export() a file to be include()d. However @@ -764,7 +682,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, "SOURCES") != debugProperties.end(); - if (this->Makefile->IsGeneratingBuildSystem()) + if (this->Makefile->IsConfigured()) { this->DebugSourcesDone = true; } @@ -803,63 +721,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, this->LinkImplementationLanguageIsContextDependent = false; } - deleteAndClear(linkInterfaceSourcesEntries); -} - -//---------------------------------------------------------------------------- -bool -cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const -{ - std::vector<std::string> configs; - this->Makefile->GetConfigurations(configs); - if (configs.empty()) - { - configs.push_back(""); - } - - std::vector<std::string>::const_iterator it = configs.begin(); - const std::string& firstConfig = *it; - this->GetSourceFiles(files, firstConfig); - - for ( ; it != configs.end(); ++it) - { - std::vector<cmSourceFile*> configFiles; - this->GetSourceFiles(configFiles, *it); - if (configFiles != files) - { - std::string firstConfigFiles; - const char* sep = ""; - for (std::vector<cmSourceFile*>::const_iterator fi = files.begin(); - fi != files.end(); ++fi) - { - firstConfigFiles += sep; - firstConfigFiles += (*fi)->GetFullPath(); - sep = "\n "; - } - - std::string thisConfigFiles; - sep = ""; - for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin(); - fi != configFiles.end(); ++fi) - { - thisConfigFiles += sep; - thisConfigFiles += (*fi)->GetFullPath(); - sep = "\n "; - } - std::ostringstream e; - e << "Target \"" << this->Name << "\" has source files which vary by " - "configuration. This is not supported by the \"" - << this->Makefile->GetGlobalGenerator()->GetName() - << "\" generator.\n" - "Config \"" << firstConfig << "\":\n" - " " << firstConfigFiles << "\n" - "Config \"" << *it << "\":\n" - " " << thisConfigFiles << "\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - } - return true; + cmDeleteAll(linkInterfaceSourcesEntries); } //---------------------------------------------------------------------------- @@ -911,7 +773,7 @@ void cmTarget::AddTracedSources(std::vector<std::string> const& srcs) this->Internal->SourceFilesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); + cmGeneratorExpression ge(lfbt); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(srcFiles); cge->SetEvaluateForBuildsystem(true); this->Internal->SourceEntries.push_back( @@ -951,7 +813,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs) this->Internal->SourceFilesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); + cmGeneratorExpression ge(lfbt); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(srcFiles); cge->SetEvaluateForBuildsystem(true); this->Internal->SourceEntries.push_back( @@ -1084,7 +946,7 @@ cmSourceFile* cmTarget::AddSource(const std::string& src) this->Internal->SourceFilesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); + cmGeneratorExpression ge(lfbt); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src); cge->SetEvaluateForBuildsystem(true); this->Internal->SourceEntries.push_back( @@ -1257,14 +1119,14 @@ void cmTarget::GetTllSignatureTraces(std::ostringstream &s, : "plain"); s << "The uses of the " << sigString << " signature are here:\n"; typedef std::vector<std::pair<TLLSignature, cmListFileContext> > Container; - cmLocalGenerator* lg = this->GetMakefile()->GetLocalGenerator(); + cmOutputConverter converter(this->GetMakefile()->GetStateSnapshot()); for(Container::const_iterator it = this->TLLCommands.begin(); it != this->TLLCommands.end(); ++it) { if (it->first == sig) { cmListFileContext lfc = it->second; - lfc.FilePath = lg->Convert(lfc.FilePath, cmLocalGenerator::HOME); + lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); s << " * " << lfc << std::endl; } } @@ -1351,11 +1213,44 @@ cmTarget::AddSystemIncludeDirectories(const std::set<std::string> &incs) this->SystemIncludeDirectories.insert(incs.begin(), incs.end()); } -//---------------------------------------------------------------------------- -void -cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs) +cmStringRange cmTarget::GetIncludeDirectoriesEntries() const { - this->SystemIncludeDirectories.insert(incs.begin(), incs.end()); + return cmMakeRange(this->Internal->IncludeDirectoriesEntries); +} + +cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const +{ + return cmMakeRange(this->Internal->IncludeDirectoriesBacktraces); +} + +cmStringRange cmTarget::GetCompileOptionsEntries() const +{ + return cmMakeRange(this->Internal->CompileOptionsEntries); +} + +cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const +{ + return cmMakeRange(this->Internal->CompileOptionsBacktraces); +} + +cmStringRange cmTarget::GetCompileFeaturesEntries() const +{ + return cmMakeRange(this->Internal->CompileFeaturesEntries); +} + +cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const +{ + return cmMakeRange(this->Internal->CompileFeaturesBacktraces); +} + +cmStringRange cmTarget::GetCompileDefinitionsEntries() const +{ + return cmMakeRange(this->Internal->CompileDefinitionsEntries); +} + +cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const +{ + return cmMakeRange(this->Internal->CompileDefinitionsBacktraces); } #if defined(_WIN32) && !defined(__CYGWIN__) @@ -1704,39 +1599,35 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) } else if(prop == "INCLUDE_DIRECTORIES") { + this->Internal->IncludeDirectoriesEntries.clear(); + this->Internal->IncludeDirectoriesBacktraces.clear(); + this->Internal->IncludeDirectoriesEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - deleteAndClear(this->Internal->IncludeDirectoriesEntries); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - this->Internal->IncludeDirectoriesEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(cge)); + this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } else if(prop == "COMPILE_OPTIONS") { + this->Internal->CompileOptionsEntries.clear(); + this->Internal->CompileOptionsBacktraces.clear(); + this->Internal->CompileOptionsEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - deleteAndClear(this->Internal->CompileOptionsEntries); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - this->Internal->CompileOptionsEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(cge)); + this->Internal->CompileOptionsBacktraces.push_back(lfbt); } else if(prop == "COMPILE_FEATURES") { + this->Internal->CompileFeaturesEntries.clear(); + this->Internal->CompileFeaturesBacktraces.clear(); + this->Internal->CompileFeaturesEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - deleteAndClear(this->Internal->CompileFeaturesEntries); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - this->Internal->CompileFeaturesEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(cge)); + this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } else if(prop == "COMPILE_DEFINITIONS") { + this->Internal->CompileDefinitionsEntries.clear(); + this->Internal->CompileDefinitionsBacktraces.clear(); + this->Internal->CompileDefinitionsEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - deleteAndClear(this->Internal->CompileDefinitionsEntries); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - this->Internal->CompileDefinitionsEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(cge)); + this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } else if(prop == "EXPORT_NAME" && this->IsImported()) { @@ -1767,7 +1658,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) } this->Internal->SourceFilesMap.clear(); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); + cmGeneratorExpression ge(lfbt); this->Internal->SourceEntries.clear(); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->SourceEntries.push_back( @@ -1775,7 +1666,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) } else { - this->Properties.SetProperty(prop, value, cmProperty::TARGET); + this->Properties.SetProperty(prop, value); this->MaybeInvalidatePropertyCache(prop); } } @@ -1802,31 +1693,27 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, } else if(prop == "INCLUDE_DIRECTORIES") { + this->Internal->IncludeDirectoriesEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - this->Internal->IncludeDirectoriesEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } else if(prop == "COMPILE_OPTIONS") { + this->Internal->CompileOptionsEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - this->Internal->CompileOptionsEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + this->Internal->CompileOptionsBacktraces.push_back(lfbt); } else if(prop == "COMPILE_FEATURES") { + this->Internal->CompileFeaturesEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - this->Internal->CompileFeaturesEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } else if(prop == "COMPILE_DEFINITIONS") { + this->Internal->CompileDefinitionsEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - this->Internal->CompileDefinitionsEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } else if(prop == "EXPORT_NAME" && this->IsImported()) { @@ -1854,16 +1741,16 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - this->Internal->SourceFilesMap.clear(); - cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmGeneratorExpression ge(&lfbt); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - this->Internal->SourceEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(cge)); + this->Internal->SourceFilesMap.clear(); + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->SourceEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); } else { - this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); + this->Properties.AppendProperty(prop, value, asString); this->MaybeInvalidatePropertyCache(prop); } } @@ -1921,568 +1808,45 @@ void cmTarget::AppendBuildInterfaceIncludes() } //---------------------------------------------------------------------------- -void cmTarget::InsertInclude(const cmValueWithOrigin &entry, - bool before) -{ - cmGeneratorExpression ge(&entry.Backtrace); - - std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position - = before ? this->Internal->IncludeDirectoriesEntries.begin() - : this->Internal->IncludeDirectoriesEntries.end(); - - this->Internal->IncludeDirectoriesEntries.insert(position, - new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); -} - -//---------------------------------------------------------------------------- -void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry, - bool before) -{ - cmGeneratorExpression ge(&entry.Backtrace); - - std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position - = before ? this->Internal->CompileOptionsEntries.begin() - : this->Internal->CompileOptionsEntries.end(); - - this->Internal->CompileOptionsEntries.insert(position, - new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); -} - -//---------------------------------------------------------------------------- -void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry) -{ - cmGeneratorExpression ge(&entry.Backtrace); - - this->Internal->CompileDefinitionsEntries.push_back( - new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); -} - -//---------------------------------------------------------------------------- -static void processIncludeDirectories(cmTarget const* tgt, - const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, - std::vector<std::string> &includes, - UNORDERED_SET<std::string> &uniqueIncludes, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string& config, bool debugIncludes, - const std::string& language) -{ - cmMakefile *mf = tgt->GetMakefile(); - - for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator - it = entries.begin(), end = entries.end(); it != end; ++it) - { - cmLinkImplItem const& item = (*it)->LinkImplItem; - std::string const& targetName = item; - bool const fromImported = item.Target && item.Target->IsImported(); - bool const checkCMP0027 = item.FromGenex; - std::vector<std::string> entryIncludes; - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - dagChecker, language), - entryIncludes); - - std::string usedIncludes; - for(std::vector<std::string>::iterator - li = entryIncludes.begin(); li != entryIncludes.end(); ++li) - { - if (fromImported - && !cmSystemTools::FileExists(li->c_str())) - { - std::ostringstream e; - cmake::MessageType messageType = cmake::FATAL_ERROR; - if (checkCMP0027) - { - switch(tgt->GetPolicyStatusCMP0027()) - { - case cmPolicies::WARN: - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n"; - case cmPolicies::OLD: - messageType = cmake::AUTHOR_WARNING; - break; - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::NEW: - break; - } - } - e << "Imported target \"" << targetName << "\" includes " - "non-existent path\n \"" << *li << "\"\nin its " - "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n" - "* The path was deleted, renamed, or moved to another " - "location.\n" - "* An install or uninstall procedure did not complete " - "successfully.\n" - "* The installation package was faulty and references files it " - "does not provide.\n"; - tgt->GetMakefile()->IssueMessage(messageType, e.str()); - return; - } - - if (!cmSystemTools::FileIsFullPath(li->c_str())) - { - std::ostringstream e; - bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; - if (!targetName.empty()) - { - e << "Target \"" << targetName << "\" contains relative " - "path in its INTERFACE_INCLUDE_DIRECTORIES:\n" - " \"" << *li << "\""; - } - else - { - switch(tgt->GetPolicyStatusCMP0021()) - { - case cmPolicies::WARN: - { - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n"; - messageType = cmake::AUTHOR_WARNING; - } - break; - case cmPolicies::OLD: - noMessage = true; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Issue the fatal message. - break; - } - e << "Found relative path while evaluating include directories of " - "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n"; - } - if (!noMessage) - { - tgt->GetMakefile()->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) - { - return; - } - } - } - - if (!cmSystemTools::IsOff(li->c_str())) - { - cmSystemTools::ConvertToUnixSlashes(*li); - } - std::string inc = *li; - - if(uniqueIncludes.insert(inc).second) - { - includes.push_back(inc); - if (debugIncludes) - { - usedIncludes += " * " + inc + "\n"; - } - } - } - if (!usedIncludes.empty()) - { - mf->GetCMakeInstance()->IssueMessage(cmake::LOG, - std::string("Used includes for target ") - + tgt->GetName() + ":\n" - + usedIncludes, (*it)->ge->GetBacktrace()); - } - } -} - -//---------------------------------------------------------------------------- -std::vector<std::string> -cmTarget::GetIncludeDirectories(const std::string& config, - const std::string& language) const +void cmTarget::InsertInclude(std::string const& entry, + cmListFileBacktrace const& bt, + bool before) { - std::vector<std::string> includes; - UNORDERED_SET<std::string> uniqueIncludes; - - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - "INCLUDE_DIRECTORIES", 0, 0); - - std::vector<std::string> debugProperties; - const char *debugProp = - this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); - if (debugProp) - { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); - } - - bool debugIncludes = !this->DebugIncludesDone - && std::find(debugProperties.begin(), - debugProperties.end(), - "INCLUDE_DIRECTORIES") - != debugProperties.end(); - - if (this->Makefile->IsGeneratingBuildSystem()) - { - this->DebugIncludesDone = true; - } - - processIncludeDirectories(this, - this->Internal->IncludeDirectoriesEntries, - includes, - uniqueIncludes, - &dagChecker, - config, - debugIncludes, - language); - - std::vector<cmTargetInternals::TargetPropertyEntry*> - linkInterfaceIncludeDirectoriesEntries; - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_INCLUDE_DIRECTORIES", - linkInterfaceIncludeDirectoriesEntries); - - if(this->Makefile->IsOn("APPLE")) - { - LinkImplementation const* impl = this->GetLinkImplementation(config); - for(std::vector<cmLinkImplItem>::const_iterator - it = impl->Libraries.begin(); - it != impl->Libraries.end(); ++it) - { - std::string libDir = cmSystemTools::CollapseFullPath(*it); - - static cmsys::RegularExpression - frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); - if(!frameworkCheck.find(libDir)) - { - continue; - } - - libDir = frameworkCheck.match(1); - - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(libDir.c_str()); - linkInterfaceIncludeDirectoriesEntries - .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); - } - } - - processIncludeDirectories(this, - linkInterfaceIncludeDirectoriesEntries, - includes, - uniqueIncludes, - &dagChecker, - config, - debugIncludes, - language); - - deleteAndClear(linkInterfaceIncludeDirectoriesEntries); - - return includes; -} - -//---------------------------------------------------------------------------- -static void processCompileOptionsInternal(cmTarget const* tgt, - const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, - std::vector<std::string> &options, - UNORDERED_SET<std::string> &uniqueOptions, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string& config, bool debugOptions, const char *logName, - std::string const& language) -{ - cmMakefile *mf = tgt->GetMakefile(); - - for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator - it = entries.begin(), end = entries.end(); it != end; ++it) - { - std::vector<std::string> entryOptions; - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - dagChecker, - language), - entryOptions); - std::string usedOptions; - for(std::vector<std::string>::iterator - li = entryOptions.begin(); li != entryOptions.end(); ++li) - { - std::string const& opt = *li; - - if(uniqueOptions.insert(opt).second) - { - options.push_back(opt); - if (debugOptions) - { - usedOptions += " * " + opt + "\n"; - } - } - } - if (!usedOptions.empty()) - { - mf->GetCMakeInstance()->IssueMessage(cmake::LOG, - std::string("Used compile ") + logName - + std::string(" for target ") - + tgt->GetName() + ":\n" - + usedOptions, (*it)->ge->GetBacktrace()); - } - } -} - -//---------------------------------------------------------------------------- -static void processCompileOptions(cmTarget const* tgt, - const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, - std::vector<std::string> &options, - UNORDERED_SET<std::string> &uniqueOptions, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string& config, bool debugOptions, - std::string const& language) -{ - processCompileOptionsInternal(tgt, entries, options, uniqueOptions, - dagChecker, config, debugOptions, "options", - language); -} - -//---------------------------------------------------------------------------- -void cmTarget::GetAutoUicOptions(std::vector<std::string> &result, - const std::string& config) const -{ - const char *prop - = this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS", - config); - if (!prop) - { - return; - } - cmGeneratorExpression ge; - - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), - "AUTOUIC_OPTIONS", 0, 0); - cmSystemTools::ExpandListArgument(ge.Parse(prop) - ->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker), - result); -} - -//---------------------------------------------------------------------------- -void cmTarget::GetCompileOptions(std::vector<std::string> &result, - const std::string& config, - const std::string& language) const -{ - UNORDERED_SET<std::string> uniqueOptions; - - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - "COMPILE_OPTIONS", 0, 0); - - std::vector<std::string> debugProperties; - const char *debugProp = - this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); - if (debugProp) - { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); - } + std::vector<std::string>::iterator position = + before ? this->Internal->IncludeDirectoriesEntries.begin() + : this->Internal->IncludeDirectoriesEntries.end(); - bool debugOptions = !this->DebugCompileOptionsDone - && std::find(debugProperties.begin(), - debugProperties.end(), - "COMPILE_OPTIONS") - != debugProperties.end(); - - if (this->Makefile->IsGeneratingBuildSystem()) - { - this->DebugCompileOptionsDone = true; - } + std::vector<cmListFileBacktrace>::iterator btPosition = + before ? this->Internal->IncludeDirectoriesBacktraces.begin() + : this->Internal->IncludeDirectoriesBacktraces.end(); - processCompileOptions(this, - this->Internal->CompileOptionsEntries, - result, - uniqueOptions, - &dagChecker, - config, - debugOptions, - language); - - std::vector<cmTargetInternals::TargetPropertyEntry*> - linkInterfaceCompileOptionsEntries; - - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_COMPILE_OPTIONS", - linkInterfaceCompileOptionsEntries); - - processCompileOptions(this, - linkInterfaceCompileOptionsEntries, - result, - uniqueOptions, - &dagChecker, - config, - debugOptions, - language); - - deleteAndClear(linkInterfaceCompileOptionsEntries); + this->Internal->IncludeDirectoriesEntries.insert(position, entry); + this->Internal->IncludeDirectoriesBacktraces.insert(btPosition, bt); } //---------------------------------------------------------------------------- -static void processCompileDefinitions(cmTarget const* tgt, - const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, - std::vector<std::string> &options, - UNORDERED_SET<std::string> &uniqueOptions, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string& config, bool debugOptions, - std::string const& language) +void cmTarget::InsertCompileOption(std::string const& entry, + cmListFileBacktrace const& bt, + bool before) { - processCompileOptionsInternal(tgt, entries, options, uniqueOptions, - dagChecker, config, debugOptions, - "definitions", language); -} + std::vector<std::string>::iterator position = + before ? this->Internal->CompileOptionsEntries.begin() + : this->Internal->CompileOptionsEntries.end(); -//---------------------------------------------------------------------------- -void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, - const std::string& config, - const std::string& language) const -{ - UNORDERED_SET<std::string> uniqueOptions; - - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - "COMPILE_DEFINITIONS", 0, 0); - - std::vector<std::string> debugProperties; - const char *debugProp = - this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); - if (debugProp) - { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); - } - - bool debugDefines = !this->DebugCompileDefinitionsDone - && std::find(debugProperties.begin(), - debugProperties.end(), - "COMPILE_DEFINITIONS") - != debugProperties.end(); - - if (this->Makefile->IsGeneratingBuildSystem()) - { - this->DebugCompileDefinitionsDone = true; - } - - processCompileDefinitions(this, - this->Internal->CompileDefinitionsEntries, - list, - uniqueOptions, - &dagChecker, - config, - debugDefines, - language); + std::vector<cmListFileBacktrace>::iterator btPosition = + before ? this->Internal->CompileOptionsBacktraces.begin() + : this->Internal->CompileOptionsBacktraces.end(); - std::vector<cmTargetInternals::TargetPropertyEntry*> - linkInterfaceCompileDefinitionsEntries; - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_COMPILE_DEFINITIONS", - linkInterfaceCompileDefinitionsEntries); - if (!config.empty()) - { - std::string configPropName = "COMPILE_DEFINITIONS_" - + cmSystemTools::UpperCase(config); - const char *configProp = this->GetProperty(configPropName); - if (configProp) - { - switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) - { - case cmPolicies::WARN: - { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - e.str()); - } - case cmPolicies::OLD: - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(configProp); - linkInterfaceCompileDefinitionsEntries - .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); - } - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - break; - } - } - } - - processCompileDefinitions(this, - linkInterfaceCompileDefinitionsEntries, - list, - uniqueOptions, - &dagChecker, - config, - debugDefines, - language); - - deleteAndClear(linkInterfaceCompileDefinitionsEntries); -} - -//---------------------------------------------------------------------------- -static void processCompileFeatures(cmTarget const* tgt, - const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, - std::vector<std::string> &options, - UNORDERED_SET<std::string> &uniqueOptions, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string& config, bool debugOptions) -{ - processCompileOptionsInternal(tgt, entries, options, uniqueOptions, - dagChecker, config, debugOptions, "features", - std::string()); + this->Internal->CompileOptionsEntries.insert(position, entry); + this->Internal->CompileOptionsBacktraces.insert(btPosition, bt); } //---------------------------------------------------------------------------- -void cmTarget::GetCompileFeatures(std::vector<std::string> &result, - const std::string& config) const +void cmTarget::InsertCompileDefinition(std::string const& entry, + cmListFileBacktrace const& bt) { - UNORDERED_SET<std::string> uniqueFeatures; - - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - "COMPILE_FEATURES", - 0, 0); - - std::vector<std::string> debugProperties; - const char *debugProp = - this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); - if (debugProp) - { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); - } - - bool debugFeatures = !this->DebugCompileFeaturesDone - && std::find(debugProperties.begin(), - debugProperties.end(), - "COMPILE_FEATURES") - != debugProperties.end(); - - if (this->Makefile->IsGeneratingBuildSystem()) - { - this->DebugCompileFeaturesDone = true; - } - - processCompileFeatures(this, - this->Internal->CompileFeaturesEntries, - result, - uniqueFeatures, - &dagChecker, - config, - debugFeatures); - - std::vector<cmTargetInternals::TargetPropertyEntry*> - linkInterfaceCompileFeaturesEntries; - this->Internal->AddInterfaceEntries( - this, config, "INTERFACE_COMPILE_FEATURES", - linkInterfaceCompileFeaturesEntries); - - processCompileFeatures(this, - linkInterfaceCompileFeaturesEntries, - result, - uniqueFeatures, - &dagChecker, - config, - debugFeatures); - - deleteAndClear(linkInterfaceCompileFeaturesEntries); + this->Internal->CompileDefinitionsEntries.push_back(entry); + this->Internal->CompileDefinitionsBacktraces.push_back(bt); } //---------------------------------------------------------------------------- @@ -2637,59 +2001,36 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo( config_upper = cmSystemTools::UpperCase(config); } typedef cmTargetInternals::OutputInfoMapType OutputInfoMapType; - OutputInfoMapType::const_iterator i = + OutputInfoMapType::iterator i = this->Internal->OutputInfoMap.find(config_upper); if(i == this->Internal->OutputInfoMap.end()) { + // Add empty info in map to detect potential recursion. OutputInfo info; + OutputInfoMapType::value_type entry(config_upper, info); + i = this->Internal->OutputInfoMap.insert(entry).first; + + // Compute output directories. this->ComputeOutputDir(config, false, info.OutDir); this->ComputeOutputDir(config, true, info.ImpDir); if(!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) { info.PdbDir = info.OutDir; } - OutputInfoMapType::value_type entry(config_upper, info); - i = this->Internal->OutputInfoMap.insert(entry).first; - } - return &i->second; -} -//---------------------------------------------------------------------------- -cmTarget::CompileInfo const* cmTarget::GetCompileInfo( - const std::string& config) const -{ - // There is no compile information for imported targets. - if(this->IsImported()) - { - return 0; + // Now update the previously-prepared map entry. + i->second = info; } - - if(this->GetType() > cmTarget::OBJECT_LIBRARY) + else if(i->second.empty()) { - std::string msg = "cmTarget::GetCompileInfo called for "; - msg += this->GetName(); - msg += " which has type "; - msg += cmTarget::GetTargetTypeName(this->GetType()); - this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg); + // An empty map entry indicates we have been called recursively + // from the above block. + this->Makefile->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.", + this->GetBacktrace()); return 0; } - - // Lookup/compute/cache the compile information for this configuration. - std::string config_upper; - if(!config.empty()) - { - config_upper = cmSystemTools::UpperCase(config); - } - typedef cmTargetInternals::CompileInfoMapType CompileInfoMapType; - CompileInfoMapType::const_iterator i = - this->Internal->CompileInfoMap.find(config_upper); - if(i == this->Internal->CompileInfoMap.end()) - { - CompileInfo info; - this->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir); - CompileInfoMapType::value_type entry(config_upper, info); - i = this->Internal->CompileInfoMap.insert(entry).first; - } return &i->second; } @@ -2724,60 +2065,11 @@ std::string cmTarget::GetPDBDirectory(const std::string& config) const } //---------------------------------------------------------------------------- -std::string cmTarget::GetCompilePDBDirectory(const std::string& config) const -{ - if(CompileInfo const* info = this->GetCompileInfo(config)) - { - return info->CompilePdbDir; - } - return ""; -} - -//---------------------------------------------------------------------------- -const char* cmTarget::GetLocation(const std::string& config) const +const char* cmTarget::ImportedGetLocation(const std::string& config) const { static std::string location; - if (this->IsImported()) - { - location = this->ImportedGetFullPath(config, false); - } - else - { - location = this->GetFullPath(config, false); - } - return location.c_str(); -} - -//---------------------------------------------------------------------------- -const char* cmTarget::GetLocationForBuild() const -{ - static std::string location; - if(this->IsImported()) - { - location = this->ImportedGetFullPath("", false); - return location.c_str(); - } - - // Now handle the deprecated build-time configuration location. - location = this->GetDirectory(); - const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); - if(cfgid && strcmp(cfgid, ".") != 0) - { - location += "/"; - location += cfgid; - } - - if(this->IsAppBundleOnApple()) - { - std::string macdir = this->BuildMacContentDirectory("", "", false); - if(!macdir.empty()) - { - location += "/"; - location += macdir; - } - } - location += "/"; - location += this->GetFullName("", false); + assert(this->IsImported()); + location = this->ImportedGetFullPath(config, false); return location.c_str(); } @@ -2820,34 +2112,6 @@ void cmTarget::GetTargetVersion(bool soversion, } //---------------------------------------------------------------------------- -const char* cmTarget::GetFeature(const std::string& feature, - const std::string& config) const -{ - if(!config.empty()) - { - std::string featureConfig = feature; - featureConfig += "_"; - featureConfig += cmSystemTools::UpperCase(config); - if(const char* value = this->GetProperty(featureConfig)) - { - return value; - } - } - if(const char* value = this->GetProperty(feature)) - { - return value; - } - return this->Makefile->GetFeature(feature, config); -} - -//---------------------------------------------------------------------------- -bool cmTarget::GetFeatureAsBool(const std::string& feature, - const std::string& config) const -{ - return cmSystemTools::IsOn(this->GetFeature(feature, config)); -} - -//---------------------------------------------------------------------------- bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const { if (this->IsImported()) @@ -2884,22 +2148,6 @@ bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const } //---------------------------------------------------------------------------- -static void MakePropertyList(std::string& output, - std::vector<cmTargetInternals::TargetPropertyEntry*> const& values) -{ - output = ""; - std::string sep; - for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator - it = values.begin(), end = values.end(); - it != end; ++it) - { - output += sep; - output += (*it)->ge->GetInput(); - sep = ";"; - } -} - -//---------------------------------------------------------------------------- const char *cmTarget::GetProperty(const std::string& prop) const { return this->GetProperty(prop, this->Makefile); @@ -2940,12 +2188,24 @@ const char *cmTarget::GetProperty(const std::string& prop, // For an imported target this is the location of an arbitrary // available configuration. // - // For a non-imported target this is deprecated because it - // cannot take into account the per-configuration name of the - // target because the configuration type may not be known at - // CMake time. - this->Properties.SetProperty(propLOCATION, this->GetLocationForBuild(), - cmProperty::TARGET); + if(this->IsImported()) + { + this->Properties.SetProperty( + propLOCATION, this->ImportedGetFullPath("", false).c_str()); + } + else + { + // For a non-imported target this is deprecated because it + // cannot take into account the per-configuration name of the + // target because the configuration type may not be known at + // CMake time. + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + gg->CreateGenerationObjects(); + cmGeneratorTarget* gt = gg->GetGeneratorTarget(this); + this->Properties.SetProperty(propLOCATION, + gt->GetLocationForBuild()); + } + } // Support "LOCATION_<CONFIG>". @@ -2956,9 +2216,20 @@ const char *cmTarget::GetProperty(const std::string& prop, return 0; } const char* configName = prop.c_str() + 9; - this->Properties.SetProperty(prop, - this->GetLocation(configName), - cmProperty::TARGET); + + if (this->IsImported()) + { + this->Properties.SetProperty( + prop, this->ImportedGetFullPath(configName, false).c_str()); + } + else + { + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + gg->CreateGenerationObjects(); + cmGeneratorTarget* gt = gg->GetGeneratorTarget(this); + this->Properties.SetProperty( + prop, gt->GetFullPath(configName, false).c_str()); + } } // Support "<CONFIG>_LOCATION". else if(cmHasLiteralSuffix(prop, "_LOCATION")) @@ -2970,9 +2241,19 @@ const char *cmTarget::GetProperty(const std::string& prop, { return 0; } - this->Properties.SetProperty(prop, - this->GetLocation(configName), - cmProperty::TARGET); + if (this->IsImported()) + { + this->Properties.SetProperty( + prop, this->ImportedGetFullPath(configName, false).c_str()); + } + else + { + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + gg->CreateGenerationObjects(); + cmGeneratorTarget* gt = gg->GetGeneratorTarget(this); + this->Properties.SetProperty( + prop, gt->GetFullPath(configName, false).c_str()); + } } } } @@ -2987,6 +2268,8 @@ const char *cmTarget::GetProperty(const std::string& prop, MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(IMPORTED); MAKE_STATIC_PROP(NAME); + MAKE_STATIC_PROP(BINARY_DIR); + MAKE_STATIC_PROP(SOURCE_DIR); MAKE_STATIC_PROP(SOURCES); #undef MAKE_STATIC_PROP if(specialProps.empty()) @@ -2999,6 +2282,8 @@ const char *cmTarget::GetProperty(const std::string& prop, specialProps.insert(propCOMPILE_DEFINITIONS); specialProps.insert(propIMPORTED); specialProps.insert(propNAME); + specialProps.insert(propBINARY_DIR); + specialProps.insert(propSOURCE_DIR); specialProps.insert(propSOURCES); } if(specialProps.count(prop)) @@ -3037,7 +2322,7 @@ const char *cmTarget::GetProperty(const std::string& prop, } static std::string output; - MakePropertyList(output, this->Internal->IncludeDirectoriesEntries); + output = cmJoin(this->Internal->IncludeDirectoriesEntries, ";"); return output.c_str(); } else if(prop == propCOMPILE_FEATURES) @@ -3048,7 +2333,7 @@ const char *cmTarget::GetProperty(const std::string& prop, } static std::string output; - MakePropertyList(output, this->Internal->CompileFeaturesEntries); + output = cmJoin(this->Internal->CompileFeaturesEntries, ";"); return output.c_str(); } else if(prop == propCOMPILE_OPTIONS) @@ -3059,7 +2344,7 @@ const char *cmTarget::GetProperty(const std::string& prop, } static std::string output; - MakePropertyList(output, this->Internal->CompileOptionsEntries); + output = cmJoin(this->Internal->CompileOptionsEntries, ";"); return output.c_str(); } else if(prop == propCOMPILE_DEFINITIONS) @@ -3070,7 +2355,7 @@ const char *cmTarget::GetProperty(const std::string& prop, } static std::string output; - MakePropertyList(output, this->Internal->CompileDefinitionsEntries); + output = cmJoin(this->Internal->CompileDefinitionsEntries, ";"); return output.c_str(); } else if (prop == propIMPORTED) @@ -3081,6 +2366,14 @@ const char *cmTarget::GetProperty(const std::string& prop, { return this->GetName().c_str(); } + else if (prop == propBINARY_DIR) + { + return this->GetMakefile()->GetCurrentBinaryDirectory(); + } + else if (prop == propSOURCE_DIR) + { + return this->GetMakefile()->GetCurrentSourceDirectory(); + } else if(prop == propSOURCES) { if (this->Internal->SourceEntries.empty()) @@ -3174,17 +2467,19 @@ const char *cmTarget::GetProperty(const std::string& prop, } } } - this->Properties.SetProperty("SOURCES", ss.str().c_str(), - cmProperty::TARGET); + this->Properties.SetProperty("SOURCES", ss.str().c_str()); } } - bool chain = false; - const char *retVal = - this->Properties.GetPropertyValue(prop, cmProperty::TARGET, chain); - if (chain) + const char *retVal = this->Properties.GetPropertyValue(prop); + if (!retVal) { - return this->Makefile->GetProperty(prop, cmProperty::TARGET); + const bool chain = this->GetMakefile()->GetState()-> + IsPropertyChained(prop, cmProperty::TARGET); + if (chain) + { + return this->Makefile->GetProperty(prop, chain); + } } return retVal; } @@ -3196,274 +2491,6 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const } //---------------------------------------------------------------------------- -class cmTargetCollectLinkLanguages -{ -public: - cmTargetCollectLinkLanguages(cmTarget const* target, - const std::string& config, - UNORDERED_SET<std::string>& languages, - cmTarget const* head): - Config(config), Languages(languages), HeadTarget(head), - Makefile(target->GetMakefile()), Target(target) - { this->Visited.insert(target); } - - void Visit(cmLinkItem const& item) - { - if(!item.Target) - { - if(item.find("::") != std::string::npos) - { - bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; - std::ostringstream e; - switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028)) - { - case cmPolicies::WARN: - { - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; - messageType = cmake::AUTHOR_WARNING; - } - break; - case cmPolicies::OLD: - noMessage = true; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Issue the fatal message. - break; - } - - if(!noMessage) - { - e << "Target \"" << this->Target->GetName() - << "\" links to target \"" << item - << "\" but the target was not found. Perhaps a find_package() " - "call is missing for an IMPORTED target, or an ALIAS target is " - "missing?"; - this->Makefile->GetCMakeInstance()->IssueMessage(messageType, - e.str(), - this->Target->GetBacktrace()); - } - } - return; - } - if(!this->Visited.insert(item.Target).second) - { - return; - } - - cmTarget::LinkInterface const* iface = - item.Target->GetLinkInterface(this->Config, this->HeadTarget); - if(!iface) { return; } - - for(std::vector<std::string>::const_iterator - li = iface->Languages.begin(); li != iface->Languages.end(); ++li) - { - this->Languages.insert(*li); - } - - for(std::vector<cmLinkItem>::const_iterator - li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li) - { - this->Visit(*li); - } - } -private: - std::string Config; - UNORDERED_SET<std::string>& Languages; - cmTarget const* HeadTarget; - cmMakefile* Makefile; - const cmTarget* Target; - std::set<cmTarget const*> Visited; -}; - -//---------------------------------------------------------------------------- -std::string cmTarget::GetLinkerLanguage(const std::string& config) const -{ - return this->GetLinkClosure(config)->LinkerLanguage; -} - -//---------------------------------------------------------------------------- -cmTarget::LinkClosure const* -cmTarget::GetLinkClosure(const std::string& config) const -{ - std::string key(cmSystemTools::UpperCase(config)); - cmTargetInternals::LinkClosureMapType::iterator - i = this->Internal->LinkClosureMap.find(key); - if(i == this->Internal->LinkClosureMap.end()) - { - LinkClosure lc; - this->ComputeLinkClosure(config, lc); - cmTargetInternals::LinkClosureMapType::value_type entry(key, lc); - i = this->Internal->LinkClosureMap.insert(entry).first; - } - return &i->second; -} - -//---------------------------------------------------------------------------- -class cmTargetSelectLinker -{ - int Preference; - cmTarget const* Target; - cmMakefile* Makefile; - cmGlobalGenerator* GG; - UNORDERED_SET<std::string> Preferred; -public: - cmTargetSelectLinker(cmTarget const* target): Preference(0), Target(target) - { - this->Makefile = this->Target->GetMakefile(); - this->GG = this->Makefile->GetGlobalGenerator(); - } - void Consider(const std::string& lang) - { - int preference = this->GG->GetLinkerPreference(lang); - if(preference > this->Preference) - { - this->Preference = preference; - this->Preferred.clear(); - } - if(preference == this->Preference) - { - this->Preferred.insert(lang); - } - } - std::string Choose() - { - if(this->Preferred.empty()) - { - return ""; - } - else if(this->Preferred.size() > 1) - { - std::ostringstream e; - e << "Target " << this->Target->GetName() - << " contains multiple languages with the highest linker preference" - << " (" << this->Preference << "):\n"; - for(UNORDERED_SET<std::string>::const_iterator - li = this->Preferred.begin(); li != this->Preferred.end(); ++li) - { - e << " " << *li << "\n"; - } - e << "Set the LINKER_LANGUAGE property for this target."; - cmake* cm = this->Makefile->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); - } - return *this->Preferred.begin(); - } -}; - -//---------------------------------------------------------------------------- -void cmTarget::ComputeLinkClosure(const std::string& config, - LinkClosure& lc) const -{ - // Get languages built in this target. - UNORDERED_SET<std::string> languages; - LinkImplementation const* impl = this->GetLinkImplementation(config); - for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); - li != impl->Languages.end(); ++li) - { - languages.insert(*li); - } - - // Add interface languages from linked targets. - cmTargetCollectLinkLanguages cll(this, config, languages, this); - for(std::vector<cmLinkImplItem>::const_iterator - li = impl->Libraries.begin(); - li != impl->Libraries.end(); ++li) - { - cll.Visit(*li); - } - - // Store the transitive closure of languages. - for(UNORDERED_SET<std::string>::const_iterator li = languages.begin(); - li != languages.end(); ++li) - { - lc.Languages.push_back(*li); - } - - // Choose the language whose linker should be used. - if(this->GetProperty("HAS_CXX")) - { - lc.LinkerLanguage = "CXX"; - } - else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) - { - lc.LinkerLanguage = linkerLang; - } - else - { - // Find the language with the highest preference value. - cmTargetSelectLinker tsl(this); - - // First select from the languages compiled directly in this target. - for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); - li != impl->Languages.end(); ++li) - { - tsl.Consider(*li); - } - - // Now consider languages that propagate from linked targets. - for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin(); - sit != languages.end(); ++sit) - { - std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES"; - if(this->Makefile->IsOn(propagates)) - { - tsl.Consider(*sit); - } - } - - lc.LinkerLanguage = tsl.Choose(); - } -} - -//---------------------------------------------------------------------------- -void cmTarget::ExpandLinkItems(std::string const& prop, - std::string const& value, - std::string const& config, - cmTarget const* headTarget, - bool usage_requirements_only, - std::vector<cmLinkItem>& items, - bool& hadHeadSensitiveCondition) const -{ - cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0); - // The $<LINK_ONLY> expression may be in a link interface to specify private - // link dependencies that are otherwise excluded from usage requirements. - if(usage_requirements_only) - { - dagChecker.SetTransitivePropertiesOnly(); - } - std::vector<std::string> libs; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - cmSystemTools::ExpandListArgument(cge->Evaluate( - this->Makefile, - config, - false, - headTarget, - this, &dagChecker), libs); - this->LookupLinkItems(libs, items); - hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); -} - -//---------------------------------------------------------------------------- -void cmTarget::LookupLinkItems(std::vector<std::string> const& names, - std::vector<cmLinkItem>& items) const -{ - for(std::vector<std::string>::const_iterator i = names.begin(); - i != names.end(); ++i) - { - std::string name = this->CheckCMP0004(*i); - if(name == this->GetName() || name.empty()) - { - continue; - } - items.push_back(cmLinkItem(name, this->FindTargetToLink(name))); - } -} - -//---------------------------------------------------------------------------- const char* cmTarget::GetSuffixVariableInternal(bool implib) const { switch(this->GetType()) @@ -3521,133 +2548,6 @@ const char* cmTarget::GetPrefixVariableInternal(bool implib) const } //---------------------------------------------------------------------------- -std::string cmTarget::GetPDBName(const std::string& config) const -{ - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - std::vector<std::string> props; - std::string configUpper = cmSystemTools::UpperCase(config); - if(!configUpper.empty()) - { - // PDB_NAME_<CONFIG> - props.push_back("PDB_NAME_" + configUpper); - } - - // PDB_NAME - props.push_back("PDB_NAME"); - - for(std::vector<std::string>::const_iterator i = props.begin(); - i != props.end(); ++i) - { - if(const char* outName = this->GetProperty(*i)) - { - base = outName; - break; - } - } - return prefix+base+".pdb"; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetCompilePDBName(const std::string& config) const -{ - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - // Check for a per-configuration output directory target property. - std::string configUpper = cmSystemTools::UpperCase(config); - std::string configProp = "COMPILE_PDB_NAME_"; - configProp += configUpper; - const char* config_name = this->GetProperty(configProp); - if(config_name && *config_name) - { - return prefix + config_name + ".pdb"; - } - - const char* name = this->GetProperty("COMPILE_PDB_NAME"); - if(name && *name) - { - return prefix + name + ".pdb"; - } - - return ""; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetCompilePDBPath(const std::string& config) const -{ - std::string dir = this->GetCompilePDBDirectory(config); - std::string name = this->GetCompilePDBName(config); - if(dir.empty() && !name.empty()) - { - dir = this->GetPDBDirectory(config); - } - if(!dir.empty()) - { - dir += "/"; - } - return dir + name; -} - -//---------------------------------------------------------------------------- -bool cmTarget::HasSOName(const std::string& config) const -{ - // soname is supported only for shared libraries and modules, - // and then only when the platform supports an soname flag. - return ((this->GetType() == cmTarget::SHARED_LIBRARY || - this->GetType() == cmTarget::MODULE_LIBRARY) && - !this->GetPropertyAsBool("NO_SONAME") && - this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetSOName(const std::string& config) const -{ - if(this->IsImported()) - { - // Lookup the imported soname. - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) - { - if(info->NoSOName) - { - // The imported library has no builtin soname so the name - // searched at runtime will be just the filename. - return cmSystemTools::GetFilenameName(info->Location); - } - else - { - // Use the soname given if any. - if(info->SOName.find("@rpath/") == 0) - { - return info->SOName.substr(6); - } - return info->SOName; - } - } - else - { - return ""; - } - } - else - { - // Compute the soname that will be built. - std::string name; - std::string soName; - std::string realName; - std::string impName; - std::string pdbName; - this->GetLibraryNames(name, soName, realName, impName, pdbName, config); - return soName; - } -} - -//---------------------------------------------------------------------------- bool cmTarget::HasMacOSXRpathInstallNameDir(const std::string& config) const { bool install_name_is_rpath = false; @@ -3774,58 +2674,6 @@ bool cmTarget::IsImportedSharedLibWithoutSOName( } //---------------------------------------------------------------------------- -std::string cmTarget::NormalGetRealName(const std::string& config) const -{ - // This should not be called for imported targets. - // TODO: Split cmTarget into a class hierarchy to get compile-time - // enforcement of the limited imported target API. - if(this->IsImported()) - { - std::string msg = "NormalGetRealName called on imported target: "; - msg += this->GetName(); - this->GetMakefile()-> - IssueMessage(cmake::INTERNAL_ERROR, - msg); - } - - if(this->GetType() == cmTarget::EXECUTABLE) - { - // Compute the real name that will be built. - std::string name; - std::string realName; - std::string impName; - std::string pdbName; - this->GetExecutableNames(name, realName, impName, pdbName, config); - return realName; - } - else - { - // Compute the real name that will be built. - std::string name; - std::string soName; - std::string realName; - std::string impName; - std::string pdbName; - this->GetLibraryNames(name, soName, realName, impName, pdbName, config); - return realName; - } -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetFullName(const std::string& config, - bool implib) const -{ - if(this->IsImported()) - { - return this->GetFullNameImported(config, implib); - } - else - { - return this->GetFullNameInternal(config, implib); - } -} - -//---------------------------------------------------------------------------- std::string cmTarget::GetFullNameImported(const std::string& config, bool implib) const { @@ -3834,57 +2682,6 @@ cmTarget::GetFullNameImported(const std::string& config, bool implib) const } //---------------------------------------------------------------------------- -void cmTarget::GetFullNameComponents(std::string& prefix, std::string& base, - std::string& suffix, - const std::string& config, - bool implib) const -{ - this->GetFullNameInternal(config, implib, prefix, base, suffix); -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetFullPath(const std::string& config, bool implib, - bool realname) const -{ - if(this->IsImported()) - { - return this->ImportedGetFullPath(config, implib); - } - else - { - return this->NormalGetFullPath(config, implib, realname); - } -} - -//---------------------------------------------------------------------------- -std::string cmTarget::NormalGetFullPath(const std::string& config, - bool implib, bool realname) const -{ - std::string fpath = this->GetDirectory(config, implib); - fpath += "/"; - if(this->IsAppBundleOnApple()) - { - fpath = this->BuildMacContentDirectory(fpath, config, false); - fpath += "/"; - } - - // Add the full name of the target. - if(implib) - { - fpath += this->GetFullName(config, true); - } - else if(realname) - { - fpath += this->NormalGetRealName(config); - } - else - { - fpath += this->GetFullName(config, false); - } - return fpath; -} - -//---------------------------------------------------------------------------- std::string cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const { @@ -3902,237 +2699,6 @@ cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const } //---------------------------------------------------------------------------- -std::string -cmTarget::GetFullNameInternal(const std::string& config, bool implib) const -{ - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, implib, prefix, base, suffix); - return prefix+base+suffix; -} - -//---------------------------------------------------------------------------- -void cmTarget::GetFullNameInternal(const std::string& config, - bool implib, - std::string& outPrefix, - std::string& outBase, - std::string& outSuffix) const -{ - // Use just the target name for non-main target types. - if(this->GetType() != cmTarget::STATIC_LIBRARY && - this->GetType() != cmTarget::SHARED_LIBRARY && - this->GetType() != cmTarget::MODULE_LIBRARY && - this->GetType() != cmTarget::EXECUTABLE) - { - outPrefix = ""; - outBase = this->GetName(); - outSuffix = ""; - return; - } - - // Return an empty name for the import library if this platform - // does not support import libraries. - if(implib && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) - { - outPrefix = ""; - outBase = ""; - outSuffix = ""; - return; - } - - // The implib option is only allowed for shared libraries, module - // libraries, and executables. - if(this->GetType() != cmTarget::SHARED_LIBRARY && - this->GetType() != cmTarget::MODULE_LIBRARY && - this->GetType() != cmTarget::EXECUTABLE) - { - implib = false; - } - - // Compute the full name for main target types. - const char* targetPrefix = (implib - ? this->GetProperty("IMPORT_PREFIX") - : this->GetProperty("PREFIX")); - const char* targetSuffix = (implib - ? this->GetProperty("IMPORT_SUFFIX") - : this->GetProperty("SUFFIX")); - const char* configPostfix = 0; - if(!config.empty()) - { - std::string configProp = cmSystemTools::UpperCase(config); - configProp += "_POSTFIX"; - configPostfix = this->GetProperty(configProp); - // Mac application bundles and frameworks have no postfix. - if(configPostfix && - (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) - { - configPostfix = 0; - } - } - const char* prefixVar = this->GetPrefixVariableInternal(implib); - const char* suffixVar = this->GetSuffixVariableInternal(implib); - - // Check for language-specific default prefix and suffix. - std::string ll = this->GetLinkerLanguage(config); - if(!ll.empty()) - { - if(!targetSuffix && suffixVar && *suffixVar) - { - std::string langSuff = suffixVar + std::string("_") + ll; - targetSuffix = this->Makefile->GetDefinition(langSuff); - } - if(!targetPrefix && prefixVar && *prefixVar) - { - std::string langPrefix = prefixVar + std::string("_") + ll; - targetPrefix = this->Makefile->GetDefinition(langPrefix); - } - } - - // if there is no prefix on the target use the cmake definition - if(!targetPrefix && prefixVar) - { - targetPrefix = this->Makefile->GetSafeDefinition(prefixVar); - } - // if there is no suffix on the target use the cmake definition - if(!targetSuffix && suffixVar) - { - targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); - } - - // frameworks have directory prefix but no suffix - std::string fw_prefix; - if(this->IsFrameworkOnApple()) - { - fw_prefix = this->GetOutputName(config, false); - fw_prefix += ".framework/"; - targetPrefix = fw_prefix.c_str(); - targetSuffix = 0; - } - - if(this->IsCFBundleOnApple()) - { - fw_prefix = this->GetCFBundleDirectory(config, false); - fw_prefix += "/"; - targetPrefix = fw_prefix.c_str(); - targetSuffix = 0; - } - - // Begin the final name with the prefix. - outPrefix = targetPrefix?targetPrefix:""; - - // Append the target name or property-specified name. - outBase += this->GetOutputName(config, implib); - - // Append the per-configuration postfix. - outBase += configPostfix?configPostfix:""; - - // Name shared libraries with their version number on some platforms. - if(const char* soversion = this->GetProperty("SOVERSION")) - { - if(this->GetType() == cmTarget::SHARED_LIBRARY && !implib && - this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) - { - outBase += "-"; - outBase += soversion; - } - } - - // Append the suffix. - outSuffix = targetSuffix?targetSuffix:""; -} - -//---------------------------------------------------------------------------- -void cmTarget::GetLibraryNames(std::string& name, - std::string& soName, - std::string& realName, - std::string& impName, - std::string& pdbName, - const std::string& config) const -{ - // This should not be called for imported targets. - // TODO: Split cmTarget into a class hierarchy to get compile-time - // enforcement of the limited imported target API. - if(this->IsImported()) - { - std::string msg = "GetLibraryNames called on imported target: "; - msg += this->GetName(); - this->Makefile->IssueMessage(cmake::INTERNAL_ERROR, - msg); - return; - } - - assert(this->GetType() != INTERFACE_LIBRARY); - - // Check for library version properties. - const char* version = this->GetProperty("VERSION"); - const char* soversion = this->GetProperty("SOVERSION"); - if(!this->HasSOName(config) || - this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") || - this->IsFrameworkOnApple()) - { - // Versioning is supported only for shared libraries and modules, - // and then only when the platform supports an soname flag. - version = 0; - soversion = 0; - } - if(version && !soversion) - { - // The soversion must be set if the library version is set. Use - // the library version as the soversion. - soversion = version; - } - if(!version && soversion) - { - // Use the soversion as the library version. - version = soversion; - } - - // Get the components of the library name. - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - // The library name. - name = prefix+base+suffix; - - if(this->IsFrameworkOnApple()) - { - realName = prefix; - realName += "Versions/"; - realName += this->GetFrameworkVersion(); - realName += "/"; - realName += base; - soName = realName; - } - else - { - // The library's soname. - this->ComputeVersionedName(soName, prefix, base, suffix, - name, soversion); - // The library's real name on disk. - this->ComputeVersionedName(realName, prefix, base, suffix, - name, version); - } - - // The import library name. - if(this->GetType() == cmTarget::SHARED_LIBRARY || - this->GetType() == cmTarget::MODULE_LIBRARY) - { - impName = this->GetFullNameInternal(config, true); - } - else - { - impName = ""; - } - - // The program database file name. - pdbName = this->GetPDBName(config); -} - -//---------------------------------------------------------------------------- void cmTarget::ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, @@ -4150,68 +2716,6 @@ void cmTarget::ComputeVersionedName(std::string& vName, } //---------------------------------------------------------------------------- -void cmTarget::GetExecutableNames(std::string& name, - std::string& realName, - std::string& impName, - std::string& pdbName, - const std::string& config) const -{ - // This should not be called for imported targets. - // TODO: Split cmTarget into a class hierarchy to get compile-time - // enforcement of the limited imported target API. - if(this->IsImported()) - { - std::string msg = - "GetExecutableNames called on imported target: "; - msg += this->GetName(); - this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg); - } - - // This versioning is supported only for executables and then only - // when the platform supports symbolic links. -#if defined(_WIN32) && !defined(__CYGWIN__) - const char* version = 0; -#else - // Check for executable version properties. - const char* version = this->GetProperty("VERSION"); - if(this->GetType() != cmTarget::EXECUTABLE || this->Makefile->IsOn("XCODE")) - { - version = 0; - } -#endif - - // Get the components of the executable name. - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - // The executable name. - name = prefix+base+suffix; - - // The executable's real name on disk. -#if defined(__CYGWIN__) - realName = prefix+base; -#else - realName = name; -#endif - if(version) - { - realName += "-"; - realName += version; - } -#if defined(__CYGWIN__) - realName += suffix; -#endif - - // The import library name. - impName = this->GetFullNameInternal(config, true); - - // The program database file name. - pdbName = this->GetPDBName(config); -} - -//---------------------------------------------------------------------------- bool cmTarget::HasImplibGNUtoMS() const { return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS"); @@ -4250,21 +2754,6 @@ void cmTarget::SetPropertyDefault(const std::string& property, } //---------------------------------------------------------------------------- -bool cmTarget::HaveBuildTreeRPATH(const std::string& config) const -{ - if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) - { - return false; - } - if(LinkImplementationLibraries const* impl = - this->GetLinkImplementationLibraries(config)) - { - return !impl->Libraries.empty(); - } - return false; -} - -//---------------------------------------------------------------------------- bool cmTarget::HaveInstallTreeRPATH() const { const char* install_rpath = this->GetProperty("INSTALL_RPATH"); @@ -4273,137 +2762,6 @@ bool cmTarget::HaveInstallTreeRPATH() const } //---------------------------------------------------------------------------- -bool cmTarget::NeedRelinkBeforeInstall(const std::string& config) const -{ - // Only executables and shared libraries can have an rpath and may - // need relinking. - if(this->TargetTypeValue != cmTarget::EXECUTABLE && - this->TargetTypeValue != cmTarget::SHARED_LIBRARY && - this->TargetTypeValue != cmTarget::MODULE_LIBRARY) - { - return false; - } - - // If there is no install location this target will not be installed - // and therefore does not need relinking. - if(!this->GetHaveInstallRule()) - { - return false; - } - - // If skipping all rpaths completely then no relinking is needed. - if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) - { - return false; - } - - // If building with the install-tree rpath no relinking is needed. - if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) - { - return false; - } - - // If chrpath is going to be used no relinking is needed. - if(this->IsChrpathUsed(config)) - { - return false; - } - - // Check for rpath support on this platform. - std::string ll = this->GetLinkerLanguage(config); - if(!ll.empty()) - { - std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - flagVar += ll; - flagVar += "_FLAG"; - if(!this->Makefile->IsSet(flagVar)) - { - // There is no rpath support on this platform so nothing needs - // relinking. - return false; - } - } - else - { - // No linker language is known. This error will be reported by - // other code. - return false; - } - - // If either a build or install tree rpath is set then the rpath - // will likely change between the build tree and install tree and - // this target must be relinked. - return this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(); -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForBuildTree( - const std::string& config) const -{ - // If building directly for installation then the build tree install_name - // is the same as the install tree. - if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) - { - return GetInstallNameDirForInstallTree(); - } - - // Use the build tree directory for the target. - if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") && - !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) - { - std::string dir; - bool macosx_rpath = this->MacOSXRpathInstallNameDirDefault(); - if(macosx_rpath) - { - dir = "@rpath"; - } - else - { - dir = this->GetDirectory(config); - } - dir += "/"; - return dir; - } - else - { - return ""; - } -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForInstallTree() const -{ - if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) - { - std::string dir; - const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); - - if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) - { - if(install_name_dir && *install_name_dir) - { - dir = install_name_dir; - dir += "/"; - } - } - if(!install_name_dir) - { - if(this->MacOSXRpathInstallNameDirDefault()) - { - dir = "@rpath/"; - } - } - return dir; - } - else - { - return ""; - } -} - -//---------------------------------------------------------------------------- const char* cmTarget::GetOutputTargetType(bool implib) const { switch(this->GetType()) @@ -4492,7 +2850,10 @@ bool cmTarget::ComputeOutputDir(const std::string& config, if(const char* config_outdir = this->GetProperty(configProp)) { // Use the user-specified per-configuration output directory. - out = config_outdir; + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(config_outdir); + out = cge->Evaluate(this->Makefile, config); // Skip per-configuration subdirectory. conf = ""; @@ -4500,7 +2861,17 @@ bool cmTarget::ComputeOutputDir(const std::string& config, else if(const char* outdir = this->GetProperty(propertyName)) { // Use the user-specified output directory. - out = outdir; + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(outdir); + out = cge->Evaluate(this->Makefile, config); + + // Skip per-configuration subdirectory if the value contained a + // generator expression. + if (out != outdir) + { + conf = ""; + } } else if(this->GetType() == cmTarget::EXECUTABLE) { @@ -4611,44 +2982,6 @@ bool cmTarget::UsesDefaultOutputDir(const std::string& config, } //---------------------------------------------------------------------------- -std::string cmTarget::GetOutputName(const std::string& config, - bool implib) const -{ - std::vector<std::string> props; - std::string type = this->GetOutputTargetType(implib); - std::string configUpper = cmSystemTools::UpperCase(config); - if(!type.empty() && !configUpper.empty()) - { - // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG> - props.push_back(type + "_OUTPUT_NAME_" + configUpper); - } - if(!type.empty()) - { - // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME - props.push_back(type + "_OUTPUT_NAME"); - } - if(!configUpper.empty()) - { - // OUTPUT_NAME_<CONFIG> - props.push_back("OUTPUT_NAME_" + configUpper); - // <CONFIG>_OUTPUT_NAME - props.push_back(configUpper + "_OUTPUT_NAME"); - } - // OUTPUT_NAME - props.push_back("OUTPUT_NAME"); - - for(std::vector<std::string>::const_iterator i = props.begin(); - i != props.end(); ++i) - { - if(const char* outName = this->GetProperty(*i)) - { - return outName; - } - } - return this->GetName(); -} - -//---------------------------------------------------------------------------- std::string cmTarget::GetFrameworkVersion() const { assert(this->GetType() != INTERFACE_LIBRARY); @@ -4701,500 +3034,6 @@ bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) const } //---------------------------------------------------------------------------- -template<typename PropertyType> -PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop); - -//---------------------------------------------------------------------------- -template<> -bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop) -{ - return tgt->GetPropertyAsBool(prop); -} - -//---------------------------------------------------------------------------- -template<> -const char *getTypedProperty<const char *>(cmTarget const* tgt, - const std::string& prop) -{ - return tgt->GetProperty(prop); -} - -enum CompatibleType -{ - BoolType, - StringType, - NumberMinType, - NumberMaxType -}; - -//---------------------------------------------------------------------------- -template<typename PropertyType> -std::pair<bool, PropertyType> consistentProperty(PropertyType lhs, - PropertyType rhs, - CompatibleType t); - -//---------------------------------------------------------------------------- -template<> -std::pair<bool, bool> consistentProperty(bool lhs, bool rhs, CompatibleType) -{ - return std::make_pair(lhs == rhs, lhs); -} - -//---------------------------------------------------------------------------- -std::pair<bool, const char*> consistentStringProperty(const char *lhs, - const char *rhs) -{ - const bool b = strcmp(lhs, rhs) == 0; - return std::make_pair(b, b ? lhs : 0); -} - -//---------------------------------------------------------------------------- -std::pair<bool, const char*> consistentNumberProperty(const char *lhs, - const char *rhs, - CompatibleType t) -{ - char *pEnd; - - const char* const null_ptr = 0; - - long lnum = strtol(lhs, &pEnd, 0); - if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) - { - return std::pair<bool, const char*>(false, null_ptr); - } - - long rnum = strtol(rhs, &pEnd, 0); - if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) - { - return std::pair<bool, const char*>(false, null_ptr); - } - - if (t == NumberMaxType) - { - return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs); - } - else - { - return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs); - } -} - -//---------------------------------------------------------------------------- -template<> -std::pair<bool, const char*> consistentProperty(const char *lhs, - const char *rhs, - CompatibleType t) -{ - if (!lhs && !rhs) - { - return std::make_pair(true, lhs); - } - if (!lhs) - { - return std::make_pair(true, rhs); - } - if (!rhs) - { - return std::make_pair(true, lhs); - } - - const char* const null_ptr = 0; - - switch(t) - { - case BoolType: - assert(0 && "consistentProperty for strings called with BoolType"); - return std::pair<bool, const char*>(false, null_ptr); - case StringType: - return consistentStringProperty(lhs, rhs); - case NumberMinType: - case NumberMaxType: - return consistentNumberProperty(lhs, rhs, t); - } - assert(0 && "Unreachable!"); - return std::pair<bool, const char*>(false, null_ptr); -} - -template<typename PropertyType> -PropertyType impliedValue(PropertyType); -template<> -bool impliedValue<bool>(bool) -{ - return false; -} -template<> -const char* impliedValue<const char*>(const char*) -{ - return ""; -} - - -template<typename PropertyType> -std::string valueAsString(PropertyType); -template<> -std::string valueAsString<bool>(bool value) -{ - return value ? "TRUE" : "FALSE"; -} -template<> -std::string valueAsString<const char*>(const char* value) -{ - return value ? value : "(unset)"; -} - -//---------------------------------------------------------------------------- -void -cmTarget::ReportPropertyOrigin(const std::string &p, - const std::string &result, - const std::string &report, - const std::string &compatibilityType) const -{ - std::vector<std::string> debugProperties; - const char *debugProp = - this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); - if (debugProp) - { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); - } - - bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] - && std::find(debugProperties.begin(), - debugProperties.end(), - p) - != debugProperties.end(); - - if (this->Makefile->IsGeneratingBuildSystem()) - { - this->DebugCompatiblePropertiesDone[p] = true; - } - if (!debugOrigin) - { - return; - } - - std::string areport = compatibilityType; - areport += std::string(" of property \"") + p + "\" for target \""; - areport += std::string(this->GetName()); - areport += "\" (result: \""; - areport += result; - areport += "\"):\n" + report; - - this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport); -} - -//---------------------------------------------------------------------------- -std::string compatibilityType(CompatibleType t) -{ - switch(t) - { - case BoolType: - return "Boolean compatibility"; - case StringType: - return "String compatibility"; - case NumberMaxType: - return "Numeric maximum compatibility"; - case NumberMinType: - return "Numeric minimum compatibility"; - } - assert(0 && "Unreachable!"); - return ""; -} - -//---------------------------------------------------------------------------- -std::string compatibilityAgree(CompatibleType t, bool dominant) -{ - switch(t) - { - case BoolType: - case StringType: - return dominant ? "(Disagree)\n" : "(Agree)\n"; - case NumberMaxType: - case NumberMinType: - return dominant ? "(Dominant)\n" : "(Ignored)\n"; - } - assert(0 && "Unreachable!"); - return ""; -} - -//---------------------------------------------------------------------------- -template<typename PropertyType> -PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, - const std::string &p, - const std::string& config, - const char *defaultValue, - CompatibleType t, - PropertyType *) -{ - PropertyType propContent = getTypedProperty<PropertyType>(tgt, p); - const bool explicitlySet = tgt->GetProperties() - .find(p) - != tgt->GetProperties().end(); - const bool impliedByUse = - tgt->IsNullImpliedByLinkLibraries(p); - assert((impliedByUse ^ explicitlySet) - || (!impliedByUse && !explicitlySet)); - - std::vector<cmTarget const*> const& deps = - tgt->GetLinkImplementationClosure(config); - - if(deps.empty()) - { - return propContent; - } - bool propInitialized = explicitlySet; - - std::string report = " * Target \""; - report += tgt->GetName(); - if (explicitlySet) - { - report += "\" has property content \""; - report += valueAsString<PropertyType>(propContent); - report += "\"\n"; - } - else if (impliedByUse) - { - report += "\" property is implied by use.\n"; - } - else - { - report += "\" property not set.\n"; - } - - std::string interfaceProperty = "INTERFACE_" + p; - for(std::vector<cmTarget const*>::const_iterator li = - deps.begin(); - li != deps.end(); ++li) - { - // An error should be reported if one dependency - // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other - // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the - // target itself has a POSITION_INDEPENDENT_CODE which disagrees - // with a dependency. - - cmTarget const* theTarget = *li; - - const bool ifaceIsSet = theTarget->GetProperties() - .find(interfaceProperty) - != theTarget->GetProperties().end(); - PropertyType ifacePropContent = - getTypedProperty<PropertyType>(theTarget, - interfaceProperty); - - std::string reportEntry; - if (ifaceIsSet) - { - reportEntry += " * Target \""; - reportEntry += theTarget->GetName(); - reportEntry += "\" property value \""; - reportEntry += valueAsString<PropertyType>(ifacePropContent); - reportEntry += "\" "; - } - - if (explicitlySet) - { - if (ifaceIsSet) - { - std::pair<bool, PropertyType> consistent = - consistentProperty(propContent, - ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) - { - std::ostringstream e; - e << "Property " << p << " on target \"" - << tgt->GetName() << "\" does\nnot match the " - "INTERFACE_" << p << " property requirement\nof " - "dependency \"" << theTarget->GetName() << "\".\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } - else - { - propContent = consistent.second; - continue; - } - } - else - { - // Explicitly set on target and not set in iface. Can't disagree. - continue; - } - } - else if (impliedByUse) - { - propContent = impliedValue<PropertyType>(propContent); - - if (ifaceIsSet) - { - std::pair<bool, PropertyType> consistent = - consistentProperty(propContent, - ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) - { - std::ostringstream e; - e << "Property " << p << " on target \"" - << tgt->GetName() << "\" is\nimplied to be " << defaultValue - << " because it was used to determine the link libraries\n" - "already. The INTERFACE_" << p << " property on\ndependency \"" - << theTarget->GetName() << "\" is in conflict.\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } - else - { - propContent = consistent.second; - continue; - } - } - else - { - // Implicitly set on target and not set in iface. Can't disagree. - continue; - } - } - else - { - if (ifaceIsSet) - { - if (propInitialized) - { - std::pair<bool, PropertyType> consistent = - consistentProperty(propContent, - ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) - { - std::ostringstream e; - e << "The INTERFACE_" << p << " property of \"" - << theTarget->GetName() << "\" does\nnot agree with the value " - "of " << p << " already determined\nfor \"" - << tgt->GetName() << "\".\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } - else - { - propContent = consistent.second; - continue; - } - } - else - { - report += reportEntry + "(Interface set)\n"; - propContent = ifacePropContent; - propInitialized = true; - } - } - else - { - // Not set. Nothing to agree on. - continue; - } - } - } - - tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent), - report, compatibilityType(t)); - return propContent; -} - -//---------------------------------------------------------------------------- -bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE", - BoolType, 0); -} - -//---------------------------------------------------------------------------- -const char * cmTarget::GetLinkInterfaceDependentStringProperty( - const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<const char *>(this, - p, - config, - "empty", - StringType, 0); -} - -//---------------------------------------------------------------------------- -const char * cmTarget::GetLinkInterfaceDependentNumberMinProperty( - const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<const char *>(this, - p, - config, - "empty", - NumberMinType, 0); -} - -//---------------------------------------------------------------------------- -const char * cmTarget::GetLinkInterfaceDependentNumberMaxProperty( - const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<const char *>(this, - p, - config, - "empty", - NumberMaxType, 0); -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0; -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0; -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentNumberMinProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0; -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0; -} - -//---------------------------------------------------------------------------- void cmTarget::GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const { @@ -5236,117 +3075,6 @@ cmTarget::GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const } //---------------------------------------------------------------------------- -void cmTarget::GetLanguages(std::set<std::string>& languages, - const std::string& config) const -{ - std::vector<cmSourceFile*> sourceFiles; - this->GetSourceFiles(sourceFiles, config); - for(std::vector<cmSourceFile*>::const_iterator - i = sourceFiles.begin(); i != sourceFiles.end(); ++i) - { - const std::string& lang = (*i)->GetLanguage(); - if(!lang.empty()) - { - languages.insert(lang); - } - } - - std::vector<cmTarget*> objectLibraries; - std::vector<cmSourceFile const*> externalObjects; - if (this->Makefile->GetGeneratorTargets().empty()) - { - this->GetObjectLibrariesCMP0026(objectLibraries); - } - else - { - cmGeneratorTarget* gt = this->Makefile->GetGlobalGenerator() - ->GetGeneratorTarget(this); - gt->GetExternalObjects(externalObjects, config); - for(std::vector<cmSourceFile const*>::const_iterator - i = externalObjects.begin(); i != externalObjects.end(); ++i) - { - std::string objLib = (*i)->GetObjectLibrary(); - if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib)) - { - objectLibraries.push_back(tgt); - } - } - } - for(std::vector<cmTarget*>::const_iterator - i = objectLibraries.begin(); i != objectLibraries.end(); ++i) - { - (*i)->GetLanguages(languages, config); - } -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsChrpathUsed(const std::string& config) const -{ - // Only certain target types have an rpath. - if(!(this->GetType() == cmTarget::SHARED_LIBRARY || - this->GetType() == cmTarget::MODULE_LIBRARY || - this->GetType() == cmTarget::EXECUTABLE)) - { - return false; - } - - // If the target will not be installed we do not need to change its - // rpath. - if(!this->GetHaveInstallRule()) - { - return false; - } - - // Skip chrpath if skipping rpath altogether. - if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) - { - return false; - } - - // Skip chrpath if it does not need to be changed at install time. - if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) - { - return false; - } - - // Allow the user to disable builtin chrpath explicitly. - if(this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH")) - { - return false; - } - - if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) - { - return true; - } - -#if defined(CMAKE_USE_ELF_PARSER) - // Enable if the rpath flag uses a separator and the target uses ELF - // binaries. - std::string ll = this->GetLinkerLanguage(config); - if(!ll.empty()) - { - std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - sepVar += ll; - sepVar += "_FLAG_SEP"; - const char* sep = this->Makefile->GetDefinition(sepVar); - if(sep && *sep) - { - // TODO: Add ELF check to ABI detection and get rid of - // CMAKE_EXECUTABLE_FORMAT. - if(const char* fmt = - this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) - { - return strcmp(fmt, "ELF") == 0; - } - } - } -#endif - static_cast<void>(config); - return false; -} - -//---------------------------------------------------------------------------- cmTarget::ImportInfo const* cmTarget::GetImportInfo(const std::string& config) const { @@ -5696,478 +3424,11 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } //---------------------------------------------------------------------------- -cmTarget::LinkInterface const* cmTarget::GetLinkInterface( - const std::string& config, - cmTarget const* head) const -{ - // Imported targets have their own link interface. - if(this->IsImported()) - { - return this->GetImportLinkInterface(config, head, false); - } - - // Link interfaces are not supported for executables that do not - // export symbols. - if(this->GetType() == cmTarget::EXECUTABLE && - !this->IsExecutableWithExports()) - { - return 0; - } - - // Lookup any existing link interface for this configuration. - std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::HeadToLinkInterfaceMap& hm = - this->Internal->LinkInterfaceMap[CONFIG]; - - // If the link interface does not depend on the head target - // then return the one we computed first. - if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) - { - return &hm.begin()->second; - } - - cmTargetInternals::OptionalLinkInterface& iface = hm[head]; - if(!iface.LibrariesDone) - { - iface.LibrariesDone = true; - this->Internal->ComputeLinkInterfaceLibraries( - this, config, iface, head, false); - } - if(!iface.AllDone) - { - iface.AllDone = true; - if(iface.Exists) - { - this->Internal->ComputeLinkInterface(this, config, iface, head); - } - } - - return iface.Exists? &iface : 0; -} - -//---------------------------------------------------------------------------- -cmTarget::LinkInterfaceLibraries const* -cmTarget::GetLinkInterfaceLibraries(const std::string& config, - cmTarget const* head, - bool usage_requirements_only) const -{ - // Imported targets have their own link interface. - if(this->IsImported()) - { - return this->GetImportLinkInterface(config, head, usage_requirements_only); - } - - // Link interfaces are not supported for executables that do not - // export symbols. - if(this->GetType() == cmTarget::EXECUTABLE && - !this->IsExecutableWithExports()) - { - return 0; - } - - // Lookup any existing link interface for this configuration. - std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::HeadToLinkInterfaceMap& hm = - (usage_requirements_only ? - this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : - this->Internal->LinkInterfaceMap[CONFIG]); - - // If the link interface does not depend on the head target - // then return the one we computed first. - if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) - { - return &hm.begin()->second; - } - - cmTargetInternals::OptionalLinkInterface& iface = hm[head]; - if(!iface.LibrariesDone) - { - iface.LibrariesDone = true; - this->Internal->ComputeLinkInterfaceLibraries( - this, config, iface, head, usage_requirements_only); - } - - return iface.Exists? &iface : 0; -} - -//---------------------------------------------------------------------------- -cmTarget::LinkInterface const* -cmTarget::GetImportLinkInterface(const std::string& config, - cmTarget const* headTarget, - bool usage_requirements_only) const -{ - cmTarget::ImportInfo const* info = this->GetImportInfo(config); - if(!info) - { - return 0; - } - - std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::HeadToLinkInterfaceMap& hm = - (usage_requirements_only ? - this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : - this->Internal->LinkInterfaceMap[CONFIG]); - - // If the link interface does not depend on the head target - // then return the one we computed first. - if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) - { - return &hm.begin()->second; - } - - cmTargetInternals::OptionalLinkInterface& iface = hm[headTarget]; - if(!iface.AllDone) - { - iface.AllDone = true; - iface.Multiplicity = info->Multiplicity; - cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); - this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, - headTarget, usage_requirements_only, - iface.Libraries, - iface.HadHeadSensitiveCondition); - std::vector<std::string> deps; - cmSystemTools::ExpandListArgument(info->SharedDeps, deps); - this->LookupLinkItems(deps, iface.SharedDeps); - } - - return &iface; -} - -//---------------------------------------------------------------------------- -void processILibs(const std::string& config, - cmTarget const* headTarget, - cmLinkItem const& item, - std::vector<cmTarget const*>& tgts, - std::set<cmTarget const*>& emitted) -{ - if (item.Target && emitted.insert(item.Target).second) - { - tgts.push_back(item.Target); - if(cmTarget::LinkInterfaceLibraries const* iface = - item.Target->GetLinkInterfaceLibraries(config, headTarget, true)) - { - for(std::vector<cmLinkItem>::const_iterator - it = iface->Libraries.begin(); - it != iface->Libraries.end(); ++it) - { - processILibs(config, headTarget, *it, tgts, emitted); - } - } - } -} - -//---------------------------------------------------------------------------- -std::vector<cmTarget const*> const& -cmTarget::GetLinkImplementationClosure(const std::string& config) const -{ - cmTargetInternals::LinkImplClosure& tgts = - this->Internal->LinkImplClosureMap[config]; - if(!tgts.Done) - { - tgts.Done = true; - std::set<cmTarget const*> emitted; - - cmTarget::LinkImplementationLibraries const* impl - = this->GetLinkImplementationLibraries(config); - - for(std::vector<cmLinkImplItem>::const_iterator - it = impl->Libraries.begin(); - it != impl->Libraries.end(); ++it) - { - processILibs(config, this, *it, tgts , emitted); - } - } - return tgts; -} - -//---------------------------------------------------------------------------- -cmTarget::CompatibleInterfaces const& -cmTarget::GetCompatibleInterfaces(std::string const& config) const -{ - cmTargetInternals::CompatibleInterfaces& compat = - this->Internal->CompatibleInterfacesMap[config]; - if(!compat.Done) - { - compat.Done = true; - compat.PropsBool.insert("POSITION_INDEPENDENT_CODE"); - compat.PropsString.insert("AUTOUIC_OPTIONS"); - std::vector<cmTarget const*> const& deps = - this->GetLinkImplementationClosure(config); - for(std::vector<cmTarget const*>::const_iterator li = deps.begin(); - li != deps.end(); ++li) - { -#define CM_READ_COMPATIBLE_INTERFACE(X, x) \ - if(const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) \ - { \ - std::vector<std::string> props; \ - cmSystemTools::ExpandListArgument(prop, props); \ - compat.Props##x.insert(props.begin(), props.end()); \ - } - CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) - CM_READ_COMPATIBLE_INTERFACE(STRING, String) - CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin) - CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax) -#undef CM_READ_COMPATIBLE_INTERFACE - } - } - return compat; -} - -//---------------------------------------------------------------------------- -void -cmTargetInternals::ComputeLinkInterfaceLibraries( - cmTarget const* thisTarget, - const std::string& config, - OptionalLinkInterface& iface, - cmTarget const* headTarget, - bool usage_requirements_only) -{ - // Construct the property name suffix for this configuration. - std::string suffix = "_"; - if(!config.empty()) - { - suffix += cmSystemTools::UpperCase(config); - } - else - { - suffix += "NOCONFIG"; - } - - // An explicit list of interface libraries may be set for shared - // libraries and executables that export symbols. - const char* explicitLibraries = 0; - std::string linkIfaceProp; - if(thisTarget->PolicyStatusCMP0022 != cmPolicies::OLD && - thisTarget->PolicyStatusCMP0022 != cmPolicies::WARN) - { - // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. - linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; - explicitLibraries = thisTarget->GetProperty(linkIfaceProp); - } - else if(thisTarget->GetType() == cmTarget::SHARED_LIBRARY || - thisTarget->IsExecutableWithExports()) - { - // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a - // shared lib or executable. - - // Lookup the per-configuration property. - linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; - linkIfaceProp += suffix; - explicitLibraries = thisTarget->GetProperty(linkIfaceProp); - - // If not set, try the generic property. - if(!explicitLibraries) - { - linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; - explicitLibraries = thisTarget->GetProperty(linkIfaceProp); - } - } - - if(explicitLibraries && - thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN && - !this->PolicyWarnedCMP0022) - { - // Compare the explicitly set old link interface properties to the - // preferred new link interface property one and warn if different. - const char* newExplicitLibraries = - thisTarget->GetProperty("INTERFACE_LINK_LIBRARIES"); - if (newExplicitLibraries - && strcmp(newExplicitLibraries, explicitLibraries) != 0) - { - std::ostringstream w; - w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n" - "Target \"" << thisTarget->GetName() << "\" has an " - "INTERFACE_LINK_LIBRARIES property which differs from its " << - linkIfaceProp << " properties." - "\n" - "INTERFACE_LINK_LIBRARIES:\n" - " " << newExplicitLibraries << "\n" << - linkIfaceProp << ":\n" - " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n"; - thisTarget->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); - this->PolicyWarnedCMP0022 = true; - } - } - - // There is no implicit link interface for executables or modules - // so if none was explicitly set then there is no link interface. - if(!explicitLibraries && - (thisTarget->GetType() == cmTarget::EXECUTABLE || - (thisTarget->GetType() == cmTarget::MODULE_LIBRARY))) - { - return; - } - iface.Exists = true; - iface.ExplicitLibraries = explicitLibraries; - - if(explicitLibraries) - { - // The interface libraries have been explicitly set. - thisTarget->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, - headTarget, usage_requirements_only, - iface.Libraries, - iface.HadHeadSensitiveCondition); - } - else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN - || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) - // If CMP0022 is NEW then the plain tll signature sets the - // INTERFACE_LINK_LIBRARIES, so if we get here then the project - // cleared the property explicitly and we should not fall back - // to the link implementation. - { - // The link implementation is the default link interface. - cmTarget::LinkImplementationLibraries const* impl = - thisTarget->GetLinkImplementationLibrariesInternal(config, headTarget); - iface.Libraries.insert(iface.Libraries.end(), - impl->Libraries.begin(), impl->Libraries.end()); - if(thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN && - !this->PolicyWarnedCMP0022 && !usage_requirements_only) - { - // Compare the link implementation fallback link interface to the - // preferred new link interface property and warn if different. - std::vector<cmLinkItem> ifaceLibs; - static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; - if(const char* newExplicitLibraries = thisTarget->GetProperty(newProp)) - { - bool hadHeadSensitiveConditionDummy = false; - thisTarget->ExpandLinkItems(newProp, newExplicitLibraries, config, - headTarget, usage_requirements_only, - ifaceLibs, hadHeadSensitiveConditionDummy); - } - if (ifaceLibs != iface.Libraries) - { - std::string oldLibraries = cmJoin(impl->Libraries, ";"); - std::string newLibraries = cmJoin(ifaceLibs, ";"); - if(oldLibraries.empty()) - { oldLibraries = "(empty)"; } - if(newLibraries.empty()) - { newLibraries = "(empty)"; } - - std::ostringstream w; - w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n" - "Target \"" << thisTarget->GetName() << "\" has an " - "INTERFACE_LINK_LIBRARIES property. " - "This should be preferred as the source of the link interface " - "for this library but because CMP0022 is not set CMake is " - "ignoring the property and using the link implementation " - "as the link interface instead." - "\n" - "INTERFACE_LINK_LIBRARIES:\n" - " " << newLibraries << "\n" - "Link implementation:\n" - " " << oldLibraries << "\n"; - thisTarget->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); - this->PolicyWarnedCMP0022 = true; - } - } - } -} - -//---------------------------------------------------------------------------- -void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, - const std::string& config, - OptionalLinkInterface& iface, - cmTarget const* headTarget) const -{ - if(iface.ExplicitLibraries) - { - if(thisTarget->GetType() == cmTarget::SHARED_LIBRARY - || thisTarget->GetType() == cmTarget::STATIC_LIBRARY - || thisTarget->GetType() == cmTarget::INTERFACE_LIBRARY) - { - // Shared libraries may have runtime implementation dependencies - // on other shared libraries that are not in the interface. - UNORDERED_SET<std::string> emitted; - for(std::vector<cmLinkItem>::const_iterator - li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) - { - emitted.insert(*li); - } - if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY) - { - cmTarget::LinkImplementation const* impl = - thisTarget->GetLinkImplementation(config); - for(std::vector<cmLinkImplItem>::const_iterator - li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) - { - if(emitted.insert(*li).second) - { - if(li->Target) - { - // This is a runtime dependency on another shared library. - if(li->Target->GetType() == cmTarget::SHARED_LIBRARY) - { - iface.SharedDeps.push_back(*li); - } - } - else - { - // TODO: Recognize shared library file names. Perhaps this - // should be moved to cmComputeLinkInformation, but that creates - // a chicken-and-egg problem since this list is needed for its - // construction. - } - } - } - } - } - } - else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN - || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) - { - // The link implementation is the default link interface. - cmTarget::LinkImplementationLibraries const* - impl = thisTarget->GetLinkImplementationLibrariesInternal(config, - headTarget); - iface.ImplementationIsInterface = true; - iface.WrongConfigLibraries = impl->WrongConfigLibraries; - } - - if(thisTarget->LinkLanguagePropagatesToDependents()) - { - // Targets using this archive need its language runtime libraries. - if(cmTarget::LinkImplementation const* impl = - thisTarget->GetLinkImplementation(config)) - { - iface.Languages = impl->Languages; - } - } - - if(thisTarget->GetType() == cmTarget::STATIC_LIBRARY) - { - // Construct the property name suffix for this configuration. - std::string suffix = "_"; - if(!config.empty()) - { - suffix += cmSystemTools::UpperCase(config); - } - else - { - suffix += "NOCONFIG"; - } - - // How many repetitions are needed if this library has cyclic - // dependencies? - std::string propName = "LINK_INTERFACE_MULTIPLICITY"; - propName += suffix; - if(const char* config_reps = thisTarget->GetProperty(propName)) - { - sscanf(config_reps, "%u", &iface.Multiplicity); - } - else if(const char* reps = - thisTarget->GetProperty("LINK_INTERFACE_MULTIPLICITY")) - { - sscanf(reps, "%u", &iface.Multiplicity); - } - } -} - -//---------------------------------------------------------------------------- void cmTargetInternals::AddInterfaceEntries( cmTarget const* thisTarget, std::string const& config, std::string const& prop, std::vector<TargetPropertyEntry*>& entries) { - if(cmTarget::LinkImplementationLibraries const* impl = + if(cmLinkImplementationLibraries const* impl = thisTarget->GetLinkImplementationLibraries(config)) { for (std::vector<cmLinkImplItem>::const_iterator @@ -6178,7 +3439,7 @@ void cmTargetInternals::AddInterfaceEntries( { std::string genex = "$<TARGET_PROPERTY:" + *it + "," + prop + ">"; - cmGeneratorExpression ge(&it->Backtrace); + cmGeneratorExpression ge(it->Backtrace); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); entries.push_back( @@ -6188,43 +3449,23 @@ void cmTargetInternals::AddInterfaceEntries( } } -//---------------------------------------------------------------------------- -cmTarget::LinkImplementation const* -cmTarget::GetLinkImplementation(const std::string& config) const +cmOptionalLinkImplementation& +cmTarget::GetLinkImplMap(std::string const& config) const { - // There is no link implementation for imported targets. - if(this->IsImported()) - { - return 0; - } - // Populate the link implementation for this configuration. std::string CONFIG = cmSystemTools::UpperCase(config); - cmTargetInternals::OptionalLinkImplementation& - impl = this->Internal->LinkImplMap[CONFIG][this]; - if(!impl.LibrariesDone) - { - impl.LibrariesDone = true; - this->Internal - ->ComputeLinkImplementationLibraries(this, config, impl, this); - } - if(!impl.LanguagesDone) - { - impl.LanguagesDone = true; - this->Internal->ComputeLinkImplementationLanguages(this, config, impl); - } - return &impl; + return Internal->LinkImplMap[CONFIG][this]; } //---------------------------------------------------------------------------- -cmTarget::LinkImplementationLibraries const* +cmLinkImplementationLibraries const* cmTarget::GetLinkImplementationLibraries(const std::string& config) const { return this->GetLinkImplementationLibrariesInternal(config, this); } //---------------------------------------------------------------------------- -cmTarget::LinkImplementationLibraries const* +cmLinkImplementationLibraries const* cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, cmTarget const* head) const { @@ -6246,39 +3487,36 @@ cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, return &hm.begin()->second; } - cmTargetInternals::OptionalLinkImplementation& impl = hm[head]; + cmOptionalLinkImplementation& impl = hm[head]; if(!impl.LibrariesDone) { impl.LibrariesDone = true; - this->Internal - ->ComputeLinkImplementationLibraries(this, config, impl, head); + this->ComputeLinkImplementationLibraries(config, impl, head); } return &impl; } //---------------------------------------------------------------------------- -void -cmTargetInternals::ComputeLinkImplementationLibraries( - cmTarget const* thisTarget, +void cmTarget::ComputeLinkImplementationLibraries( const std::string& config, - OptionalLinkImplementation& impl, + cmOptionalLinkImplementation& impl, cmTarget const* head) const { // Collect libraries directly linked in this configuration. for (std::vector<cmValueWithOrigin>::const_iterator - le = this->LinkImplementationPropertyEntries.begin(), - end = this->LinkImplementationPropertyEntries.end(); + le = this->Internal->LinkImplementationPropertyEntries.begin(), + end = this->Internal->LinkImplementationPropertyEntries.end(); le != end; ++le) { std::vector<std::string> llibs; cmGeneratorExpressionDAGChecker dagChecker( - thisTarget->GetName(), + this->GetName(), "LINK_LIBRARIES", 0, 0); - cmGeneratorExpression ge(&le->Backtrace); + cmGeneratorExpression ge(le->Backtrace); cmsys::auto_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(le->Value); std::string const evaluated = - cge->Evaluate(thisTarget->Makefile, config, false, head, &dagChecker); + cge->Evaluate(this->Makefile, config, false, head, &dagChecker); cmSystemTools::ExpandListArgument(evaluated, llibs); if(cge->GetHadHeadSensitiveCondition()) { @@ -6289,15 +3527,15 @@ cmTargetInternals::ComputeLinkImplementationLibraries( li != llibs.end(); ++li) { // Skip entries that resolve to the target itself or are empty. - std::string name = thisTarget->CheckCMP0004(*li); - if(name == thisTarget->GetName() || name.empty()) + std::string name = this->CheckCMP0004(*li); + if(name == this->GetName() || name.empty()) { - if(name == thisTarget->GetName()) + if(name == this->GetName()) { bool noMessage = false; cmake::MessageType messageType = cmake::FATAL_ERROR; std::ostringstream e; - switch(thisTarget->GetPolicyStatusCMP0038()) + switch(this->GetPolicyStatusCMP0038()) { case cmPolicies::WARN: { @@ -6316,9 +3554,9 @@ cmTargetInternals::ComputeLinkImplementationLibraries( if(!noMessage) { - e << "Target \"" << thisTarget->GetName() << "\" links to itself."; - thisTarget->Makefile->GetCMakeInstance()->IssueMessage( - messageType, e.str(), thisTarget->GetBacktrace()); + e << "Target \"" << this->GetName() << "\" links to itself."; + this->Makefile->GetCMakeInstance()->IssueMessage( + messageType, e.str(), this->GetBacktrace()); if (messageType == cmake::FATAL_ERROR) { return; @@ -6330,7 +3568,7 @@ cmTargetInternals::ComputeLinkImplementationLibraries( // The entry is meant for this configuration. impl.Libraries.push_back( - cmLinkImplItem(name, thisTarget->FindTargetToLink(name), + cmLinkImplItem(name, this->FindTargetToLink(name), le->Backtrace, evaluated != le->Value)); } @@ -6338,51 +3576,35 @@ cmTargetInternals::ComputeLinkImplementationLibraries( for (std::set<std::string>::const_iterator it = seenProps.begin(); it != seenProps.end(); ++it) { - if (!thisTarget->GetProperty(*it)) + if (!this->GetProperty(*it)) { - thisTarget->LinkImplicitNullProperties.insert(*it); + this->LinkImplicitNullProperties.insert(*it); } } - cge->GetMaxLanguageStandard(thisTarget, thisTarget->MaxLanguageStandards); + cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards); } - cmTarget::LinkLibraryType linkType = thisTarget->ComputeLinkType(config); + cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); cmTarget::LinkLibraryVectorType const& oldllibs = - thisTarget->GetOriginalLinkLibraries(); + this->GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin(); li != oldllibs.end(); ++li) { if(li->second != cmTarget::GENERAL && li->second != linkType) { - std::string name = thisTarget->CheckCMP0004(li->first); - if(name == thisTarget->GetName() || name.empty()) + std::string name = this->CheckCMP0004(li->first); + if(name == this->GetName() || name.empty()) { continue; } // Support OLD behavior for CMP0003. impl.WrongConfigLibraries.push_back( - cmLinkItem(name, thisTarget->FindTargetToLink(name))); + cmLinkItem(name, this->FindTargetToLink(name))); } } } //---------------------------------------------------------------------------- -void -cmTargetInternals::ComputeLinkImplementationLanguages( - cmTarget const* thisTarget, - const std::string& config, - OptionalLinkImplementation& impl) const -{ - // This target needs runtime libraries for its source languages. - std::set<std::string> languages; - // Get languages used in our source files. - thisTarget->GetLanguages(languages, config); - // Copy the set of langauges to the link implementation. - impl.Languages.insert(impl.Languages.begin(), - languages.begin(), languages.end()); -} - -//---------------------------------------------------------------------------- cmTarget const* cmTarget::FindTargetToLink(std::string const& name) const { cmTarget const* tgt = this->Makefile->FindTargetToUse(name); @@ -6433,7 +3655,7 @@ std::string cmTarget::CheckCMP0004(std::string const& item) const if(lib != item) { cmake* cm = this->Makefile->GetCMakeInstance(); - switch(this->PolicyStatusCMP0004) + switch(this->GetPolicyStatusCMP0004()) { case cmPolicies::WARN: { @@ -6470,382 +3692,6 @@ std::string cmTarget::CheckCMP0004(std::string const& item) const return lib; } -template<typename PropertyType> -PropertyType getLinkInterfaceDependentProperty(cmTarget const* tgt, - const std::string& prop, - const std::string& config, - CompatibleType, - PropertyType *); - -template<> -bool getLinkInterfaceDependentProperty(cmTarget const* tgt, - const std::string& prop, - const std::string& config, - CompatibleType, bool *) -{ - return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); -} - -template<> -const char * getLinkInterfaceDependentProperty(cmTarget const* tgt, - const std::string& prop, - const std::string& config, - CompatibleType t, - const char **) -{ - switch(t) - { - case BoolType: - assert(0 && "String compatibility check function called for boolean"); - return 0; - case StringType: - return tgt->GetLinkInterfaceDependentStringProperty(prop, config); - case NumberMinType: - return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config); - case NumberMaxType: - return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config); - } - assert(0 && "Unreachable!"); - return 0; -} - -//---------------------------------------------------------------------------- -template<typename PropertyType> -void checkPropertyConsistency(cmTarget const* depender, - cmTarget const* dependee, - const std::string& propName, - std::set<std::string> &emitted, - const std::string& config, - CompatibleType t, - PropertyType *) -{ - const char *prop = dependee->GetProperty(propName); - if (!prop) - { - return; - } - - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - std::string pdir = - dependee->GetMakefile()->GetRequiredDefinition("CMAKE_ROOT"); - pdir += "/Help/prop_tgt/"; - - for(std::vector<std::string>::iterator pi = props.begin(); - pi != props.end(); ++pi) - { - std::string pname = cmSystemTools::HelpFileName(*pi); - std::string pfile = pdir + pname + ".rst"; - if(cmSystemTools::FileExists(pfile.c_str(), true)) - { - std::ostringstream e; - e << "Target \"" << dependee->GetName() << "\" has property \"" - << *pi << "\" listed in its " << propName << " property. " - "This is not allowed. Only user-defined properties may appear " - "listed in the " << propName << " property."; - depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); - return; - } - if(emitted.insert(*pi).second) - { - getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, - t, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - } - } -} - -static std::string intersect(const std::set<std::string> &s1, - const std::set<std::string> &s2) -{ - std::set<std::string> intersect; - std::set_intersection(s1.begin(),s1.end(), - s2.begin(),s2.end(), - std::inserter(intersect,intersect.begin())); - if (!intersect.empty()) - { - return *intersect.begin(); - } - return ""; -} -static std::string intersect(const std::set<std::string> &s1, - const std::set<std::string> &s2, - const std::set<std::string> &s3) -{ - std::string result; - result = intersect(s1, s2); - if (!result.empty()) - return result; - result = intersect(s1, s3); - if (!result.empty()) - return result; - return intersect(s2, s3); -} -static std::string intersect(const std::set<std::string> &s1, - const std::set<std::string> &s2, - const std::set<std::string> &s3, - const std::set<std::string> &s4) -{ - std::string result; - result = intersect(s1, s2); - if (!result.empty()) - return result; - result = intersect(s1, s3); - if (!result.empty()) - return result; - result = intersect(s1, s4); - if (!result.empty()) - return result; - return intersect(s2, s3, s4); -} - -//---------------------------------------------------------------------------- -void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, - const std::string& config) const -{ - const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); - - std::set<std::string> emittedBools; - static std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; - std::set<std::string> emittedStrings; - static std::string strString = "COMPATIBLE_INTERFACE_STRING"; - std::set<std::string> emittedMinNumbers; - static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; - std::set<std::string> emittedMaxNumbers; - static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; - - for(cmComputeLinkInformation::ItemVector::const_iterator li = - deps.begin(); - li != deps.end(); ++li) - { - if (!li->Target) - { - continue; - } - - checkPropertyConsistency<bool>(this, li->Target, - strBool, - emittedBools, config, BoolType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - checkPropertyConsistency<const char *>(this, li->Target, - strString, - emittedStrings, config, - StringType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - checkPropertyConsistency<const char *>(this, li->Target, - strNumMin, - emittedMinNumbers, config, - NumberMinType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - checkPropertyConsistency<const char *>(this, li->Target, - strNumMax, - emittedMaxNumbers, config, - NumberMaxType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - } - - std::string prop = intersect(emittedBools, - emittedStrings, - emittedMinNumbers, - emittedMaxNumbers); - - if (!prop.empty()) - { - // Use a sorted std::vector to keep the error message sorted. - std::vector<std::string> props; - std::set<std::string>::const_iterator i = emittedBools.find(prop); - if (i != emittedBools.end()) - { - props.push_back(strBool); - } - i = emittedStrings.find(prop); - if (i != emittedStrings.end()) - { - props.push_back(strString); - } - i = emittedMinNumbers.find(prop); - if (i != emittedMinNumbers.end()) - { - props.push_back(strNumMin); - } - i = emittedMaxNumbers.find(prop); - if (i != emittedMaxNumbers.end()) - { - props.push_back(strNumMax); - } - std::sort(props.begin(), props.end()); - - std::string propsString = cmJoin(cmRange(props).retreat(1), ", "); - propsString += " and the " + props.back(); - - std::ostringstream e; - e << "Property \"" << prop << "\" appears in both the " - << propsString << - " property in the dependencies of target \"" << this->GetName() << - "\". This is not allowed. A property may only require compatibility " - "in a boolean interpretation, a numeric minimum, a numeric maximum or a " - "string interpretation, but not a mixture."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - } -} - -//---------------------------------------------------------------------------- -cmComputeLinkInformation* -cmTarget::GetLinkInformation(const std::string& config) const -{ - // Lookup any existing information for this configuration. - std::string key(cmSystemTools::UpperCase(config)); - cmTargetLinkInformationMap::iterator - i = this->LinkInformation.find(key); - if(i == this->LinkInformation.end()) - { - // Compute information for this configuration. - cmComputeLinkInformation* info = - new cmComputeLinkInformation(this, config); - if(!info || !info->Compute()) - { - delete info; - info = 0; - } - - // Store the information for this configuration. - cmTargetLinkInformationMap::value_type entry(key, info); - i = this->LinkInformation.insert(entry).first; - - if (info) - { - this->CheckPropertyCompatibility(info, config); - } - } - return i->second; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetFrameworkDirectory(const std::string& config, - bool rootDir) const -{ - std::string fpath; - fpath += this->GetOutputName(config, false); - fpath += ".framework"; - if(!rootDir) - { - fpath += "/Versions/"; - fpath += this->GetFrameworkVersion(); - } - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetCFBundleDirectory(const std::string& config, - bool contentOnly) const -{ - std::string fpath; - fpath += this->GetOutputName(config, false); - fpath += "."; - const char *ext = this->GetProperty("BUNDLE_EXTENSION"); - if (!ext) - { - if (this->IsXCTestOnApple()) - { - ext = "xctest"; - } - else - { - ext = "bundle"; - } - } - fpath += ext; - fpath += "/Contents"; - if(!contentOnly) - fpath += "/MacOS"; - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetAppBundleDirectory(const std::string& config, - bool contentOnly) const -{ - std::string fpath = this->GetFullName(config, false); - fpath += ".app/Contents"; - if(!contentOnly) - fpath += "/MacOS"; - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::BuildMacContentDirectory(const std::string& base, - const std::string& config, - bool contentOnly) const -{ - std::string fpath = base; - if(this->IsAppBundleOnApple()) - { - fpath += this->GetAppBundleDirectory(config, contentOnly); - } - if(this->IsFrameworkOnApple()) - { - fpath += this->GetFrameworkDirectory(config, contentOnly); - } - if(this->IsCFBundleOnApple()) - { - fpath += this->GetCFBundleDirectory(config, contentOnly); - } - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetMacContentDirectory(const std::string& config, - bool implib) const -{ - // Start with the output directory for the target. - std::string fpath = this->GetDirectory(config, implib); - fpath += "/"; - bool contentOnly = true; - if(this->IsFrameworkOnApple()) - { - // additional files with a framework go into the version specific - // directory - contentOnly = false; - } - fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); - return fpath; -} - -//---------------------------------------------------------------------------- -cmTargetLinkInformationMap -::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived() -{ - // Ideally cmTarget instances should never be copied. However until - // we can make a sweep to remove that, this copy constructor avoids - // allowing the resources (LinkInformation) from getting copied. In - // the worst case this will lead to extra cmComputeLinkInformation - // instances. We also enforce in debug mode that the map be emptied - // when copied. - static_cast<void>(r); - assert(r.empty()); -} - -//---------------------------------------------------------------------------- -cmTargetLinkInformationMap::~cmTargetLinkInformationMap() -{ - cmDeleteAll(*this); -} - //---------------------------------------------------------------------------- cmTargetInternalPointer::cmTargetInternalPointer() { @@ -6865,10 +3711,6 @@ cmTargetInternalPointer //---------------------------------------------------------------------------- cmTargetInternalPointer::~cmTargetInternalPointer() { - cmDeleteAll(this->Pointer->IncludeDirectoriesEntries); - cmDeleteAll(this->Pointer->CompileOptionsEntries); - cmDeleteAll(this->Pointer->CompileFeaturesEntries); - cmDeleteAll(this->Pointer->CompileDefinitionsEntries); cmDeleteAll(this->Pointer->SourceEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3eb9e7e..c86ec24 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -16,6 +16,7 @@ #include "cmPropertyMap.h" #include "cmPolicies.h" #include "cmListFileCache.h" +#include "cmLinkItem.h" #include <cmsys/auto_ptr.hxx> #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -52,41 +53,6 @@ class cmTarget; class cmGeneratorTarget; class cmTargetTraceDependencies; -// Basic information about each link item. -class cmLinkItem: public std::string -{ - typedef std::string std_string; -public: - cmLinkItem(): std_string(), Target(0) {} - cmLinkItem(const std_string& n, - cmTarget const* t): std_string(n), Target(t) {} - cmLinkItem(cmLinkItem const& r): std_string(r), Target(r.Target) {} - cmTarget const* Target; -}; -class cmLinkImplItem: public cmLinkItem -{ -public: - cmLinkImplItem(): cmLinkItem(), Backtrace(0), FromGenex(false) {} - cmLinkImplItem(std::string const& n, - cmTarget const* t, - cmListFileBacktrace const& bt, - bool fromGenex): - cmLinkItem(n, t), Backtrace(bt), FromGenex(fromGenex) {} - cmLinkImplItem(cmLinkImplItem const& r): - cmLinkItem(r), Backtrace(r.Backtrace), FromGenex(r.FromGenex) {} - cmListFileBacktrace Backtrace; - bool FromGenex; -}; - -struct cmTargetLinkInformationMap: - public std::map<std::string, cmComputeLinkInformation*> -{ - typedef std::map<std::string, cmComputeLinkInformation*> derived; - cmTargetLinkInformationMap() {} - cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); - ~cmTargetLinkInformationMap(); -}; - class cmTargetInternals; class cmTargetInternalPointer { @@ -144,7 +110,7 @@ public: #define DECLARE_TARGET_POLICY(POLICY) \ cmPolicies::PolicyStatus GetPolicyStatus ## POLICY () const \ - { return this->PolicyStatus ## POLICY; } + { return this->PolicyMap.Get(cmPolicies::POLICY); } CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY) @@ -171,8 +137,6 @@ public: */ void GetSourceFiles(std::vector<cmSourceFile*> &files, const std::string& config) const; - bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const; - /** * Add sources to the target. */ @@ -261,98 +225,19 @@ public: bool GetPropertyAsBool(const std::string& prop) const; void CheckProperty(const std::string& prop, cmMakefile* context) const; - const char* GetFeature(const std::string& feature, - const std::string& config) const; - bool GetFeatureAsBool(const std::string& feature, - const std::string& config) const; - bool IsImported() const {return this->IsImportedTarget;} void GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const; - /** The link interface specifies transitive library dependencies and - other information needed by targets that link to this target. */ - struct LinkInterfaceLibraries - { - // Libraries listed in the interface. - std::vector<cmLinkItem> Libraries; - }; - struct LinkInterface: public LinkInterfaceLibraries - { - // Languages whose runtime libraries must be linked. - std::vector<std::string> Languages; - - // Shared library dependencies needed for linking on some platforms. - std::vector<cmLinkItem> SharedDeps; - - // Number of repetitions of a strongly connected component of two - // or more static libraries. - int Multiplicity; - - // Libraries listed for other configurations. - // Needed only for OLD behavior of CMP0003. - std::vector<cmLinkItem> WrongConfigLibraries; - - bool ImplementationIsInterface; - - LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {} - }; - - /** Get the link interface for the given configuration. Returns 0 - if the target cannot be linked. */ - LinkInterface const* GetLinkInterface(const std::string& config, - cmTarget const* headTarget) const; - LinkInterfaceLibraries const* - GetLinkInterfaceLibraries(const std::string& config, - cmTarget const* headTarget, - bool usage_requirements_only) const; - - std::vector<cmTarget const*> const& - GetLinkImplementationClosure(const std::string& config) const; - - struct CompatibleInterfaces - { - std::set<std::string> PropsBool; - std::set<std::string> PropsString; - std::set<std::string> PropsNumberMax; - std::set<std::string> PropsNumberMin; - }; - CompatibleInterfaces const& - GetCompatibleInterfaces(std::string const& config) const; - - /** The link implementation specifies the direct library - dependencies needed by the object files of the target. */ - struct LinkImplementationLibraries - { - // Libraries linked directly in this configuration. - std::vector<cmLinkImplItem> Libraries; - - // Libraries linked directly in other configurations. - // Needed only for OLD behavior of CMP0003. - std::vector<cmLinkItem> WrongConfigLibraries; - }; - struct LinkImplementation: public LinkImplementationLibraries - { - // Languages whose runtime libraries must be linked. - std::vector<std::string> Languages; - }; - LinkImplementation const* - GetLinkImplementation(const std::string& config) const; - - LinkImplementationLibraries const* + cmLinkImplementationLibraries const* GetLinkImplementationLibraries(const std::string& config) const; - /** Link information from the transitive closure of the link - implementation and the interfaces of its dependencies. */ - struct LinkClosure - { - // The preferred linker language. - std::string LinkerLanguage; + void ComputeLinkImplementationLibraries(const std::string& config, + cmOptionalLinkImplementation& impl, + cmTarget const* head) const; - // Languages whose runtime libraries must be linked. - std::vector<std::string> Languages; - }; - LinkClosure const* GetLinkClosure(const std::string& config) const; + cmOptionalLinkImplementation& + GetLinkImplMap(std::string const& config) const; cmTarget const* FindTargetToLink(std::string const& name) const; @@ -373,20 +258,7 @@ public: pdb output directory is given. */ std::string GetPDBDirectory(const std::string& config) const; - /** Get the directory in which to place the target compiler .pdb file. - If the configuration name is given then the generator will add its - subdirectory for that configuration. Otherwise just the canonical - compiler pdb output directory is given. */ - std::string GetCompilePDBDirectory(const std::string& config = "") const; - - /** Get the location of the target in the build tree for the given - configuration. */ - const char* GetLocation(const std::string& config) const; - - /** Get the location of the target in the build tree with a placeholder - referencing the configuration in the native build system. This - location is suitable for use as the LOCATION target property. */ - const char* GetLocationForBuild() const; + const char* ImportedGetLocation(const std::string& config) const; /** Get the target major and minor version numbers interpreted from the VERSION property. Version 0 is returned if the property is @@ -399,33 +271,6 @@ public: void GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; - ///! Return the preferred linker language for this target - std::string GetLinkerLanguage(const std::string& config = "") const; - - /** Get the full name of the target according to the settings in its - makefile. */ - std::string GetFullName(const std::string& config="", - bool implib = false) const; - void GetFullNameComponents(std::string& prefix, - std::string& base, std::string& suffix, - const std::string& config="", - bool implib = false) const; - - /** Get the name of the pdb file for the target. */ - std::string GetPDBName(const std::string& config) const; - - /** Get the name of the compiler pdb file for the target. */ - std::string GetCompilePDBName(const std::string& config="") const; - - /** Get the path for the MSVC /Fd option for this target. */ - std::string GetCompilePDBPath(const std::string& config="") const; - - /** Whether this library has soname enabled and platform supports it. */ - bool HasSOName(const std::string& config) const; - - /** Get the soname of the target. Allowed only for a shared library. */ - std::string GetSOName(const std::string& config) const; - /** Whether this library has \@rpath and platform supports it. */ bool HasMacOSXRpathInstallNameDir(const std::string& config) const; @@ -436,26 +281,6 @@ public: no soname at all. */ bool IsImportedSharedLibWithoutSOName(const std::string& config) const; - /** Get the full path to the target according to the settings in its - makefile and the configuration type. */ - std::string GetFullPath(const std::string& config="", bool implib = false, - bool realname = false) const; - - /** Get the names of the library needed to generate a build rule - that takes into account shared library version numbers. This - should be called only on a library target. */ - void GetLibraryNames(std::string& name, std::string& soName, - std::string& realName, std::string& impName, - std::string& pdbName, const std::string& config) const; - - /** Get the names of the executable needed to generate a build rule - that takes into account executable version numbers. This should - be called only on an executable target. */ - void GetExecutableNames(std::string& name, std::string& realName, - std::string& impName, - std::string& pdbName, - const std::string& config) const; - /** Does this target have a GNU implib to convert to MS format? */ bool HasImplibGNUtoMS() const; @@ -464,29 +289,8 @@ public: bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out, const char* newExt = 0) const; - /** - * Compute whether this target must be relinked before installing. - */ - bool NeedRelinkBeforeInstall(const std::string& config) const; - - bool HaveBuildTreeRPATH(const std::string& config) const; bool HaveInstallTreeRPATH() const; - /** Return true if builtin chrpath will work for this target */ - bool IsChrpathUsed(const std::string& config) const; - - /** Return the install name directory for the target in the - * build tree. For example: "\@rpath/", "\@loader_path/", - * or "/full/path/to/library". */ - std::string GetInstallNameDirForBuildTree(const std::string& config) const; - - /** Return the install name directory for the target in the - * install tree. For example: "\@rpath/" or "\@loader_path/". */ - std::string GetInstallNameDirForInstallTree() const; - - cmComputeLinkInformation* - GetLinkInformation(const std::string& config) const; - // Get the properties cmPropertyMap &GetProperties() const { return this->Properties; } @@ -499,18 +303,6 @@ public: If no macro should be defined null is returned. */ const char* GetExportMacro() const; - void GetCompileDefinitions(std::vector<std::string> &result, - const std::string& config, - const std::string& language) const; - - // Compute the set of languages compiled by the target. This is - // computed every time it is called because the languages can change - // when source file properties are changed and we do not have enough - // information to forward these property changes to the targets - // until we have per-target object file properties. - void GetLanguages(std::set<std::string>& languages, - std::string const& config) const; - /** Return whether this target is an executable with symbol exports enabled. */ bool IsExecutableWithExports() const; @@ -537,10 +329,6 @@ public: /** Return whether this target is an executable Bundle on Apple. */ bool IsAppBundleOnApple() const; - /** Return whether this target is an executable Bundle, a framework - or CFBundle on Apple. */ - bool IsBundleOnApple() const; - /** Return the framework version string. Undefined if IsFrameworkOnApple returns false. */ std::string GetFrameworkVersion() const; @@ -555,86 +343,50 @@ public: directory. */ bool UsesDefaultOutputDir(const std::string& config, bool implib) const; - /** @return the mac content directory for this target. */ - std::string GetMacContentDirectory(const std::string& config, - bool implib) const; - /** @return whether this target have a well defined output file name. */ bool HaveWellDefinedOutputFiles() const; - /** @return the Mac framework directory without the base. */ - std::string GetFrameworkDirectory(const std::string& config, - bool rootDir) const; - - /** @return the Mac CFBundle directory without the base */ - std::string GetCFBundleDirectory(const std::string& config, - bool contentOnly) const; - - /** @return the Mac App directory without the base */ - std::string GetAppBundleDirectory(const std::string& config, - bool contentOnly) const; - - std::vector<std::string> GetIncludeDirectories( - const std::string& config, - const std::string& language) const; - void InsertInclude(const cmValueWithOrigin &entry, + void InsertInclude(std::string const& entry, + cmListFileBacktrace const& bt, bool before = false); - void InsertCompileOption(const cmValueWithOrigin &entry, - bool before = false); - void InsertCompileDefinition(const cmValueWithOrigin &entry); + void InsertCompileOption(std::string const& entry, + cmListFileBacktrace const& bt, + bool before = false); + void InsertCompileDefinition(std::string const& entry, + cmListFileBacktrace const& bt); void AppendBuildInterfaceIncludes(); - void GetCompileOptions(std::vector<std::string> &result, - const std::string& config, - const std::string& language) const; - void GetAutoUicOptions(std::vector<std::string> &result, - const std::string& config) const; - void GetCompileFeatures(std::vector<std::string> &features, - const std::string& config) const; - bool IsNullImpliedByLinkLibraries(const std::string &p) const; - bool IsLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const; - bool IsLinkInterfaceDependentStringProperty(const std::string &p, - const std::string& config) const; - bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p, - const std::string& config) const; - bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, - const std::string& config) const; - - bool GetLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const; - - const char *GetLinkInterfaceDependentStringProperty(const std::string &p, - const std::string& config) const; - const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p, - const std::string& config) const; - const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p, - const std::string& config) const; std::string GetDebugGeneratorExpressions(const std::string &value, cmTarget::LinkLibraryType llt) const; void AddSystemIncludeDirectories(const std::set<std::string> &incs); - void AddSystemIncludeDirectories(const std::vector<std::string> &incs); std::set<std::string> const & GetSystemIncludeDirectories() const { return this->SystemIncludeDirectories; } bool LinkLanguagePropagatesToDependents() const { return this->TargetTypeValue == STATIC_LIBRARY; } - void ReportPropertyOrigin(const std::string &p, - const std::string &result, - const std::string &report, - const std::string &compatibilityType) const; - std::map<std::string, std::string> const& GetMaxLanguageStandards() const { return this->MaxLanguageStandards; } + cmStringRange GetIncludeDirectoriesEntries() const; + cmBacktraceRange GetIncludeDirectoriesBacktraces() const; + + cmStringRange GetCompileOptionsEntries() const; + cmBacktraceRange GetCompileOptionsBacktraces() const; + + cmStringRange GetCompileFeaturesEntries() const; + cmBacktraceRange GetCompileFeaturesBacktraces() const; + + cmStringRange GetCompileDefinitionsEntries() const; + cmBacktraceRange GetCompileDefinitionsBacktraces() const; + #if defined(_WIN32) && !defined(__CYGWIN__) const LinkLibraryVectorType &GetLinkLibrariesForVS6() const { return this->LinkLibrariesForVS6;} @@ -643,12 +395,6 @@ public: private: bool HandleLocationPropertyPolicy(cmMakefile* context) const; - // The set of include directories that are marked as system include - // directories. - std::set<std::string> SystemIncludeDirectories; - - std::vector<std::pair<TLLSignature, cmListFileContext> > TLLCommands; - #if defined(_WIN32) && !defined(__CYGWIN__) /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -704,11 +450,6 @@ private: const char* GetSuffixVariableInternal(bool implib) const; const char* GetPrefixVariableInternal(bool implib) const; - std::string GetFullNameInternal(const std::string& config, - bool implib) const; - void GetFullNameInternal(const std::string& config, bool implib, - std::string& outPrefix, std::string& outBase, - std::string& outSuffix) const; // Use a makefile variable to set a default for the given property. // If the variable is not defined use the given default instead. @@ -718,65 +459,53 @@ private: // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type. const char* GetOutputTargetType(bool implib) const; - // Get the target base name. - std::string GetOutputName(const std::string& config, bool implib) const; - std::string GetFullNameImported(const std::string& config, bool implib) const; std::string ImportedGetFullPath(const std::string& config, bool implib) const; - std::string NormalGetFullPath(const std::string& config, bool implib, - bool realname) const; - - /** Get the real name of the target. Allowed only for non-imported - targets. When a library or executable file is versioned this is - the full versioned name. If the target is not versioned this is - the same as GetFullName. */ - std::string NormalGetRealName(const std::string& config) const; - /** Append to @a base the mac content directory and return it. */ - std::string BuildMacContentDirectory(const std::string& base, - const std::string& config, - bool contentOnly) const; void GetSourceFiles(std::vector<std::string> &files, const std::string& config) const; private: + mutable cmPropertyMap Properties; + std::set<std::string> SystemIncludeDirectories; + std::set<std::string> LinkDirectoriesEmmitted; + std::set<std::string> Utilities; + mutable std::set<std::string> LinkImplicitNullProperties; + std::map<std::string, cmListFileBacktrace> UtilityBacktraces; + mutable std::map<std::string, std::string> MaxLanguageStandards; + cmPolicies::PolicyMap PolicyMap; std::string Name; + std::string InstallPath; + std::string RuntimeInstallPath; + mutable std::string ExportMacro; + std::vector<std::string> LinkDirectories; std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; std::vector<cmCustomCommand> PostBuildCommands; - TargetType TargetTypeValue; + std::vector<std::pair<TLLSignature, cmListFileContext> > TLLCommands; LinkLibraryVectorType PrevLinkedLibraries; + LinkLibraryVectorType OriginalLinkLibraries; #if defined(_WIN32) && !defined(__CYGWIN__) LinkLibraryVectorType LinkLibrariesForVS6; - bool LinkLibrariesForVS6Analyzed; #endif - std::vector<std::string> LinkDirectories; - std::set<std::string> LinkDirectoriesEmmitted; + cmMakefile* Makefile; + cmTargetInternalPointer Internal; + TargetType TargetTypeValue; bool HaveInstallRule; - std::string InstallPath; - std::string RuntimeInstallPath; - mutable std::string ExportMacro; - std::set<std::string> Utilities; - std::map<std::string, cmListFileBacktrace> UtilityBacktraces; bool RecordDependencies; - mutable cmPropertyMap Properties; - LinkLibraryVectorType OriginalLinkLibraries; bool DLLPlatform; bool IsAndroid; bool IsApple; bool IsImportedTarget; - mutable bool DebugIncludesDone; - mutable std::map<std::string, bool> DebugCompatiblePropertiesDone; - mutable bool DebugCompileOptionsDone; - mutable bool DebugCompileDefinitionsDone; - mutable bool DebugSourcesDone; - mutable bool DebugCompileFeaturesDone; - mutable std::set<std::string> LinkImplicitNullProperties; - mutable std::map<std::string, std::string> MaxLanguageStandards; bool BuildInterfaceIncludesAppended; + mutable bool DebugSourcesDone; + mutable bool LinkImplementationLanguageIsContextDependent; +#if defined(_WIN32) && !defined(__CYGWIN__) + bool LinkLibrariesForVS6Analyzed; +#endif // Cache target output paths for each configuration. struct OutputInfo; @@ -788,35 +517,27 @@ private: std::string& out) const; // Cache import information from properties for each configuration. - struct ImportInfo; + struct ImportInfo + { + ImportInfo(): NoSOName(false), Multiplicity(0) {} + bool NoSOName; + int Multiplicity; + std::string Location; + std::string SOName; + std::string ImportLibrary; + std::string Languages; + std::string Libraries; + std::string LibrariesProp; + std::string SharedDeps; + }; + ImportInfo const* GetImportInfo(const std::string& config) const; void ComputeImportInfo(std::string const& desired_config, ImportInfo& info) const; - // Cache target compile paths for each configuration. - struct CompileInfo; - CompileInfo const* GetCompileInfo(const std::string& config) const; - - mutable cmTargetLinkInformationMap LinkInformation; - void CheckPropertyCompatibility(cmComputeLinkInformation *info, - const std::string& config) const; - - LinkInterface const* - GetImportLinkInterface(const std::string& config, cmTarget const* head, - bool usage_requirements_only) const; - - LinkImplementationLibraries const* + cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(const std::string& config, cmTarget const* head) const; - void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; - - void ExpandLinkItems(std::string const& prop, std::string const& value, - std::string const& config, cmTarget const* headTarget, - bool usage_requirements_only, - std::vector<cmLinkItem>& items, - bool& hadHeadSensitiveCondition) const; - void LookupLinkItems(std::vector<std::string> const& names, - std::vector<cmLinkItem>& items) const; std::string ProcessSourceItemCMP0049(const std::string& s); @@ -824,25 +545,10 @@ private: void MaybeInvalidatePropertyCache(const std::string& prop); - void ProcessSourceExpression(std::string const& expr); - - // The cmMakefile instance that owns this target. This should - // always be set. - cmMakefile* Makefile; - - // Policy status recorded when target was created. -#define TARGET_POLICY_MEMBER(POLICY) \ - cmPolicies::PolicyStatus PolicyStatus ## POLICY; - - CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_MEMBER) - -#undef TARGET_POLICY_MEMBER - // Internal representation details. friend class cmTargetInternals; friend class cmGeneratorTarget; friend class cmTargetTraceDependencies; - cmTargetInternalPointer Internal; void ComputeVersionedName(std::string& vName, std::string const& prefix, @@ -850,8 +556,6 @@ private: std::string const& suffix, std::string const& name, const char* version) const; - - mutable bool LinkImplementationLanguageIsContextDependent; }; #ifdef CMAKE_BUILD_WITH_CMAKE diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index a85153d..8e86f0f 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -50,7 +50,6 @@ bool cmTargetCompileOptionsCommand bool, bool) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmValueWithOrigin entry(this->Join(content), lfbt); - tgt->InsertCompileOption(entry); + tgt->InsertCompileOption(this->Join(content), lfbt); return true; } diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index 1feb072..c5059ee 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -14,23 +14,24 @@ #include "cmStandardIncludes.h" -class cmTarget; +class cmGeneratorTarget; /** One edge in the global target dependency graph. It may be marked as a 'link' or 'util' edge or both. */ class cmTargetDepend { - cmTarget const* Target; + cmGeneratorTarget const* Target; // The set order depends only on the Target, so we use // mutable members to acheive a map with set syntax. mutable bool Link; mutable bool Util; public: - cmTargetDepend(cmTarget const* t): Target(t), Link(false), Util(false) {} - operator cmTarget const*() const { return this->Target; } - cmTarget const* operator->() const { return this->Target; } - cmTarget const& operator*() const { return *this->Target; } + cmTargetDepend(cmGeneratorTarget const* t) + : Target(t), Link(false), Util(false) {} + operator cmGeneratorTarget const*() const { return this->Target; } + cmGeneratorTarget const* operator->() const { return this->Target; } + cmGeneratorTarget const& operator*() const { return *this->Target; } friend bool operator < (cmTargetDepend const& l, cmTargetDepend const& r) { return l.Target < r.Target; } void SetType(bool strong) const diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 24500db..7dfe9ca 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -72,11 +72,26 @@ bool cmTargetIncludeDirectoriesCommand bool prepend, bool system) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - cmValueWithOrigin entry(this->Join(content), lfbt); - tgt->InsertInclude(entry, prepend); + tgt->InsertInclude(this->Join(content), lfbt, prepend); if (system) { - tgt->AddSystemIncludeDirectories(content); + std::string prefix = + this->Makefile->GetCurrentSourceDirectory() + std::string("/"); + std::set<std::string> sdirs; + for (std::vector<std::string>::const_iterator it = content.begin(); + it != content.end(); ++it) + { + if (cmSystemTools::FileIsFullPath(it->c_str()) + || cmGeneratorExpression::Find(*it) == 0) + { + sdirs.insert(*it); + } + else + { + sdirs.insert(prefix + *it); + } + } + tgt->AddSystemIncludeDirectories(sdirs); } return true; } @@ -92,7 +107,7 @@ void cmTargetIncludeDirectoriesCommand if (system) { - std::string joined = cmJoin(content, ";"); + std::string joined = this->Join(content); tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined.c_str()); } diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index ff5d411..6fcd0dc 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -21,7 +21,6 @@ cmTest::cmTest(cmMakefile* mf) { this->Makefile = mf; this->OldStyle = true; - this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); } //---------------------------------------------------------------------------- @@ -50,12 +49,15 @@ void cmTest::SetCommand(std::vector<std::string> const& command) //---------------------------------------------------------------------------- const char *cmTest::GetProperty(const std::string& prop) const { - bool chain = false; - const char *retVal = - this->Properties.GetPropertyValue(prop, cmProperty::TEST, chain); - if (chain) + const char *retVal = this->Properties.GetPropertyValue(prop); + if (!retVal) { - return this->Makefile->GetProperty(prop,cmProperty::TEST); + const bool chain = this->Makefile->GetState()-> + IsPropertyChained(prop, cmProperty::TEST); + if (chain) + { + return this->Makefile->GetProperty(prop, chain); + } } return retVal; } @@ -69,12 +71,12 @@ bool cmTest::GetPropertyAsBool(const std::string& prop) const //---------------------------------------------------------------------------- void cmTest::SetProperty(const std::string& prop, const char* value) { - this->Properties.SetProperty(prop, value, cmProperty::TEST); + this->Properties.SetProperty(prop, value); } //---------------------------------------------------------------------------- void cmTest::AppendProperty(const std::string& prop, const char* value, bool asString) { - this->Properties.AppendProperty(prop, value, cmProperty::TEST, asString); + this->Properties.AppendProperty(prop, value, asString); } diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 7e11d8c..9d85f5a 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -12,8 +12,9 @@ #include "cmTestGenerator.h" #include "cmGeneratorExpression.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmMakefile.h" +#include "cmLocalGenerator.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTest.h" @@ -27,6 +28,7 @@ cmTestGenerator { this->ActionsPerConfig = !test->GetOldStyle(); this->TestGenerated = false; + this->LG = 0; } //---------------------------------------------------------------------------- @@ -35,6 +37,11 @@ cmTestGenerator { } +void cmTestGenerator::Compute(cmLocalGenerator* lg) +{ + this->LG = lg; +} + //---------------------------------------------------------------------------- void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent const& indent) @@ -70,7 +77,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, this->TestGenerated = true; // Set up generator expression evaluation context. - cmGeneratorExpression ge(&this->Test->GetBacktrace()); + cmGeneratorExpression ge(this->Test->GetBacktrace()); // Start the test command. os << indent << "add_test(" << this->Test->GetName() << " "; @@ -81,8 +88,8 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Check whether the command executable is a target whose name is to // be translated. std::string exe = command[0]; - cmMakefile* mf = this->Test->GetMakefile(); - cmTarget* target = mf->FindTargetToUse(exe); + cmGeneratorTarget* target = + this->LG->GetMakefile()->FindGeneratorTargetToUse(exe); if(target && target->GetType() == cmTarget::EXECUTABLE) { // Use the target file on disk. @@ -97,30 +104,31 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); std::string emulatorExe(emulatorWithArgs[0]); cmSystemTools::ConvertToUnixSlashes(emulatorExe); - os << cmLocalGenerator::EscapeForCMake(emulatorExe) << " "; + os << cmOutputConverter::EscapeForCMake(emulatorExe) << " "; for(std::vector<std::string>::const_iterator ei = emulatorWithArgs.begin()+1; ei != emulatorWithArgs.end(); ++ei) { - os << cmLocalGenerator::EscapeForCMake(*ei) << " "; + os << cmOutputConverter::EscapeForCMake(*ei) << " "; } } } else { // Use the command name given. - exe = ge.Parse(exe.c_str())->Evaluate(mf, config); + exe = ge.Parse(exe.c_str())->Evaluate(this->LG->GetMakefile(), config); cmSystemTools::ConvertToUnixSlashes(exe); } // Generate the command line with full escapes. - os << cmLocalGenerator::EscapeForCMake(exe); + os << cmOutputConverter::EscapeForCMake(exe); for(std::vector<std::string>::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) { - os << " " << cmLocalGenerator::EscapeForCMake( - ge.Parse(*ci)->Evaluate(mf, config)); + os << " " << cmOutputConverter::EscapeForCMake( + ge.Parse(*ci)->Evaluate( + this->LG->GetMakefile(), config)); } // Finish the test command. @@ -136,8 +144,9 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, i != pm.end(); ++i) { os << " " << i->first - << " " << cmLocalGenerator::EscapeForCMake( - ge.Parse(i->second.GetValue())->Evaluate(mf, config)); + << " " << cmOutputConverter::EscapeForCMake( + ge.Parse(i->second.GetValue())->Evaluate(this->LG->GetMakefile(), + config)); } os << ")" << std::endl; } @@ -206,7 +215,7 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, i != pm.end(); ++i) { fout << " " << i->first - << " " << cmLocalGenerator::EscapeForCMake(i->second.GetValue()); + << " " << cmOutputConverter::EscapeForCMake(i->second.GetValue()); } fout << ")" << std::endl; } diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index 5446553..de8ab78 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -15,6 +15,7 @@ #include "cmScriptGenerator.h" class cmTest; +class cmLocalGenerator; /** \class cmTestGenerator * \brief Support class for generating install scripts. @@ -28,6 +29,8 @@ public: configurations = std::vector<std::string>()); virtual ~cmTestGenerator(); + void Compute(cmLocalGenerator* lg); + protected: virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent); virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); @@ -38,6 +41,7 @@ protected: virtual bool NeedsScriptNoConfig() const; void GenerateOldStyle(std::ostream& os, Indent const& indent); + cmLocalGenerator* LG; cmTest* Test; bool TestGenerated; }; diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 9473008..98a397c 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -49,30 +49,26 @@ static void cmVariableWatchCommandVariableAccessed( newLFF.Arguments.clear(); newLFF.Arguments.push_back( cmListFileArgument(variable, cmListFileArgument::Quoted, - "unknown", 9999)); + 9999)); newLFF.Arguments.push_back( cmListFileArgument(accessString, cmListFileArgument::Quoted, - "unknown", 9999)); + 9999)); newLFF.Arguments.push_back( cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted, - "unknown", 9999)); + 9999)); newLFF.Arguments.push_back( cmListFileArgument(currentListFile, cmListFileArgument::Quoted, - "unknown", 9999)); + 9999)); newLFF.Arguments.push_back( cmListFileArgument(stack, cmListFileArgument::Quoted, - "unknown", 9999)); + 9999)); newLFF.Name = data->Command; - newLFF.FilePath = "Some weird path"; newLFF.Line = 9999; cmExecutionStatus status; if(!makefile->ExecuteCommand(newLFF,status)) { - arg.FilePath = "Unknown"; - arg.Line = 0; std::ostringstream error; - error << "Error in cmake code at\n" - << arg.FilePath << ":" << arg.Line << ":\n" + error << "Error in cmake code at\nUnknown:0:\n" << "A command failed during the invocation of callback \"" << data->Command << "\"."; cmSystemTools::Error(error.str().c_str()); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 5dfdb14..4c380f7 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -176,9 +176,8 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->Makefile->GetConfigurations(this->Configurations); this->LocalGenerator = (cmLocalVisualStudio7Generator*) - this->Makefile->GetLocalGenerator(); + this->GeneratorTarget->GetLocalGenerator(); this->Name = this->Target->GetName(); - this->GlobalGenerator->CreateGUID(this->Name.c_str()); this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str()); this->Platform = gg->GetPlatformName(); this->NsightTegra = gg->IsNsightTegra(); @@ -325,12 +324,22 @@ void cmVisualStudio10TargetGenerator::Generate() if(this->NsightTegra) { this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1); - if(this->NsightTegraVersion[0] >= 2) + const int nsightTegraMajorVersion = this->NsightTegraVersion[0]; + const int nsightTegraMinorVersion = this->NsightTegraVersion[1]; + if (nsightTegraMajorVersion >= 2) { - // Nsight Tegra 2.0 uses project revision 9. - this->WriteString("<NsightTegraProjectRevisionNumber>" - "9" - "</NsightTegraProjectRevisionNumber>\n", 2); + this->WriteString("<NsightTegraProjectRevisionNumber>", 2); + if (nsightTegraMajorVersion > 3 || + (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) + { + (*this->BuildFileStream) << "11"; + } + else + { + // Nsight Tegra 2.0 uses project revision 9. + (*this->BuildFileStream) << "9"; + } + (*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n"; // Tell newer versions to upgrade silently when loading. this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>" "true" @@ -788,6 +797,20 @@ void cmVisualStudio10TargetGenerator (*this->BuildFileStream ) << "android-" << cmVS10EscapeXML(api) << "</AndroidTargetAPI>\n"; } + + if(const char* cpuArch = this->Target->GetProperty("ANDROID_ARCH")) + { + this->WriteString("<AndroidArch>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) << + "</AndroidArch>\n"; + } + + if(const char* stlType = this->Target->GetProperty("ANDROID_STL_TYPE")) + { + this->WriteString("<AndroidStlType>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(stlType) << + "</AndroidStlType>\n"; + } } void cmVisualStudio10TargetGenerator::WriteCustomCommands() @@ -867,7 +890,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, i = this->Configurations.begin(); i != this->Configurations.end(); ++i) { - cmCustomCommandGenerator ccg(command, *i, this->Makefile); + cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); std::string script = @@ -923,10 +946,7 @@ cmVisualStudio10TargetGenerator::ConvertPath(std::string const& path, return forceRelative ? cmSystemTools::RelativePath( this->Makefile->GetCurrentBinaryDirectory(), path.c_str()) - : this->LocalGenerator->Convert(path.c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::UNCHANGED, - /* optional = */ true); + : path.c_str(); } void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s) @@ -945,7 +965,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); std::vector<cmSourceFile*> classes; - if (!this->Target->GetConfigCommonSourceFiles(classes)) + if (!this->GeneratorTarget->GetConfigCommonSourceFiles(classes)) { return; } @@ -1084,7 +1104,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups() (*this->BuildFileStream) << name << "\">\n"; std::string guidName = "SG_Filter_"; guidName += name; - this->GlobalGenerator->CreateGUID(guidName.c_str()); this->WriteString("<UniqueIdentifier>", 3); std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str()); @@ -1099,7 +1118,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups() { this->WriteString("<Filter Include=\"Object Libraries\">\n", 2); std::string guidName = "SG_Filter_Object Libraries"; - this->GlobalGenerator->CreateGUID(guidName.c_str()); this->WriteString("<UniqueIdentifier>", 3); std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str()); @@ -1112,7 +1130,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups() { this->WriteString("<Filter Include=\"Resource Files\">\n", 2); std::string guidName = "SG_Filter_Resource Files"; - this->GlobalGenerator->CreateGUID(guidName.c_str()); this->WriteString("<UniqueIdentifier>", 3); std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str()); @@ -1610,7 +1627,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( this->GlobalGenerator->GetLanguageFromExtension (sf.GetExtension().c_str()); std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf); - const std::string& linkLanguage = this->Target->GetLinkerLanguage(); + const std::string& linkLanguage = this->GeneratorTarget->GetLinkerLanguage(); bool needForceLang = false; // source file does not match its extension language if(lang != sourceLang) @@ -1639,7 +1656,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( // for the first time we need a new line if there is something // produced here. const char* firstString = ">\n"; - if(objectName.size()) + if(!objectName.empty()) { (*this->BuildFileStream ) << firstString; firstString = ""; @@ -1658,7 +1675,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( defPropName += configUpper; if(const char* ccdefs = sf.GetProperty(defPropName.c_str())) { - if(configDefines.size()) + if(!configDefines.empty()) { configDefines += ";"; } @@ -1757,7 +1774,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() else { outDir = this->Target->GetDirectory(config->c_str()) + "/"; - targetNameFull = this->Target->GetFullName(config->c_str()); + targetNameFull = this->GeneratorTarget->GetFullName(config->c_str()); } this->ConvertToWindowsSlash(intermediateDir); this->ConvertToWindowsSlash(outDir); @@ -1871,7 +1888,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( std::string flags; const std::string& linkLanguage = - this->Target->GetLinkerLanguage(configName.c_str()); + this->GeneratorTarget->GetLinkerLanguage(configName.c_str()); if(linkLanguage.empty()) { cmSystemTools::Error @@ -1917,7 +1934,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); std::vector<std::string> targetDefines; - this->Target->GetCompileDefinitions(targetDefines, + this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName.c_str(), "CXX"); clOptions.AddDefines(targetDefines); if(this->MSTools) @@ -1985,6 +2002,17 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "CXX"); + if(this->NsightTegra) + { + if(const char* processMax = + this->Target->GetProperty("ANDROID_PROCESS_MAX")) + { + this->WriteString("<ProcessMax>", 3); + *this->BuildFileStream << cmVS10EscapeXML(processMax) << + "</ProcessMax>\n"; + } + } + if(this->MSTools) { this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); @@ -1998,7 +2026,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( } // Specify the compiler program database file if configured. - std::string pdb = this->Target->GetCompilePDBPath(configName.c_str()); + std::string pdb = + this->GeneratorTarget->GetCompilePDBPath(configName.c_str()); if(!pdb.empty()) { this->ConvertToWindowsSlash(pdb); @@ -2177,7 +2206,7 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) //---------------------------------------------------------------------------- void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( - std::string const&) + std::string const& configName) { // Look through the sources for AndroidManifest.xml and use // its location as the root source directory. @@ -2207,6 +2236,92 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( cmVS10EscapeXML(antBuildPath) << "</AntBuildPath>\n"; } + if (this->Target->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) + { + this->WriteString("<SkipAntStep>true</SkipAntStep>\n", 3); + } + + if (this->Target->GetPropertyAsBool("ANDROID_PROGUARD")) + { + this->WriteString("<EnableProGuard>true</EnableProGuard>\n", 3); + } + + if (const char* proGuardConfigLocation = + this->Target->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) + { + this->WriteString("<ProGuardConfigLocation>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(proGuardConfigLocation) << + "</ProGuardConfigLocation>\n"; + } + + if (const char* securePropertiesLocation = + this->Target->GetProperty("ANDROID_SECURE_PROPS_PATH")) + { + this->WriteString("<SecurePropertiesLocation>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(securePropertiesLocation) << + "</SecurePropertiesLocation>\n"; + } + + if (const char* nativeLibDirectoriesExpression = + this->Target->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) + { + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(nativeLibDirectoriesExpression); + std::string nativeLibDirs = cge->Evaluate(this->Makefile, configName); + this->WriteString("<NativeLibDirectories>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDirs) << + "</NativeLibDirectories>\n"; + } + + if (const char* nativeLibDependenciesExpression = + this->Target->GetProperty("ANDROID_NATIVE_LIB_DEPENDENCIES")) + { + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(nativeLibDependenciesExpression); + std::string nativeLibDeps = cge->Evaluate(this->Makefile, configName); + this->WriteString("<NativeLibDependencies>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDeps) << + "</NativeLibDependencies>\n"; + } + + if (const char* javaSourceDir = + this->Target->GetProperty("ANDROID_JAVA_SOURCE_DIR")) + { + this->WriteString("<JavaSourceDir>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(javaSourceDir) << + "</JavaSourceDir>\n"; + } + + if (const char* jarDirectoriesExpression = + this->Target->GetProperty("ANDROID_JAR_DIRECTORIES")) + { + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(jarDirectoriesExpression); + std::string jarDirectories = cge->Evaluate(this->Makefile, configName); + this->WriteString("<JarDirectories>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(jarDirectories) << + "</JarDirectories>\n"; + } + + if (const char* jarDeps = + this->Target->GetProperty("ANDROID_JAR_DEPENDENCIES")) + { + this->WriteString("<JarDependencies>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(jarDeps) << + "</JarDependencies>\n"; + } + + if (const char* assetsDirectories = + this->Target->GetProperty("ANDROID_ASSETS_DIRECTORIES")) + { + this->WriteString("<AssetsDirectories>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(assetsDirectories) << + "</AssetsDirectories>\n"; + } + { std::string manifest_xml = rootDir + "/AndroidManifest.xml"; this->ConvertToWindowsSlash(manifest_xml); @@ -2215,6 +2330,14 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( cmVS10EscapeXML(manifest_xml) << "</AndroidManifestLocation>\n"; } + if (const char* antAdditionalOptions = + this->Target->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) + { + this->WriteString("<AdditionalOptions>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(antAdditionalOptions) << + " %(AdditionalOptions)</AdditionalOptions>\n"; + } + this->WriteString("</AntBuild>\n", 2); } @@ -2248,7 +2371,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) Options& linkOptions = *pOptions; const std::string& linkLanguage = - this->Target->GetLinkerLanguage(config.c_str()); + this->GeneratorTarget->GetLinkerLanguage(config.c_str()); if(linkLanguage.empty()) { cmSystemTools::Error @@ -2299,7 +2422,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) libs = this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); // Remove trailing spaces from libs std::string::size_type pos = libs.size()-1; - if(libs.size() != 0) + if(!libs.empty()) { while(libs[pos] == ' ') { @@ -2316,7 +2439,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) cmSystemTools::ExpandListArgument(libs, libVec); cmComputeLinkInformation* pcli = - this->Target->GetLinkInformation(config.c_str()); + this->GeneratorTarget->GetLinkInformation(config.c_str()); if(!pcli) { cmSystemTools::Error @@ -2349,13 +2472,14 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) std::string targetNamePDB; if(this->Target->GetType() == cmTarget::EXECUTABLE) { - this->Target->GetExecutableNames(targetName, targetNameFull, + this->GeneratorTarget->GetExecutableNames(targetName, targetNameFull, targetNameImport, targetNamePDB, config.c_str()); } else { - this->Target->GetLibraryNames(targetName, targetNameSO, targetNameFull, + this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO, + targetNameFull, targetNameImport, targetNamePDB, config.c_str()); } @@ -2473,6 +2597,15 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) "%(IgnoreSpecificDefaultLibraries)"); } + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def"); + } + } + this->LinkOptions[config] = pOptions.release(); return true; } @@ -2620,8 +2753,25 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() void cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName) { - this->WriteEvent("PreLinkEvent", - this->Target->GetPreLinkCommands(), configName); + bool addedPrelink = false; + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + addedPrelink = true; + std::vector<cmCustomCommand> commands = + this->Target->GetPreLinkCommands(); + this->GlobalGenerator->AddSymbolExportCommand( + this->GeneratorTarget, commands, configName); + this->WriteEvent("PreLinkEvent", commands, configName); + } + } + if (!addedPrelink) + { + this->WriteEvent("PreLinkEvent", + this->Target->GetPreLinkCommands(), configName); + } this->WriteEvent("PreBuildEvent", this->Target->GetPreBuildCommands(), configName); this->WriteEvent("PostBuildEvent", @@ -2633,7 +2783,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent( std::vector<cmCustomCommand> const& commands, std::string const& configName) { - if(commands.size() == 0) + if(commands.empty()) { return; } @@ -2646,7 +2796,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent( for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); i != commands.end(); ++i) { - cmCustomCommandGenerator ccg(*i, configName, this->Makefile); + cmCustomCommandGenerator ccg(*i, configName, this->LocalGenerator); comment += pre; comment += lg->ConstructComment(ccg); script += pre; @@ -2667,7 +2817,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent( void cmVisualStudio10TargetGenerator::WriteProjectReferences() { cmGlobalGenerator::TargetDependSet const& unordered - = this->GlobalGenerator->GetTargetDirectDepends(*this->Target); + = this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget); typedef cmGlobalVisualStudioGenerator::OrderedTargetDependSet OrderedTargetDependSet; OrderedTargetDependSet depends(unordered); @@ -2675,7 +2825,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() for( OrderedTargetDependSet::const_iterator i = depends.begin(); i != depends.end(); ++i) { - cmTarget const* dt = *i; + cmTarget const* dt = (*i)->Target; if(dt->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -2743,7 +2893,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() (*this->BuildFileStream) << cmVS10EscapeXML(artifactDir) << "\\</AppxPackageArtifactsDir>\n"; this->WriteString("<ProjectPriFullPath>" - "$(TargetDir)resources.pri</ProjectPriFullPath>", 2); + "$(TargetDir)resources.pri</ProjectPriFullPath>\n", 2); // If we are missing files and we don't have a certificate and // aren't targeting WP8.0, add a default certificate @@ -2761,6 +2911,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() this->WriteString("<", 2); (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile << "</PackageCertificateKeyFile>\n"; + std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile); + if (!thumb.empty()) + { + this->WriteString("<PackageCertificateThumbprint>", 2); + (*this->BuildFileStream) << thumb + << "</PackageCertificateThumbprint>\n"; + } this->WriteString("</PropertyGroup>\n", 1); } else if(!pfxFile.empty()) @@ -2769,6 +2926,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() this->WriteString("<", 2); (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile << "</PackageCertificateKeyFile>\n"; + std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile); + if (!thumb.empty()) + { + this->WriteString("<PackageCertificateThumbprint>", 2); + (*this->BuildFileStream) << thumb + << "</PackageCertificateThumbprint>\n"; + } this->WriteString("</PropertyGroup>\n", 1); } } diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 6512fc2..bd4eb69 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -1,6 +1,6 @@ #include "cmVisualStudioGeneratorOptions.h" +#include "cmOutputConverter.h" #include "cmSystemTools.h" -#include <cmsys/System.h> #include "cmVisualStudio10TargetGenerator.h" static @@ -246,10 +246,10 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) // This option is not known. Store it in the output flags. this->FlagString += " "; this->FlagString += - cmSystemTools::EscapeWindowsShellArgument( + cmOutputConverter::EscapeWindowsShellArgument( flag, - cmsysSystem_Shell_Flag_AllowMakeVariables | - cmsysSystem_Shell_Flag_VSIDE); + cmOutputConverter::Shell_Flag_AllowMakeVariables | + cmOutputConverter::Shell_Flag_VSIDE); } //---------------------------------------------------------------------------- @@ -274,7 +274,7 @@ cmVisualStudioGeneratorOptions { // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions - if(this->Configuration.size()) + if(!this->Configuration.empty()) { fout << prefix; this->TargetGenerator->WritePlatformConfigTag( @@ -346,7 +346,7 @@ cmVisualStudioGeneratorOptions m != this->FlagMap.end(); ++m) { fout << indent; - if(this->Configuration.size()) + if(!this->Configuration.empty()) { this->TargetGenerator->WritePlatformConfigTag( m->first.c_str(), @@ -398,7 +398,7 @@ cmVisualStudioGeneratorOptions if(this->Version >= cmGlobalVisualStudioGenerator::VS10) { fout << prefix; - if(this->Configuration.size()) + if(!this->Configuration.empty()) { this->TargetGenerator->WritePlatformConfigTag( "AdditionalOptions", diff --git a/Source/cmXCode21Object.cxx b/Source/cmXCode21Object.cxx index f30f700..3973540 100644 --- a/Source/cmXCode21Object.cxx +++ b/Source/cmXCode21Object.cxx @@ -22,7 +22,7 @@ cmXCode21Object::cmXCode21Object(PBXType ptype, Type type) //---------------------------------------------------------------------------- void cmXCode21Object::PrintComment(std::ostream& out) { - if(this->Comment.size() == 0) + if(this->Comment.empty()) { cmXCodeObject* n = this->GetObject("name"); if(n) diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx index ba6e395..c59c360 100644 --- a/Source/cmXCodeObject.cxx +++ b/Source/cmXCodeObject.cxx @@ -243,7 +243,11 @@ void cmXCodeObject::PrintString(std::ostream& os,std::string String) bool needQuote = (String.empty() || String.find("//") != String.npos || - String.find_first_of(" <>+-*=@[](){},~") != String.npos); + String.find_first_not_of( + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "$_./") != String.npos); const char* quote = needQuote? "\"" : ""; // Print the string, quoted and escaped as necessary. diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx index 99f5625..4ad05ca 100644 --- a/Source/cmXMLSafe.cxx +++ b/Source/cmXMLSafe.cxx @@ -13,8 +13,8 @@ #include "cm_utf8.h" -#include <cmsys/ios/iostream> -#include <cmsys/ios/sstream> +#include <iostream> +#include <sstream> #include <string.h> #include <stdio.h> @@ -45,13 +45,13 @@ cmXMLSafe& cmXMLSafe::Quotes(bool b) //---------------------------------------------------------------------------- std::string cmXMLSafe::str() { - cmsys_ios::ostringstream ss; + std::ostringstream ss; ss << *this; return ss.str(); } //---------------------------------------------------------------------------- -cmsys_ios::ostream& operator<<(cmsys_ios::ostream& os, cmXMLSafe const& self) +std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self) { char const* first = self.Data; char const* last = self.Data + self.Size; diff --git a/Source/cmXMLSafe.h b/Source/cmXMLSafe.h index c23a90c..ead2e01 100644 --- a/Source/cmXMLSafe.h +++ b/Source/cmXMLSafe.h @@ -12,8 +12,9 @@ #ifndef cmXMLSafe_h #define cmXMLSafe_h -#include <cmsys/stl/string> -#include <cmsys/ios/iosfwd> +#include <cmsys/Configure.hxx> +#include <string> +#include <iosfwd> /** \class cmXMLSafe * \brief Write strings to XML with proper escapes @@ -37,8 +38,7 @@ private: char const* Data; unsigned long Size; bool DoQuotes; - friend cmsys_ios::ostream& operator<<(cmsys_ios::ostream&, - cmXMLSafe const&); + friend std::ostream& operator<<(std::ostream&, cmXMLSafe const&); }; #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 23803ef..f069481 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -75,7 +75,9 @@ # include "cmGlobalWatcomWMakeGenerator.h" #endif #include "cmGlobalUnixMakefileGenerator3.h" -#include "cmGlobalNinjaGenerator.h" +#if defined(CMAKE_BUILD_WITH_CMAKE) +# include "cmGlobalNinjaGenerator.h" +#endif #include "cmExtraCodeLiteGenerator.h" #if !defined(CMAKE_BOOT_MINGW) @@ -121,20 +123,18 @@ void cmWarnUnusedCliWarning(const std::string& variable, cmake::cmake() { this->Trace = false; + this->TraceExpand = false; this->WarnUninitialized = false; this->WarnUnused = false; this->WarnUnusedCli = true; this->CheckSystemVars = false; - this->SuppressDevWarnings = false; - this->DoSuppressDevWarnings = false; this->DebugOutput = false; this->DebugTryCompile = false; this->ClearBuildSystem = false; this->FileComparison = new cmFileTimeComparison; - this->Policies = new cmPolicies(); this->State = new cmState(this); - this->CurrentSnapshot = this->State->CreateSnapshot(cmState::Snapshot()); + this->CurrentSnapshot = this->State->CreateBaseSnapshot(); #ifdef __APPLE__ struct rlimit rlp; @@ -170,7 +170,6 @@ cmake::cmake() cmake::~cmake() { delete this->CacheManager; - delete this->Policies; delete this->State; if (this->GlobalGenerator) { @@ -186,7 +185,7 @@ cmake::~cmake() void cmake::CleanupCommandsAndMacros() { - this->State->Reset(); + this->CurrentSnapshot = this->State->Reset(); this->State->RemoveUserDefinedCommands(); } @@ -251,15 +250,70 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return false; } } - else if(arg.find("-Wno-dev",0) == 0) + else if(cmHasLiteralPrefix(arg, "-W")) { - this->SuppressDevWarnings = true; - this->DoSuppressDevWarnings = true; + std::string entry = arg.substr(2); + if (entry.empty()) + { + ++i; + if (i < args.size()) + { + entry = args[i]; + } + else + { + cmSystemTools::Error( + "-W must be followed with [no-][error=]<name>."); + return false; + } } - else if(arg.find("-Wdev",0) == 0) - { - this->SuppressDevWarnings = false; - this->DoSuppressDevWarnings = true; + + std::string name; + bool foundNo = false; + bool foundError = false; + unsigned int nameStartPosition = 0; + + if (entry.find("no-", nameStartPosition) == 0) + { + foundNo = true; + nameStartPosition += 3; + } + + if (entry.find("error=", nameStartPosition) == 0) + { + foundError = true; + nameStartPosition += 6; + } + + name = entry.substr(nameStartPosition); + if (name.empty()) + { + cmSystemTools::Error("No warning name provided."); + return false; + } + + if (!foundNo && !foundError) + { + // -W<name> + this->WarningLevels[name] = std::max(this->WarningLevels[name], + WARNING_LEVEL); + } + else if (foundNo && !foundError) + { + // -Wno<name> + this->WarningLevels[name] = IGNORE_LEVEL; + } + else if (!foundNo && foundError) + { + // -Werror=<name> + this->WarningLevels[name] = ERROR_LEVEL; + } + else + { + // -Wno-error=<name> + this->WarningLevels[name] = std::min(this->WarningLevels[name], + WARNING_LEVEL); + } } else if(arg.find("-U",0) == 0) { @@ -370,11 +424,14 @@ void cmake::ReadListFile(const std::vector<std::string>& args, // read in the list file to fill the cache if(path) { + this->CurrentSnapshot = this->State->Reset(); std::string homeDir = this->GetHomeDirectory(); std::string homeOutputDir = this->GetHomeOutputDirectory(); this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); - cmsys::auto_ptr<cmLocalGenerator> lg(gg->MakeLocalGenerator()); + cmState::Snapshot snapshot = this->GetCurrentSnapshot(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(gg, snapshot)); + cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator(mf.get())); lg->GetMakefile()->SetCurrentBinaryDirectory (cmSystemTools::GetCurrentWorkingDirectory()); lg->GetMakefile()->SetCurrentSourceDirectory @@ -414,9 +471,10 @@ bool cmake::FindPackage(const std::vector<std::string>& args) cmGlobalGenerator *gg = new cmGlobalGenerator(this); this->SetGlobalGenerator(gg); + cmState::Snapshot snapshot = this->GetCurrentSnapshot(); // read in the list file to fill the cache - cmsys::auto_ptr<cmLocalGenerator> lg(gg->MakeLocalGenerator()); - cmMakefile* mf = lg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(gg, snapshot)); + cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator(mf.get())); mf->SetCurrentBinaryDirectory (cmSystemTools::GetCurrentWorkingDirectory()); mf->SetCurrentSourceDirectory @@ -482,7 +540,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string linkPath; std::string flags; std::string linkFlags; - gg->CreateGeneratorTargets(mf); + gg->CreateGeneratorTargets(cmGlobalGenerator::AllTargets, lg.get()); cmGeneratorTarget *gtgt = gg->GetGeneratorTarget(tgt); lg->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags, gtgt, false); @@ -587,11 +645,7 @@ void cmake::SetArgs(const std::vector<std::string>& args, // skip for now i++; } - else if(arg.find("-Wno-dev",0) == 0) - { - // skip for now - } - else if(arg.find("-Wdev",0) == 0) + else if(arg.find("-W",0) == 0) { // skip for now } @@ -616,10 +670,17 @@ void cmake::SetArgs(const std::vector<std::string>& args, std::cout << "Running with debug output on.\n"; this->SetDebugOutputOn(true); } + else if(arg.find("--trace-expand",0) == 0) + { + std::cout << "Running with expanded trace output on.\n"; + this->SetTrace(true); + this->SetTraceExpand(true); + } else if(arg.find("--trace",0) == 0) { std::cout << "Running with trace output on.\n"; this->SetTrace(true); + this->SetTraceExpand(false); } else if(arg.find("--warn-uninitialized",0) == 0) { @@ -1171,25 +1232,121 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) int cmake::Configure() { - if(this->DoSuppressDevWarnings) + WarningLevel warningLevel; + + if (this->WarningLevels.count("deprecated") == 1) + { + warningLevel = this->WarningLevels["deprecated"]; + if (warningLevel == IGNORE_LEVEL) + { + this->CacheManager-> + AddCacheEntry("CMAKE_WARN_DEPRECATED", "FALSE", + "Whether to issue deprecation warnings for" + " macros and functions.", + cmState::BOOL); + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEPRECATED", "FALSE", + "Whether to issue deprecation errors for macros" + " and functions.", + cmState::BOOL); + } + if (warningLevel == WARNING_LEVEL) + { + this->CacheManager-> + AddCacheEntry("CMAKE_WARN_DEPRECATED", "TRUE", + "Whether to issue deprecation warnings for" + " macros and functions.", + cmState::BOOL); + } + else if (warningLevel == ERROR_LEVEL) + { + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEPRECATED", "TRUE", + "Whether to issue deprecation errors for macros" + " and functions.", + cmState::BOOL); + } + } + + if (this->WarningLevels.count("dev") == 1) { - if(this->SuppressDevWarnings) + bool setDeprecatedVariables = false; + + const char* cachedWarnDeprecated = + this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); + const char* cachedErrorDeprecated = + this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); + + // don't overwrite deprecated warning setting from a previous invocation + if (!cachedWarnDeprecated && !cachedErrorDeprecated) + { + setDeprecatedVariables = true; + } + + warningLevel = this->WarningLevels["dev"]; + if (warningLevel == IGNORE_LEVEL) { this->CacheManager-> AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", "Suppress Warnings that are meant for" " the author of the CMakeLists.txt files.", cmState::INTERNAL); + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEVELOPER_WARNINGS", "FALSE", + "Suppress errors that are meant for" + " the author of the CMakeLists.txt files.", + cmState::INTERNAL); + + if (setDeprecatedVariables) + { + this->CacheManager-> + AddCacheEntry("CMAKE_WARN_DEPRECATED", "FALSE", + "Whether to issue deprecation warnings for" + " macros and functions.", + cmState::BOOL); + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEPRECATED", "FALSE", + "Whether to issue deprecation errors for macros" + " and functions.", + cmState::BOOL); + } } - else + else if (warningLevel == WARNING_LEVEL) { this->CacheManager-> AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE", "Suppress Warnings that are meant for" " the author of the CMakeLists.txt files.", cmState::INTERNAL); + + if (setDeprecatedVariables) + { + this->CacheManager-> + AddCacheEntry("CMAKE_WARN_DEPRECATED", "TRUE", + "Whether to issue deprecation warnings for" + " macros and functions.", + cmState::BOOL); + } + } + else if (warningLevel == ERROR_LEVEL) + { + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEVELOPER_WARNINGS", "TRUE", + "Suppress errors that are meant for" + " the author of the CMakeLists.txt files.", + cmState::INTERNAL); + + if (setDeprecatedVariables) + { + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEPRECATED", "TRUE", + "Whether to issue deprecation errors for macros" + " and functions.", + cmState::BOOL); + } } } + int ret = this->ActualConfigure(); const char* delCacheVars = this->State ->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_"); @@ -1437,35 +1594,8 @@ int cmake::ActualConfigure() cmState::PATH); } } - if(!this->State - ->GetInitializedCacheValue("CMAKE_USE_RELATIVE_PATHS")) - { - this->State->AddCacheEntry - ("CMAKE_USE_RELATIVE_PATHS", "OFF", - "If true, cmake will use relative paths in makefiles and projects.", - cmState::BOOL); - if (!this->State->GetCacheEntryProperty("CMAKE_USE_RELATIVE_PATHS", - "ADVANCED")) - { - this->State->SetCacheEntryProperty("CMAKE_USE_RELATIVE_PATHS", - "ADVANCED", "1"); - } - } - if(cmSystemTools::GetFatalErrorOccured()) - { - const char* makeProgram = - this->State->GetInitializedCacheValue("CMAKE_MAKE_PROGRAM"); - if (!makeProgram || cmSystemTools::IsOff(makeProgram)) - { - // We must have a bad generator selection. Wipe the cache entry so the - // user can select another. - this->State->RemoveCacheEntry("CMAKE_GENERATOR"); - this->State->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR"); - } - } - - cmMakefile* mf=this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile(); + cmMakefile* mf=this->GlobalGenerator->GetMakefiles()[0]; if (mf->IsOn("CTEST_USE_LAUNCHERS") && !this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE")) { @@ -1547,6 +1677,18 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) { this->AddCMakePaths(); } + + // don't turn dev warnings into errors by default, if no value has been + // specified for the flag, disable it + if (!this->State->GetCacheEntryValue("CMAKE_ERROR_DEVELOPER_WARNINGS")) + { + this->CacheManager-> + AddCacheEntry("CMAKE_ERROR_DEVELOPER_WARNINGS", "FALSE", + "Suppress errors that are meant for" + " the author of the CMakeLists.txt files.", + cmState::INTERNAL); + } + // Add any cache args if ( !this->SetCacheArgs(args) ) { @@ -1625,7 +1767,11 @@ int cmake::Generate() { return -1; } - this->GlobalGenerator->DoGenerate(); + if (!this->GlobalGenerator->Compute()) + { + return -1; + } + this->GlobalGenerator->Generate(); if ( !this->GraphVizFile.empty() ) { std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl; @@ -1714,8 +1860,10 @@ void cmake::AddDefaultGenerators() #endif this->Generators.push_back( cmGlobalUnixMakefileGenerator3::NewFactory()); +#if defined(CMAKE_BUILD_WITH_CMAKE) this->Generators.push_back( cmGlobalNinjaGenerator::NewFactory()); +#endif #if defined(CMAKE_USE_WMAKE) this->Generators.push_back( cmGlobalWatcomWMakeGenerator::NewFactory()); @@ -1914,8 +2062,8 @@ int cmake::CheckBuildSystem() cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmGlobalGenerator gg(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); - cmMakefile* mf = lg->GetMakefile(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator(mf.get())); if(!mf->ReadListFile(this->CheckBuildSystemArgument.c_str()) || cmSystemTools::GetErrorOccuredFlag()) { @@ -1944,8 +2092,11 @@ int cmake::CheckBuildSystem() ggd(this->CreateGlobalGenerator(genName)); if(ggd.get()) { - cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->MakeLocalGenerator()); - lgd->ClearDependencies(mf, verbose); + cmsys::auto_ptr<cmMakefile> mfd(new cmMakefile(ggd.get(), + cm.GetCurrentSnapshot())); + cmsys::auto_ptr<cmLocalGenerator> lgd( + ggd->CreateLocalGenerator(mfd.get())); + lgd->ClearDependencies(mfd.get(), verbose); } } @@ -2445,20 +2596,17 @@ bool cmake::PrintMessagePreamble(cmake::MessageType t, std::ostream& msg) { msg << "CMake Deprecation Warning"; } + else if (t == cmake::AUTHOR_WARNING) + { + msg << "CMake Warning (dev)"; + } + else if (t == cmake::AUTHOR_ERROR) + { + msg << "CMake Error (dev)"; + } else { msg << "CMake Warning"; - if(t == cmake::AUTHOR_WARNING) - { - // Allow suppression of these warnings. - const char* suppress = this->State->GetCacheEntryValue( - "CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); - if(suppress && cmSystemTools::IsOn(suppress)) - { - return false; - } - msg << " (dev)"; - } } return true; } @@ -2480,6 +2628,12 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) msg << "This warning is for project developers. Use -Wno-dev to suppress it."; } + else if (t == cmake::AUTHOR_ERROR) + { + msg << + "This error is for project developers. Use -Wno-error=dev to suppress " + "it."; + } // Add a terminating blank line. msg << "\n"; @@ -2503,7 +2657,8 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) // Output the message. if(t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR - || t == cmake::DEPRECATION_ERROR) + || t == cmake::DEPRECATION_ERROR + || t == cmake::AUTHOR_ERROR) { cmSystemTools::SetErrorOccured(); cmSystemTools::Message(msg.str().c_str(), "Error"); @@ -2519,7 +2674,6 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, cmListFileBacktrace const& bt) { cmListFileBacktrace backtrace = bt; - backtrace.MakeRelative(); std::ostringstream msg; if (!this->PrintMessagePreamble(t, msg)) @@ -2595,6 +2749,25 @@ int cmake::Build(const std::string& dir, } std::string cachePath = dir; cmSystemTools::ConvertToUnixSlashes(cachePath); + std::string cacheFile = cachePath; + cacheFile += "/CMakeCache.txt"; + if(!cmSystemTools::FileExists(cacheFile.c_str())) + { + // search in parent directories for cache + std::string cmakeFiles = cachePath; + cmakeFiles += "/CMakeFiles"; + if(cmSystemTools::FileExists(cmakeFiles.c_str())) + { + std::string cachePathFound = + cmSystemTools::FileExistsInParentDirectories( + "CMakeCache.txt", cachePath.c_str(), "/"); + if(!cachePathFound.empty()) + { + cachePath = cmSystemTools::GetFilenamePath(cachePathFound); + } + } + } + if(!this->LoadCache(cachePath)) { std::cerr << "Error: could not load cache\n"; @@ -2682,3 +2855,18 @@ void cmake::RunCheckForUnusedVariables() } #endif } + +void cmake::SetSuppressDevWarnings(bool b) +{ + // equivalent to -Wno-dev + if (b) + { + this->WarningLevels["dev"] = IGNORE_LEVEL; + } + // equivalent to -Wdev + else + { + this->WarningLevels["dev"] = std::max(this->WarningLevels["dev"], + WARNING_LEVEL); + } +} diff --git a/Source/cmake.h b/Source/cmake.h index 12b7e68..8ac8897 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -27,7 +27,6 @@ class cmVariableWatch; class cmFileTimeComparison; class cmExternalMakefileProjectGenerator; class cmDocumentationSection; -class cmPolicies; class cmTarget; class cmGeneratedFileStream; @@ -60,6 +59,7 @@ class cmake public: enum MessageType { AUTHOR_WARNING, + AUTHOR_ERROR, FATAL_ERROR, INTERNAL_ERROR, MESSAGE, @@ -69,6 +69,12 @@ class cmake DEPRECATION_WARNING }; + enum WarningLevel + { + IGNORE_LEVEL, + WARNING_LEVEL, + ERROR_LEVEL + }; /** \brief Describes the working modes of cmake */ enum WorkingMode @@ -222,9 +228,6 @@ class cmake ///! this is called by generators to update the progress void UpdateProgress(const char *msg, float prog); - ///! get the cmake policies instance - cmPolicies *GetPolicies() {return this->Policies;} - ///! Get the variable watch object cmVariableWatch* GetVariableWatch() { return this->VariableWatch; } @@ -273,6 +276,9 @@ class cmake // Do we want trace output during the cmake run. bool GetTrace() { return this->Trace;} void SetTrace(bool b) { this->Trace = b;} + bool GetTraceExpand() { return this->TraceExpand;} + void SetTraceExpand(bool b) { this->TraceExpand = b;} + void SetSuppressDevWarnings(bool b); bool GetWarnUninitialized() { return this->WarnUninitialized;} void SetWarnUninitialized(bool b) { this->WarnUninitialized = b;} bool GetWarnUnused() { return this->WarnUnused;} @@ -293,15 +299,9 @@ class cmake std::string const& GetCMakeEditCommand() const { return this->CMakeEditCommand; } - void SetSuppressDevWarnings(bool v) - { - this->SuppressDevWarnings = v; - this->DoSuppressDevWarnings = true; - } - /** Display a message to the user. */ void IssueMessage(cmake::MessageType t, std::string const& text, - cmListFileBacktrace const& backtrace = cmListFileBacktrace(NULL)); + cmListFileBacktrace const& backtrace = cmListFileBacktrace()); void IssueMessage(cmake::MessageType t, std::string const& text, cmListFileContext const& lfc); @@ -339,11 +339,9 @@ protected: void AddExtraGenerator(const std::string& name, CreateExtraGeneratorFunctionType newFunction); - cmPolicies *Policies; cmGlobalGenerator *GlobalGenerator; cmCacheManager *CacheManager; - bool SuppressDevWarnings; - bool DoSuppressDevWarnings; + std::map<std::string, WarningLevel> WarningLevels; std::string GeneratorPlatform; std::string GeneratorToolset; @@ -381,6 +379,7 @@ private: WorkingMode CurrentWorkingMode; bool DebugOutput; bool Trace; + bool TraceExpand; bool WarnUninitialized; bool WarnUnused; bool WarnUnusedCli; @@ -418,7 +417,15 @@ private: {"-T <toolset-name>", "Specify toolset name if supported by generator."}, \ {"-A <platform-name>", "Specify platform name if supported by generator."}, \ {"-Wno-dev", "Suppress developer warnings."},\ - {"-Wdev", "Enable developer warnings."} + {"-Wdev", "Enable developer warnings."},\ + {"-Werror=dev", "Make developer warnings errors."},\ + {"-Wno-error=dev", "Make developer warnings not errors."},\ + {"-Wdeprecated", "Enable deprecated macro and function warnings."},\ + {"-Wno-deprecated", "Suppress deprecated macro and function warnings."},\ + {"-Werror=deprecated", "Make deprecated macro and function warnings " \ + "errors."},\ + {"-Wno-error=deprecated", "Make deprecated macro and function warnings " \ + "not errors."} #define FOR_EACH_C_FEATURE(F) \ F(c_function_prototypes) \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index e5f4700..a06b26f 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -83,6 +83,7 @@ static const char * cmDocumentationOptions[][2] = "useful on one try_compile at a time."}, {"--debug-output", "Put cmake in a debug mode."}, {"--trace", "Put cmake in trace mode."}, + {"--trace-expand", "Put cmake in trace mode with variable expansion."}, {"--warn-uninitialized", "Warn about uninitialized values."}, {"--warn-unused-vars", "Warn about unused variables."}, {"--no-warn-unused-cli", "Don't warn about command line options."}, @@ -113,12 +114,7 @@ static cmMakefile* cmakemainGetMakefile(void *clientdata) cmGlobalGenerator* gg=cm->GetGlobalGenerator(); if (gg) { - cmLocalGenerator* lg=gg->GetCurrentLocalGenerator(); - if (lg) - { - cmMakefile* mf = lg->GetMakefile(); - return mf; - } + return gg->GetCurrentMakefile(); } } return 0; @@ -425,7 +421,7 @@ static int do_build(int ac, char const* const* av) switch (doing) { case DoingDir: - dir = av[i]; + dir = cmSystemTools::CollapseFullPath(av[i]); doing = DoingNone; break; case DoingTarget: diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 3ea2186..aa70aa0 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -34,6 +34,10 @@ #include <time.h> #include <stdlib.h> // required for atoi +#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +// defined in binexplib.cxx +bool DumpFile(const char* filename, FILE *fout); +#endif void CMakeCommandUsage(const char* program) { @@ -211,6 +215,41 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) return 0; } +#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) + else if(args[1] == "__create_def") + { + if(args.size() < 4) + { + std::cerr << + "__create_def Usage: -E __create_def outfile.def objlistfile\n"; + return 1; + } + FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+"); + if(!fout) + { + std::cerr << "could not open output .def file: " << args[2].c_str() + << "\n"; + return 1; + } + cmsys::ifstream fin(args[3].c_str(), + std::ios::in | std::ios::binary); + if(!fin) + { + std::cerr << "could not open object list file: " << args[3].c_str() + << "\n"; + return 1; + } + std::string objfile; + while(cmSystemTools::GetLineFromStream(fin, objfile)) + { + if (!DumpFile(objfile.c_str(), fout)) + { + return 1; + } + } + return 0; + } +#endif // run include what you use command and then run the compile // command. This is an internal undocumented option and should // only be used by CMake itself when running iwyu. @@ -296,14 +335,14 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // Echo string else if (args[1] == "echo" ) { - std::cout << cmJoin(cmRange(args).advance(2), " ") << std::endl; + std::cout << cmJoin(cmMakeRange(args).advance(2), " ") << std::endl; return 0; } // Echo string no new line else if (args[1] == "echo_append" ) { - std::cout << cmJoin(cmRange(args).advance(2), " "); + std::cout << cmJoin(cmMakeRange(args).advance(2), " "); return 0; } @@ -472,7 +511,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // Clock command else if (args[1] == "time" && args.size() > 2) { - std::string command = cmJoin(cmRange(args).advance(2), " "); + std::string command = cmJoin(cmMakeRange(args).advance(2), " "); clock_t clock_start, clock_finish; time_t time_start, time_finish; @@ -533,7 +572,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) return 1; } - std::string command = cmWrap('"', cmRange(args).advance(3), '"', " "); + std::string command = + cmWrap('"', cmMakeRange(args).advance(3), '"', " "); int retval = 0; int timeout = 0; if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, 0, &retval, @@ -728,7 +768,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen)) { cm.SetGlobalGenerator(ggd); - cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->MakeLocalGenerator()); + cmState::Snapshot snapshot = cm.GetCurrentSnapshot(); + cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(ggd, snapshot)); + cmsys::auto_ptr<cmLocalGenerator> lgd( + ggd->CreateLocalGenerator(mf.get())); lgd->GetMakefile()->SetCurrentSourceDirectory(startDir); lgd->GetMakefile()->SetCurrentBinaryDirectory(startOutDir); @@ -1428,18 +1471,24 @@ bool cmcmd::RunCommand(const char* comment, std::string output; int retCode =0; // use rc command to create .res file - cmSystemTools::RunSingleCommand(command, - &output, &output, - &retCode, 0, cmSystemTools::OUTPUT_NONE); + bool res = cmSystemTools::RunSingleCommand(command, + &output, &output, + &retCode, 0, + cmSystemTools::OUTPUT_NONE); // always print the output of the command, unless // it is the dumb rc command banner, but if the command // returned an error code then print the output anyway as // the banner may be mixed with some other important information. if(output.find("Resource Compiler Version") == output.npos - || retCode !=0) + || !res || retCode) { std::cout << output; } + if (!res) + { + std::cout << comment << " failed to run." << std::endl; + return false; + } // if retCodeOut is requested then always return true // and set the retCodeOut to retCode if(retCodeOut) @@ -1553,7 +1602,10 @@ int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args, mtCommand.push_back(tempManifest); // now run mt.exe to create the final manifest file int mtRet =0; - cmcmd::RunCommand("MT", mtCommand, verbose, &mtRet); + if(!cmcmd::RunCommand("MT", mtCommand, verbose, &mtRet)) + { + return -1; + } // if mt returns 0, then the manifest was not changed and // we do not need to do another link step if(mtRet == 0) diff --git a/Source/ctest.cxx b/Source/ctest.cxx index e784759..afcbd61 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -98,6 +98,7 @@ static const char * cmDocumentationOptions[][2] = {"--test-command", "The test to run with the --build-and-test option."}, {"--test-timeout", "The time limit in seconds, internal use only."}, + {"--test-load", "CPU load threshold for starting new parallel tests."}, {"--tomorrow-tag", "Nightly or experimental starts with next day tag."}, {"--ctest-config", "The configuration file used to initialize CTest state " "when submitting dashboards."}, diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index c88e888..017d619 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -786,6 +786,15 @@ IF(KWSYS_USE_SystemInformation) SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1) ENDIF() + + IF(UNIX AND NOT CYGWIN) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_GETLOADAVG + "Checking whether CXX compiler has getloadavg" DIRECT) + IF(KWSYS_CXX_HAS_GETLOADAVG) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_CXX_HAS_GETLOADAVG=1) + ENDIF() + ENDIF() ENDIF() #----------------------------------------------------------------------------- @@ -1228,7 +1237,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) IF(NOT CYGWIN) SET(KWSYS_TEST_PROCESS_7 7) ENDIF() - FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7}) + FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7} 9 10) ADD_TEST(kwsys.testProcess-${n} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestProcess ${n}) SET_PROPERTY(TEST kwsys.testProcess-${n} PROPERTY LABELS ${KWSYS_LABELS_TEST}) SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120) @@ -1261,6 +1270,10 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}") ENDIF() + # Set up ctest custom configuration file. + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/CTestCustom.cmake.in + ${PROJECT_BINARY_DIR}/CTestCustom.cmake @ONLY) + # Suppress known consistent failures on buggy systems. IF(KWSYS_TEST_BOGUS_FAILURES) SET_TESTS_PROPERTIES(${KWSYS_TEST_BOGUS_FAILURES} PROPERTIES WILL_FAIL ON) diff --git a/Source/kwsys/CONTRIBUTING.rst b/Source/kwsys/CONTRIBUTING.rst index e097b76..960eea4 100644 --- a/Source/kwsys/CONTRIBUTING.rst +++ b/Source/kwsys/CONTRIBUTING.rst @@ -29,7 +29,7 @@ License We do not require any formal copyright assignment or contributor license agreement. Any contributions intentionally sent upstream are presumed -to be offerred under terms of the OSI-approved BSD 3-clause License. +to be offered under terms of the OSI-approved BSD 3-clause License. See `Copyright.txt`_ for details. .. _`Copyright.txt`: Copyright.txt diff --git a/Source/kwsys/CTestCustom.cmake.in b/Source/kwsys/CTestCustom.cmake.in new file mode 100644 index 0000000..d6f802e --- /dev/null +++ b/Source/kwsys/CTestCustom.cmake.in @@ -0,0 +1,15 @@ +# kwsys.testProcess-10 involves sending SIGINT to a child process, which then +# exits abnormally via a call to _exit(). (On Windows, a call to ExitProcess). +# Naturally, this results in plenty of memory being "leaked" by this child +# process - the memory check results are not meaningful in this case. +# +# kwsys.testProcess-9 also tests sending SIGINT to a child process. However, +# normal operation of that test involves the child process timing out, and the +# host process kills (SIGKILL) it as a result. Since it was SIGKILL'ed, the +# resulting memory leaks are not logged by valgrind anyway. Therefore, we +# don't have to exclude it. + +set(CTEST_CUSTOM_MEMCHECK_IGNORE + ${CTEST_CUSTOM_MEMCHECK_IGNORE} + kwsys.testProcess-10 + ) diff --git a/Source/kwsys/EncodingC.c b/Source/kwsys/EncodingC.c index ba2cec2..32b9bff 100644 --- a/Source/kwsys/EncodingC.c +++ b/Source/kwsys/EncodingC.c @@ -45,8 +45,11 @@ wchar_t* kwsysEncoding_DupToWide(const char* str) if(length > 0) { ret = (wchar_t*)malloc((length)*sizeof(wchar_t)); - ret[0] = 0; - kwsysEncoding_mbstowcs(ret, str, length); + if(ret) + { + ret[0] = 0; + kwsysEncoding_mbstowcs(ret, str, length); + } } return ret; } @@ -72,8 +75,11 @@ char* kwsysEncoding_DupToNarrow(const wchar_t* str) if(length > 0) { ret = (char*)malloc(length); - ret[0] = 0; - kwsysEncoding_wcstombs(ret, str, length); + if(ret) + { + ret[0] = 0; + kwsysEncoding_wcstombs(ret, str, length); + } } return ret; } diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index e35939f..c5ebc97 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -23,58 +23,60 @@ # define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT #endif #if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# define kwsysProcess kwsys_ns(Process) -# define kwsysProcess_s kwsys_ns(Process_s) -# define kwsysProcess_New kwsys_ns(Process_New) -# define kwsysProcess_Delete kwsys_ns(Process_Delete) -# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand) -# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand) -# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout) -# define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory) -# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile) -# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative) -# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared) -# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach) -# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow) -# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput) -# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim) -# define kwsysProcess_GetOption kwsys_ns(Process_GetOption) -# define kwsysProcess_SetOption kwsys_ns(Process_SetOption) -# define kwsysProcess_Option_e kwsys_ns(Process_Option_e) -# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting) -# define kwsysProcess_State_Error kwsys_ns(Process_State_Error) -# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception) -# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing) -# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited) -# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired) -# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed) -# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned) -# define kwsysProcess_GetState kwsys_ns(Process_GetState) -# define kwsysProcess_State_e kwsys_ns(Process_State_e) -# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None) -# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault) -# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal) -# define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt) -# define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical) -# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other) -# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException) -# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e) -# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode) -# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue) -# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString) -# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString) -# define kwsysProcess_Execute kwsys_ns(Process_Execute) -# define kwsysProcess_Disown kwsys_ns(Process_Disown) -# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) -# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e) -# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None) -# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN) -# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT) -# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR) -# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout) -# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle) -# define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit) -# define kwsysProcess_Kill kwsys_ns(Process_Kill) +# define kwsysProcess kwsys_ns(Process) +# define kwsysProcess_s kwsys_ns(Process_s) +# define kwsysProcess_New kwsys_ns(Process_New) +# define kwsysProcess_Delete kwsys_ns(Process_Delete) +# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand) +# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand) +# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout) +# define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory) +# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile) +# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative) +# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared) +# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach) +# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow) +# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput) +# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim) +# define kwsysProcess_Option_CreateProcessGroup kwsys_ns(Process_Option_CreateProcessGroup) +# define kwsysProcess_GetOption kwsys_ns(Process_GetOption) +# define kwsysProcess_SetOption kwsys_ns(Process_SetOption) +# define kwsysProcess_Option_e kwsys_ns(Process_Option_e) +# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting) +# define kwsysProcess_State_Error kwsys_ns(Process_State_Error) +# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception) +# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing) +# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited) +# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired) +# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed) +# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned) +# define kwsysProcess_GetState kwsys_ns(Process_GetState) +# define kwsysProcess_State_e kwsys_ns(Process_State_e) +# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None) +# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault) +# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal) +# define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt) +# define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical) +# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other) +# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException) +# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e) +# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode) +# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue) +# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString) +# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString) +# define kwsysProcess_Execute kwsys_ns(Process_Execute) +# define kwsysProcess_Disown kwsys_ns(Process_Disown) +# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) +# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e) +# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None) +# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN) +# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT) +# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR) +# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout) +# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle) +# define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit) +# define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt) +# define kwsysProcess_Kill kwsys_ns(Process_Kill) #endif #if defined(__cplusplus) @@ -199,6 +201,15 @@ kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, * and ignore the rest of the arguments. * 0 = No (default) * 1 = Yes + * + * kwsysProcess_Option_CreateProcessGroup = Whether to place the process in a + * new process group. This is + * useful if you want to send Ctrl+C + * to the process. On UNIX, also + * places the process in a new + * session. + * 0 = No (default) + * 1 = Yes */ kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId); kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, @@ -208,7 +219,8 @@ enum kwsysProcess_Option_e kwsysProcess_Option_HideWindow, kwsysProcess_Option_Detach, kwsysProcess_Option_MergeOutput, - kwsysProcess_Option_Verbatim + kwsysProcess_Option_Verbatim, + kwsysProcess_Option_CreateProcessGroup }; /** @@ -363,6 +375,17 @@ enum kwsysProcess_Pipes_e kwsysEXPORT int kwsysProcess_WaitForExit(kwsysProcess* cp, double* timeout); /** + * Interrupt the process group for the child process that is currently + * running by sending it the appropriate operating-system specific signal. + * The caller should call WaitForExit after this returns to wait for the + * child to terminate. + * + * WARNING: If you didn't specify kwsysProcess_Option_CreateProcessGroup, + * you will interrupt your own process group. + */ +kwsysEXPORT void kwsysProcess_Interrupt(kwsysProcess* cp); + +/** * Forcefully terminate the child process that is currently running. * The caller should call WaitForExit after this returns to wait for * the child to terminate. @@ -394,6 +417,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); # undef kwsysProcess_Option_HideWindow # undef kwsysProcess_Option_MergeOutput # undef kwsysProcess_Option_Verbatim +# undef kwsysProcess_Option_CreateProcessGroup # undef kwsysProcess_GetOption # undef kwsysProcess_SetOption # undef kwsysProcess_Option_e @@ -430,6 +454,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); # undef kwsysProcess_Pipe_Timeout # undef kwsysProcess_Pipe_Handle # undef kwsysProcess_WaitForExit +# undef kwsysProcess_Interrupt # undef kwsysProcess_Kill # endif #endif diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 0393a6d..6d9b109 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -88,7 +88,7 @@ typedef ssize_t kwsysProcess_ssize_t; typedef int kwsysProcess_ssize_t; #endif -#if defined(__BEOS__) && !defined(__ZETA__) +#if defined(__BEOS__) && !defined(__ZETA__) /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */ # include <be/kernel/OS.h> static inline void kwsysProcess_usleep(unsigned int msec) @@ -151,6 +151,7 @@ typedef struct kwsysProcessCreateInformation_s } kwsysProcessCreateInformation; /*--------------------------------------------------------------------------*/ +static void kwsysProcessVolatileFree(volatile void* p); static int kwsysProcessInitialize(kwsysProcess* cp); static void kwsysProcessCleanup(kwsysProcess* cp, int error); static void kwsysProcessCleanupDescriptor(int* pfd); @@ -197,7 +198,7 @@ struct kwsysProcess_s { /* The command lines to execute. */ char*** Commands; - int NumberOfCommands; + volatile int NumberOfCommands; /* Descriptors for the read ends of the child's output pipes and the signal pipe. */ @@ -213,8 +214,10 @@ struct kwsysProcess_s /* Buffer for pipe data. */ char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; - /* Process IDs returned by the calls to fork. */ - pid_t* ForkPIDs; + /* Process IDs returned by the calls to fork. Everything is volatile + because the signal handler accesses them. You must be very careful + when reaping PIDs or modifying this array to avoid race conditions. */ + volatile pid_t* volatile ForkPIDs; /* Flag for whether the children were terminated by a faild select. */ int SelectError; @@ -237,6 +240,9 @@ struct kwsysProcess_s /* Whether to merge stdout/stderr of the child. */ int MergeOutput; + /* Whether to create the process in a new process group. */ + volatile sig_atomic_t CreateProcessGroup; + /* Time at which the child started. Negative for no timeout. */ kwsysProcessTime StartTime; @@ -257,8 +263,9 @@ struct kwsysProcess_s /* The number of children still executing. */ int CommandsLeft; - /* The current status of the child process. */ - int State; + /* The current status of the child process. Must be atomic because + the signal handler checks this to avoid a race. */ + volatile sig_atomic_t State; /* The exceptional behavior that terminated the child process, if * any. */ @@ -271,7 +278,7 @@ struct kwsysProcess_s int ExitValue; /* Whether the process was killed. */ - int Killed; + volatile sig_atomic_t Killed; /* Buffer for error message in case of failure. */ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; @@ -649,6 +656,8 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) case kwsysProcess_Option_Detach: return cp->OptionDetach; case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; case kwsysProcess_Option_Verbatim: return cp->Verbatim; + case kwsysProcess_Option_CreateProcessGroup: + return cp->CreateProcessGroup; default: return 0; } } @@ -666,6 +675,8 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; + case kwsysProcess_Option_CreateProcessGroup: + cp->CreateProcessGroup = value; break; default: break; } } @@ -1490,6 +1501,45 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) } /*--------------------------------------------------------------------------*/ +void kwsysProcess_Interrupt(kwsysProcess* cp) +{ + int i; + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || + cp->Killed) + { + return; + } + + /* Interrupt the children. */ + if (cp->CreateProcessGroup) + { + if(cp->ForkPIDs) + { + for(i=0; i < cp->NumberOfCommands; ++i) + { + /* Make sure the PID is still valid. */ + if(cp->ForkPIDs[i]) + { + /* The user created a process group for this process. The group ID + is the process ID for the original process in the group. */ + kill(-cp->ForkPIDs[i], SIGINT); + } + } + } + } + else + { + /* No process group was created. Kill our own process group. + NOTE: While one could argue that we could call kill(cp->ForkPIDs[i], + SIGINT) as a way to still interrupt the process even though it's not in + a special group, this is not an option on Windows. Therefore, we kill + the current process group for consistency with Windows. */ + kill(0, SIGINT); + } +} + +/*--------------------------------------------------------------------------*/ void kwsysProcess_Kill(kwsysProcess* cp) { int i; @@ -1539,10 +1589,28 @@ void kwsysProcess_Kill(kwsysProcess* cp) } /*--------------------------------------------------------------------------*/ +/* Call the free() function with a pointer to volatile without causing + compiler warnings. */ +static void kwsysProcessVolatileFree(volatile void* p) +{ + /* clang has made it impossible to free memory that points to volatile + without first using special pragmas to disable a warning... */ +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wcast-qual" +#endif + free((void*)p); /* The cast will silence most compilers, but not clang. */ +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +} + +/*--------------------------------------------------------------------------*/ /* Initialize a process control structure for kwsysProcess_Execute. */ static int kwsysProcessInitialize(kwsysProcess* cp) { int i; + volatile pid_t* oldForkPIDs; for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) { cp->PipeReadEnds[i] = -1; @@ -1571,16 +1639,21 @@ static int kwsysProcessInitialize(kwsysProcess* cp) cp->ErrorMessage[0] = 0; strcpy(cp->ExitExceptionString, "No exception"); - if(cp->ForkPIDs) + oldForkPIDs = cp->ForkPIDs; + cp->ForkPIDs = (volatile pid_t*)malloc( + sizeof(volatile pid_t)*(size_t)(cp->NumberOfCommands)); + if(oldForkPIDs) { - free(cp->ForkPIDs); + kwsysProcessVolatileFree(oldForkPIDs); } - cp->ForkPIDs = (pid_t*)malloc(sizeof(pid_t)*(size_t)(cp->NumberOfCommands)); if(!cp->ForkPIDs) { return 0; } - memset(cp->ForkPIDs, 0, sizeof(pid_t)*(size_t)(cp->NumberOfCommands)); + for(i=0; i < cp->NumberOfCommands; ++i) + { + cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */ + } if(cp->CommandExitCodes) { @@ -1671,7 +1744,7 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error) /* Free memory. */ if(cp->ForkPIDs) { - free(cp->ForkPIDs); + kwsysProcessVolatileFree(cp->ForkPIDs); cp->ForkPIDs = 0; } if(cp->RealWorkingDirectory) @@ -1758,15 +1831,49 @@ int decc$set_child_standard_streams(int fd1, int fd2, int fd3); static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, kwsysProcessCreateInformation* si) { + sigset_t mask, old_mask; + int pgidPipe[2]; + char tmp; + ssize_t readRes; + /* Create the error reporting pipe. */ if(pipe(si->ErrorPipe) < 0) { return 0; } - /* Set close-on-exec flag on the error pipe's write end. */ - if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0) + /* Create a pipe for detecting that the child process has created a process + group and session. */ + if(pipe(pgidPipe) < 0) { + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); + return 0; + } + + /* Set close-on-exec flag on the pipe's write end. */ + if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0 || + fcntl(pgidPipe[1], F_SETFD, FD_CLOEXEC) < 0) + { + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); + kwsysProcessCleanupDescriptor(&pgidPipe[0]); + kwsysProcessCleanupDescriptor(&pgidPipe[1]); + return 0; + } + + /* Block SIGINT / SIGTERM while we start. The purpose is so that our signal + handler doesn't get called from the child process after the fork and + before the exec, and subsequently start kill()'ing PIDs from ForkPIDs. */ + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) + { + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); + kwsysProcessCleanupDescriptor(&pgidPipe[0]); + kwsysProcessCleanupDescriptor(&pgidPipe[1]); return 0; } @@ -1774,13 +1881,19 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, #if defined(__VMS) /* VMS needs vfork and execvp to be in the same function because they use setjmp/longjmp to run the child startup code in the - parent! TODO: OptionDetach. */ + parent! TODO: OptionDetach. Also + TODO: CreateProcessGroup. */ cp->ForkPIDs[prIndex] = vfork(); #else cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si); #endif if(cp->ForkPIDs[prIndex] < 0) { + sigprocmask(SIG_SETMASK, &old_mask, 0); + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); + kwsysProcessCleanupDescriptor(&pgidPipe[0]); + kwsysProcessCleanupDescriptor(&pgidPipe[1]); return 0; } @@ -1790,8 +1903,10 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, /* Specify standard pipes for child process. */ decc$set_child_standard_streams(si->StdIn, si->StdOut, si->StdErr); #else - /* Close the read end of the error reporting pipe. */ + /* Close the read end of the error reporting / process group + setup pipe. */ close(si->ErrorPipe[0]); + close(pgidPipe[0]); /* Setup the stdin, stdout, and stderr pipes. */ if(si->StdIn > 0) @@ -1819,11 +1934,25 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, /* Restore all default signal handlers. */ kwsysProcessRestoreDefaultSignalHandlers(); + + /* Now that we have restored default signal handling and created the + process group, restore mask. */ + sigprocmask(SIG_SETMASK, &old_mask, 0); + + /* Create new process group. We use setsid instead of setpgid to avoid + the child getting hung up on signals like SIGTTOU. (In the real world, + this has been observed where "git svn" ends up calling the "resize" + program which opens /dev/tty. */ + if(cp->CreateProcessGroup && setsid() < 0) + { + kwsysProcessChildErrorExit(si->ErrorPipe[1]); + } #endif /* Execute the real process. If successful, this does not return. */ execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]); /* TODO: What does VMS do if the child fails to start? */ + /* TODO: On VMS, how do we put the process in a new group? */ /* Failure. Report error to parent and terminate. */ kwsysProcessChildErrorExit(si->ErrorPipe[1]); @@ -1834,12 +1963,34 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, decc$set_child_standard_streams(0, 1, 2); #endif + /* We are done with the error reporting pipe and process group setup pipe + write end. */ + kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); + kwsysProcessCleanupDescriptor(&pgidPipe[1]); + + /* Make sure the child is in the process group before we proceed. This + avoids race conditions with calls to the kill function that we make for + signalling process groups. */ + while((readRes = read(pgidPipe[0], &tmp, 1)) > 0); + if(readRes < 0) + { + sigprocmask(SIG_SETMASK, &old_mask, 0); + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + kwsysProcessCleanupDescriptor(&pgidPipe[0]); + return 0; + } + kwsysProcessCleanupDescriptor(&pgidPipe[0]); + + /* Unmask signals. */ + if(sigprocmask(SIG_SETMASK, &old_mask, 0) < 0) + { + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + return 0; + } + /* A child has been created. */ ++cp->CommandsLeft; - /* We are done with the error reporting pipe write end. */ - kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); - /* Block until the child's exec call succeeds and closes the error pipe or writes data to the pipe to report an error. */ { @@ -1877,6 +2028,17 @@ static void kwsysProcessDestroy(kwsysProcess* cp) /* A child process has terminated. Reap it if it is one handled by this object. */ int i; + /* Temporarily disable signals that access ForkPIDs. We don't want them to + read a reaped PID, and writes to ForkPIDs are not atomic. */ + sigset_t mask, old_mask; + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) + { + return; + } + for(i=0; i < cp->NumberOfCommands; ++i) { if(cp->ForkPIDs[i]) @@ -1910,6 +2072,9 @@ static void kwsysProcessDestroy(kwsysProcess* cp) } } } + + /* Re-enable signals. */ + sigprocmask(SIG_SETMASK, &old_mask, 0); } /*--------------------------------------------------------------------------*/ @@ -1938,7 +2103,7 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name) /* Assign the replacement descriptor. */ *p = fout; - return 1; + return 1; } /*--------------------------------------------------------------------------*/ @@ -2582,19 +2747,23 @@ typedef struct kwsysProcessInstances_s } kwsysProcessInstances; static kwsysProcessInstances kwsysProcesses; -/* The old SIGCHLD handler. */ +/* The old SIGCHLD / SIGINT / SIGTERM handlers. */ static struct sigaction kwsysProcessesOldSigChldAction; +static struct sigaction kwsysProcessesOldSigIntAction; +static struct sigaction kwsysProcessesOldSigTermAction; /*--------------------------------------------------------------------------*/ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) { - /* Block SIGCHLD while we update the set of pipes to check. + /* Block signals while we update the set of pipes to check. TODO: sigprocmask is undefined for threaded apps. See pthread_sigmask. */ sigset_t newset; sigset_t oldset; sigemptyset(&newset); sigaddset(&newset, SIGCHLD); + sigaddset(&newset, SIGINT); + sigaddset(&newset, SIGTERM); sigprocmask(SIG_BLOCK, &newset, &oldset); /* Store the new set in that seen by the signal handler. */ @@ -2686,21 +2855,36 @@ static int kwsysProcessesAdd(kwsysProcess* cp) { /* Install our handler for SIGCHLD. Repeat call until it is not interrupted. */ - struct sigaction newSigChldAction; - memset(&newSigChldAction, 0, sizeof(struct sigaction)); + struct sigaction newSigAction; + memset(&newSigAction, 0, sizeof(struct sigaction)); #if KWSYSPE_USE_SIGINFO - newSigChldAction.sa_sigaction = kwsysProcessesSignalHandler; - newSigChldAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; + newSigAction.sa_sigaction = kwsysProcessesSignalHandler; + newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; # ifdef SA_RESTART - newSigChldAction.sa_flags |= SA_RESTART; + newSigAction.sa_flags |= SA_RESTART; # endif #else - newSigChldAction.sa_handler = kwsysProcessesSignalHandler; - newSigChldAction.sa_flags = SA_NOCLDSTOP; + newSigAction.sa_handler = kwsysProcessesSignalHandler; + newSigAction.sa_flags = SA_NOCLDSTOP; #endif - while((sigaction(SIGCHLD, &newSigChldAction, + sigemptyset(&newSigAction.sa_mask); + while((sigaction(SIGCHLD, &newSigAction, &kwsysProcessesOldSigChldAction) < 0) && (errno == EINTR)); + + /* Install our handler for SIGINT / SIGTERM. Repeat call until + it is not interrupted. */ + sigemptyset(&newSigAction.sa_mask); + sigaddset(&newSigAction.sa_mask, SIGTERM); + while((sigaction(SIGINT, &newSigAction, + &kwsysProcessesOldSigIntAction) < 0) && + (errno == EINTR)); + + sigemptyset(&newSigAction.sa_mask); + sigaddset(&newSigAction.sa_mask, SIGINT); + while((sigaction(SIGTERM, &newSigAction, + &kwsysProcessesOldSigIntAction) < 0) && + (errno == EINTR)); } } @@ -2734,10 +2918,14 @@ static void kwsysProcessesRemove(kwsysProcess* cp) /* If this was the last process, disable the signal handler. */ if(newProcesses.Count == 0) { - /* Restore the SIGCHLD handler. Repeat call until it is not + /* Restore the signal handlers. Repeat call until it is not interrupted. */ while((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) && (errno == EINTR)); + while((sigaction(SIGINT, &kwsysProcessesOldSigIntAction, 0) < 0) && + (errno == EINTR)); + while((sigaction(SIGTERM, &kwsysProcessesOldSigTermAction, 0) < 0) && + (errno == EINTR)); /* Free the table of process pointers since it is now empty. This is safe because the signal handler has been removed. */ @@ -2763,39 +2951,108 @@ static void kwsysProcessesSignalHandler(int signum #endif ) { - (void)signum; + int i, j, procStatus, old_errno = errno; #if KWSYSPE_USE_SIGINFO (void)info; (void)ucontext; #endif /* Signal all process objects that a child has terminated. */ - { - int i; - for(i=0; i < kwsysProcesses.Count; ++i) + switch(signum) { - /* Set the pipe in a signalled state. */ - char buf = 1; - kwsysProcess* cp = kwsysProcesses.Processes[i]; - kwsysProcess_ssize_t status= - read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1); - (void)status; - status=write(cp->SignalPipe, &buf, 1); - (void)status; + case SIGCHLD: + for(i=0; i < kwsysProcesses.Count; ++i) + { + /* Set the pipe in a signalled state. */ + char buf = 1; + kwsysProcess* cp = kwsysProcesses.Processes[i]; + kwsysProcess_ssize_t pipeStatus= + read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1); + (void)pipeStatus; + pipeStatus=write(cp->SignalPipe, &buf, 1); + (void)pipeStatus; + } + break; + case SIGINT: + case SIGTERM: + /* Signal child processes that are running in new process groups. */ + for(i=0; i < kwsysProcesses.Count; ++i) + { + kwsysProcess* cp = kwsysProcesses.Processes[i]; + /* Check Killed to avoid data race condition when killing. + Check State to avoid data race condition in kwsysProcessCleanup + when there is an error (it leaves a reaped PID). */ + if(cp->CreateProcessGroup && !cp->Killed && + cp->State != kwsysProcess_State_Error && cp->ForkPIDs) + { + for(j=0; j < cp->NumberOfCommands; ++j) + { + /* Make sure the PID is still valid. */ + if(cp->ForkPIDs[j]) + { + /* The user created a process group for this process. The group ID + is the process ID for the original process in the group. */ + kill(-cp->ForkPIDs[j], SIGINT); + } + } + } + } + + /* Wait for all processes to terminate. */ + while(wait(&procStatus) >= 0 || errno != ECHILD) + { + } + + /* Terminate the process, which is now in an inconsistent state + because we reaped all the PIDs that it may have been reaping + or may have reaped in the future. Reraise the signal so that + the proper exit code is returned. */ + { + /* Install default signal handler. */ + struct sigaction defSigAction; + sigset_t unblockSet; + memset(&defSigAction, 0, sizeof(defSigAction)); + defSigAction.sa_handler = SIG_DFL; + sigemptyset(&defSigAction.sa_mask); + while((sigaction(signum, &defSigAction, 0) < 0) && + (errno == EINTR)); + /* Unmask the signal. */ + sigemptyset(&unblockSet); + sigaddset(&unblockSet, signum); + sigprocmask(SIG_UNBLOCK, &unblockSet, 0); + /* Raise the signal again. */ + raise(signum); + /* We shouldn't get here... but if we do... */ + _exit(1); + } + /* break omitted to silence unreachable code clang compiler warning. */ } - } #if !KWSYSPE_USE_SIGINFO - /* Re-Install our handler for SIGCHLD. Repeat call until it is not - interrupted. */ + /* Re-Install our handler. Repeat call until it is not interrupted. */ { - struct sigaction newSigChldAction; - memset(&newSigChldAction, 0, sizeof(struct sigaction)); + struct sigaction newSigAction; + struct sigaction &oldSigAction; + memset(&newSigAction, 0, sizeof(struct sigaction)); newSigChldAction.sa_handler = kwsysProcessesSignalHandler; newSigChldAction.sa_flags = SA_NOCLDSTOP; - while((sigaction(SIGCHLD, &newSigChldAction, - &kwsysProcessesOldSigChldAction) < 0) && + sigemptyset(&newSigAction.sa_mask); + switch(signum) + { + case SIGCHLD: oldSigAction = &kwsysProcessesOldSigChldAction; break; + case SIGINT: + sigaddset(&newSigAction.sa_mask, SIGTERM); + oldSigAction = &kwsysProcessesOldSigIntAction; break; + case SIGTERM: + sigaddset(&newSigAction.sa_mask, SIGINT); + oldSigAction = &kwsysProcessesOldSigTermAction; break; + default: return 0; + } + while((sigaction(signum, &newSigAction, + oldSigAction) < 0) && (errno == EINTR)); } #endif + + errno = old_errno; } diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index f630171..1f8749f 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -11,14 +11,12 @@ ============================================================================*/ #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) -#include KWSYS_HEADER(System.h) #include KWSYS_HEADER(Encoding.h) /* Work-around CMake dependency scanning limitation. This must duplicate the above list of headers. */ #if 0 # include "Process.h.in" -# include "System.h.in" # include "Encoding_c.h.in" #endif @@ -111,20 +109,16 @@ static DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd); static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td); static int kwsysProcessInitialize(kwsysProcess* cp); -static int kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si); +static DWORD kwsysProcessCreate(kwsysProcess* cp, int index, + kwsysProcessCreateInformation* si); static void kwsysProcessDestroy(kwsysProcess* cp, int event); -static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name); +static DWORD kwsysProcessSetupOutputPipeFile(PHANDLE handle, + const char* name); static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle); static void kwsysProcessCleanupHandle(PHANDLE h); -static void kwsysProcessCleanup(kwsysProcess* cp, int error); +static void kwsysProcessCleanup(kwsysProcess* cp, DWORD error); static void kwsysProcessCleanErrorMessage(kwsysProcess* cp); -static int kwsysProcessComputeCommandLength(kwsysProcess* cp, - char const* const* command); -static void kwsysProcessComputeCommandLine(kwsysProcess* cp, - char const* const* command, - char* cmd); static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, kwsysProcessTime* timeoutTime); static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, @@ -140,6 +134,13 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc static void kwsysProcessSetExitException(kwsysProcess* cp, int code); static void kwsysProcessKillTree(int pid); static void kwsysProcessDisablePipeThreads(kwsysProcess* cp); +static int kwsysProcessesInitialize(void); +static int kwsysTryEnterCreateProcessSection(void); +static void kwsysLeaveCreateProcessSection(void); +static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId, + int newProcessGroup); +static void kwsysProcessesRemove(HANDLE hProcess); +static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType); /*--------------------------------------------------------------------------*/ /* A structure containing synchronization data for each thread. */ @@ -229,6 +230,9 @@ struct kwsysProcess_s /* Whether to merge stdout/stderr of the child. */ int MergeOutput; + /* Whether to create the process in a new process group. */ + int CreateProcessGroup; + /* Mutex to protect the shared index used by threads to report data. */ HANDLE SharedIndexMutex; @@ -328,6 +332,16 @@ kwsysProcess* kwsysProcess_New(void) /* Windows version number data. */ OSVERSIONINFO osv; + /* Initialize list of processes before we get any farther. It's especially + important that the console Ctrl handler be added BEFORE starting the + first process. This prevents the risk of an orphaned process being + started by the main thread while the default Ctrl handler is in + progress. */ + if(!kwsysProcessesInitialize()) + { + return 0; + } + /* Allocate a process control structure. */ cp = (kwsysProcess*)malloc(sizeof(kwsysProcess)); if(!cp) @@ -602,37 +616,69 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) } } - /* We need to construct a single string representing the command - and its arguments. We will surround each argument containing - spaces with double-quotes. Inside a double-quoted argument, we - need to escape double-quotes and all backslashes before them. - We also need to escape backslashes at the end of an argument - because they come before the closing double-quote for the - argument. */ - { - /* First determine the length of the final string. */ - int length = kwsysProcessComputeCommandLength(cp, command); - - /* Allocate enough space for the command. We do not need an extra - byte for the terminating null because we allocated a space for - the first argument that we will not use. */ - char* new_cmd = malloc(length); - if(!new_cmd) + if (cp->Verbatim) { - /* Out of memory. */ + /* Copy the verbatim command line into the buffer. */ + newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(*command); + } + else + { + /* Encode the arguments so CommandLineToArgvW can decode + them from the command line string in the child. */ + char buffer[32768]; /* CreateProcess max command-line length. */ + char* end = buffer + sizeof(buffer); + char* out = buffer; + char const* const* a; + for (a = command; *a; ++a) + { + int quote = !**a; /* Quote the empty string. */ + int slashes = 0; + char const* c; + if (a != command && out != end) { *out++ = ' '; } + for (c = *a; !quote && *c; ++c) + { quote = (*c == ' ' || *c == '\t'); } + if (quote && out != end) { *out++ = '"'; } + for (c = *a; *c; ++c) + { + if (*c == '\\') + { + ++slashes; + } + else + { + if (*c == '"') + { + // Add n+1 backslashes to total 2n+1 before internal '"'. + while(slashes-- >= 0 && out != end) { *out++ = '\\'; } + } + slashes = 0; + } + if (out != end) { *out++ = *c; } + } + if (quote) + { + // Add n backslashes to total 2n before ending '"'. + while (slashes-- > 0 && out != end) { *out++ = '\\'; } + if (out != end) { *out++ = '"'; } + } + } + if(out != end) + { + *out = '\0'; + newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(buffer); + } + else + { + newCommands[cp->NumberOfCommands] = 0; + } + } + if (!newCommands[cp->NumberOfCommands]) + { + /* Out of memory or command line too long. */ free(newCommands); return 0; } - /* Construct the command line in the allocated buffer. */ - kwsysProcessComputeCommandLine(cp, command, - new_cmd); - - newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(new_cmd); - free(new_cmd); - } - - /* Save the new array of commands. */ free(cp->Commands); cp->Commands = newCommands; @@ -811,6 +857,8 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) case kwsysProcess_Option_HideWindow: return cp->HideWindow; case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; case kwsysProcess_Option_Verbatim: return cp->Verbatim; + case kwsysProcess_Option_CreateProcessGroup: + return cp->CreateProcessGroup; default: return 0; } } @@ -829,6 +877,8 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break; case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; + case kwsysProcess_Option_CreateProcessGroup: + cp->CreateProcessGroup = value; break; default: break; } } @@ -920,7 +970,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) if(!GetCurrentDirectoryW(cp->RealWorkingDirectoryLength, cp->RealWorkingDirectory)) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, GetLastError()); return; } SetCurrentDirectoryW(cp->WorkingDirectory); @@ -932,14 +982,16 @@ void kwsysProcess_Execute(kwsysProcess* cp) { /* Create a handle to read a file for stdin. */ wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); + DWORD error; cp->PipeChildStd[0] = CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + error = GetLastError(); /* Check now in case free changes this. */ free(wstdin); if(cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, error); return; } } @@ -965,17 +1017,18 @@ void kwsysProcess_Execute(kwsysProcess* cp) if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDOUT].Read, &cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, 0, 0)) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, GetLastError()); return; } if(cp->PipeFileSTDOUT) { /* Use a file for stdout. */ - if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], - cp->PipeFileSTDOUT)) + DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], + cp->PipeFileSTDOUT); + if(error) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, error); return; } } @@ -998,7 +1051,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) GetCurrentProcess(), &cp->PipeChildStd[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, GetLastError()); return; } } @@ -1009,17 +1062,18 @@ void kwsysProcess_Execute(kwsysProcess* cp) if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, GetLastError()); return; } if(cp->PipeFileSTDERR) { /* Use a file for stderr. */ - if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], - cp->PipeFileSTDERR)) + DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], + cp->PipeFileSTDERR); + if(error) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, error); return; } } @@ -1042,7 +1096,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) GetCurrentProcess(), &cp->PipeChildStd[2], 0, FALSE, DUPLICATE_SAME_ACCESS)) { - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, GetLastError()); return; } } @@ -1081,11 +1135,12 @@ void kwsysProcess_Execute(kwsysProcess* cp) HANDLE p[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; if (!CreatePipe(&p[0], &p[1], 0, 0)) { + DWORD error = GetLastError(); if (nextStdInput != cp->PipeChildStd[0]) { kwsysProcessCleanupHandle(&nextStdInput); } - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, error); return; } nextStdInput = p[0]; @@ -1094,7 +1149,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) si.hStdError = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; { - int res = kwsysProcessCreate(cp, i, &si); + DWORD error = kwsysProcessCreate(cp, i, &si); /* Close our copies of pipes used between children. */ if (si.hStdInput != cp->PipeChildStd[0]) @@ -1109,7 +1164,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) { kwsysProcessCleanupHandle(&si.hStdError); } - if (res) + if (!error) { cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess; } @@ -1119,7 +1174,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) { kwsysProcessCleanupHandle(&nextStdInput); } - kwsysProcessCleanup(cp, 1); + kwsysProcessCleanup(cp, error); return; } } @@ -1435,6 +1490,52 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) } /*--------------------------------------------------------------------------*/ +void kwsysProcess_Interrupt(kwsysProcess* cp) +{ + int i; + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || + cp->Killed) + { + KWSYSPE_DEBUG((stderr, "interrupt: child not executing\n")); + return; + } + + /* Skip actually interrupting the child if it has already terminated. */ + if(cp->Terminated) + { + KWSYSPE_DEBUG((stderr, "interrupt: child already terminated\n")); + return; + } + + /* Interrupt the children. */ + if (cp->CreateProcessGroup) + { + if(cp->ProcessInformation) + { + for(i=0; i < cp->NumberOfCommands; ++i) + { + /* Make sure the process handle isn't closed (e.g. from disowning). */ + if(cp->ProcessInformation[i].hProcess) + { + /* The user created a process group for this process. The group ID + is the process ID for the original process in the group. Note + that we have to use Ctrl+Break: Ctrl+C is not allowed for process + groups. */ + GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, + cp->ProcessInformation[i].dwProcessId); + } + } + } + } + else + { + /* No process group was created. Kill our own process group... */ + GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0); + } +} + +/*--------------------------------------------------------------------------*/ void kwsysProcess_Kill(kwsysProcess* cp) { int i; @@ -1462,7 +1563,8 @@ void kwsysProcess_Kill(kwsysProcess* cp) for(i=0; i < cp->NumberOfCommands; ++i) { kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); - // close the handle if we kill it + /* Remove from global list of processes and close handles. */ + kwsysProcessesRemove(cp->ProcessInformation[i].hProcess); kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); } @@ -1661,7 +1763,7 @@ int kwsysProcessInitialize(kwsysProcess* cp) } /*--------------------------------------------------------------------------*/ -static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) +static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) { DWORD flags; @@ -1672,13 +1774,19 @@ static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) if (flags & HANDLE_FLAG_INHERIT) { *out = in; - return 1; + return ERROR_SUCCESS; } /* Create an inherited copy of this handle. */ - return DuplicateHandle(GetCurrentProcess(), in, - GetCurrentProcess(), out, - 0, TRUE, DUPLICATE_SAME_ACCESS); + if (DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), out, + 0, TRUE, DUPLICATE_SAME_ACCESS)) + { + return ERROR_SUCCESS; + } + else + { + return GetLastError(); + } } else { @@ -1694,29 +1802,46 @@ static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) (GENERIC_WRITE | FILE_READ_ATTRIBUTES)), FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, 0); - return *out != INVALID_HANDLE_VALUE; + return (*out != INVALID_HANDLE_VALUE) ? ERROR_SUCCESS : GetLastError(); } - } /*--------------------------------------------------------------------------*/ -int kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si) +DWORD kwsysProcessCreate(kwsysProcess* cp, int index, + kwsysProcessCreateInformation* si) { - int res = + DWORD creationFlags; + DWORD error = ERROR_SUCCESS; - /* Create inherited copies the handles. */ - kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput, - si->hStdInput, 1) && - kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput, - si->hStdOutput, 0) && - kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError, - si->hStdError, 0) && + /* Check if we are currently exiting. */ + if (!kwsysTryEnterCreateProcessSection()) + { + /* The Ctrl handler is currently working on exiting our process. Rather + than return an error code, which could cause incorrect conclusions to be + reached by the caller, we simply hang. (For example, a CMake try_run + configure step might cause the project to configure wrong.) */ + Sleep(INFINITE); + } + + /* Create the child in a suspended state so we can wait until all + children have been created before running any one. */ + creationFlags = CREATE_SUSPENDED; + if (cp->CreateProcessGroup) + { + creationFlags |= CREATE_NEW_PROCESS_GROUP; + } - /* Create the child in a suspended state so we can wait until all - children have been created before running any one. */ - CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, - 0, &si->StartupInfo, &cp->ProcessInformation[index]); + /* Create inherited copies of the handles. */ + (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput, + si->hStdInput, 1)) || + (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput, + si->hStdOutput, 0)) || + (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError, + si->hStdError, 0)) || + /* Create the process. */ + (!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, creationFlags, 0, + 0, &si->StartupInfo, &cp->ProcessInformation[index]) && + (error = GetLastError())); /* Close the inherited copies of the handles. */ if (si->StartupInfo.hStdInput != si->hStdInput) @@ -1732,7 +1857,23 @@ int kwsysProcessCreate(kwsysProcess* cp, int index, kwsysProcessCleanupHandle(&si->StartupInfo.hStdError); } - return res; + /* Add the process to the global list of processes. */ + if (!error && + !kwsysProcessesAdd(cp->ProcessInformation[index].hProcess, + cp->ProcessInformation[index].dwProcessId, cp->CreateProcessGroup)) + { + /* This failed for some reason. Kill the suspended process. */ + TerminateProcess(cp->ProcessInformation[index].hProcess, 1); + /* And clean up... */ + kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); + kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread); + strcpy(cp->ErrorMessage, "kwsysProcessesAdd function failed"); + error = ERROR_NOT_ENOUGH_MEMORY; /* Most likely reason. */ + } + + /* If the console Ctrl handler is waiting for us, this will release it... */ + kwsysLeaveCreateProcessSection(); + return error; } /*--------------------------------------------------------------------------*/ @@ -1754,6 +1895,9 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event) GetExitCodeProcess(cp->ProcessInformation[index].hProcess, &cp->CommandExitCodes[index]); + /* Remove from global list of processes. */ + kwsysProcessesRemove(cp->ProcessInformation[index].hProcess); + /* Close the process handle for the terminated process. */ kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); @@ -1788,13 +1932,14 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event) } /*--------------------------------------------------------------------------*/ -int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) +DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) { HANDLE fout; wchar_t* wname; + DWORD error; if(!name) { - return 1; + return ERROR_INVALID_PARAMETER; } /* Close the existing handle. */ @@ -1804,15 +1949,16 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) wname = kwsysEncoding_DupToWide(name); fout = CreateFileW(wname, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); + error = GetLastError(); free(wname); if(fout == INVALID_HANDLE_VALUE) { - return 0; + return error; } /* Assign the replacement handle. */ *phandle = fout; - return 1; + return ERROR_SUCCESS; } /*--------------------------------------------------------------------------*/ @@ -1851,7 +1997,7 @@ void kwsysProcessCleanupHandle(PHANDLE h) /*--------------------------------------------------------------------------*/ /* Close all handles created by kwsysProcess_Execute. */ -void kwsysProcessCleanup(kwsysProcess* cp, int error) +void kwsysProcessCleanup(kwsysProcess* cp, DWORD error) { int i; /* If this is an error case, report the error. */ @@ -1861,21 +2007,27 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) if(cp->ErrorMessage[0] == 0) { /* Format the error message. */ - DWORD original = GetLastError(); wchar_t err_msg[KWSYSPE_PIPE_BUFFER_SIZE]; DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, 0, original, + FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_msg, KWSYSPE_PIPE_BUFFER_SIZE, 0); - WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage, - KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL); if(length < 1) { /* FormatMessage failed. Use a default message. */ _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, "Process execution failed with error 0x%X. " "FormatMessage failed with error 0x%X", - original, GetLastError()); + error, GetLastError()); + } + if(!WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage, + KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL)) + { + /* WideCharToMultiByte failed. Use a default message. */ + _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, + "Process execution failed with error 0x%X. " + "WideCharToMultiByte failed with error 0x%X", + error, GetLastError()); } } @@ -1898,6 +2050,8 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) } for(i=0; i < cp->NumberOfCommands; ++i) { + /* Remove from global list of processes and close handles. */ + kwsysProcessesRemove(cp->ProcessInformation[i].hProcess); kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); } @@ -1962,66 +2116,6 @@ void kwsysProcessCleanErrorMessage(kwsysProcess* cp) } /*--------------------------------------------------------------------------*/ -int kwsysProcessComputeCommandLength(kwsysProcess* cp, - char const* const* command) -{ - int length = 0; - if(cp->Verbatim) - { - /* Treat the first argument as a verbatim command line. Use its - length directly and add space for the null-terminator. */ - length = (int)strlen(*command)+1; - } - else - { - /* Compute the length of the command line when it is converted to - a single string. Space for the null-terminator is allocated by - the whitespace character allocated for the first argument that - will not be used. */ - char const* const* arg; - for(arg = command; *arg; ++arg) - { - /* Add the length of this argument. It already includes room - for a separating space or terminating null. */ - length += kwsysSystem_Shell_GetArgumentSizeForWindows(*arg, 0); - } - } - - return length; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcessComputeCommandLine(kwsysProcess* cp, - char const* const* command, - char* cmd) -{ - if(cp->Verbatim) - { - /* Copy the verbatim command line into the buffer. */ - strcpy(cmd, *command); - } - else - { - /* Construct the command line in the allocated buffer. */ - char const* const* arg; - for(arg = command; *arg; ++arg) - { - /* Add the separating space if this is not the first argument. */ - if(arg != command) - { - *cmd++ = ' '; - } - - /* Add the current argument. */ - cmd = kwsysSystem_Shell_GetArgumentForWindows(*arg, cmd, 0); - } - - /* Add the terminating null character to the command line. */ - *cmd = 0; - } -} - -/*--------------------------------------------------------------------------*/ /* Get the time at which either the process or user timeout will expire. Returns 1 if the user timeout is first, and 0 otherwise. */ int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, @@ -2694,3 +2788,230 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp) ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); } } + +/*--------------------------------------------------------------------------*/ +/* Global set of executing processes for use by the Ctrl handler. + This global instance will be zero-initialized by the compiler. + + Note that the console Ctrl handler runs on a background thread and so + everything it does must be thread safe. Here, we track the hProcess + HANDLEs directly instead of kwsysProcess instances, so that we don't have + to make kwsysProcess thread safe. */ +typedef struct kwsysProcessInstance_s +{ + HANDLE hProcess; + DWORD dwProcessId; + int NewProcessGroup; /* Whether the process was created in a new group. */ +} kwsysProcessInstance; + +typedef struct kwsysProcessInstances_s +{ + /* Whether we have initialized key fields below, like critical sections. */ + int Initialized; + + /* Ctrl handler runs on a different thread, so we must sync access. */ + CRITICAL_SECTION Lock; + + int Exiting; + size_t Count; + size_t Size; + kwsysProcessInstance* Processes; +} kwsysProcessInstances; +static kwsysProcessInstances kwsysProcesses; + +/*--------------------------------------------------------------------------*/ +/* Initialize critial section and set up console Ctrl handler. You MUST call + this before using any other kwsysProcesses* functions below. */ +static int kwsysProcessesInitialize(void) +{ + /* Initialize everything if not done already. */ + if(!kwsysProcesses.Initialized) + { + InitializeCriticalSection(&kwsysProcesses.Lock); + + /* Set up console ctrl handler. */ + if(!SetConsoleCtrlHandler(kwsysCtrlHandler, TRUE)) + { + return 0; + } + + kwsysProcesses.Initialized = 1; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +/* The Ctrl handler waits on the global list of processes. To prevent an + orphaned process, do not create a new process if the Ctrl handler is + already running. Do so by using this function to check if it is ok to + create a process. */ +static int kwsysTryEnterCreateProcessSection(void) +{ + /* Enter main critical section; this means creating a process and the Ctrl + handler are mutually exclusive. */ + EnterCriticalSection(&kwsysProcesses.Lock); + /* Indicate to the caller if they can create a process. */ + if(kwsysProcesses.Exiting) + { + LeaveCriticalSection(&kwsysProcesses.Lock); + return 0; + } + else + { + return 1; + } +} + +/*--------------------------------------------------------------------------*/ +/* Matching function on successful kwsysTryEnterCreateProcessSection return. + Make sure you called kwsysProcessesAdd if applicable before calling this.*/ +static void kwsysLeaveCreateProcessSection(void) +{ + LeaveCriticalSection(&kwsysProcesses.Lock); +} + +/*--------------------------------------------------------------------------*/ +/* Add new process to global process list. The Ctrl handler will wait for + the process to exit before it returns. Do not close the process handle + until after calling kwsysProcessesRemove. The newProcessGroup parameter + must be set if the process was created with CREATE_NEW_PROCESS_GROUP. */ +static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid, + int newProcessGroup) +{ + if(!kwsysProcessesInitialize() || !hProcess || + hProcess == INVALID_HANDLE_VALUE) + { + return 0; + } + + /* Enter the critical section. */ + EnterCriticalSection(&kwsysProcesses.Lock); + + /* Make sure there is enough space for the new process handle. */ + if(kwsysProcesses.Count == kwsysProcesses.Size) + { + size_t newSize; + kwsysProcessInstance *newArray; + /* Start with enough space for a small number of process handles + and double the size each time more is needed. */ + newSize = kwsysProcesses.Size? kwsysProcesses.Size*2 : 4; + + /* Try allocating the new block of memory. */ + if(newArray = (kwsysProcessInstance*)malloc( + newSize*sizeof(kwsysProcessInstance))) + { + /* Copy the old process handles to the new memory. */ + if(kwsysProcesses.Count > 0) + { + memcpy(newArray, kwsysProcesses.Processes, + kwsysProcesses.Count * sizeof(kwsysProcessInstance)); + } + } + else + { + /* Failed to allocate memory for the new process handle set. */ + LeaveCriticalSection(&kwsysProcesses.Lock); + return 0; + } + + /* Free original array. */ + free(kwsysProcesses.Processes); + + /* Update original structure with new allocation. */ + kwsysProcesses.Size = newSize; + kwsysProcesses.Processes = newArray; + } + + /* Append the new process information to the set. */ + kwsysProcesses.Processes[kwsysProcesses.Count].hProcess = hProcess; + kwsysProcesses.Processes[kwsysProcesses.Count].dwProcessId = dwProcessid; + kwsysProcesses.Processes[kwsysProcesses.Count++].NewProcessGroup = + newProcessGroup; + + /* Leave critical section and return success. */ + LeaveCriticalSection(&kwsysProcesses.Lock); + + return 1; +} + +/*--------------------------------------------------------------------------*/ +/* Removes process to global process list. */ +static void kwsysProcessesRemove(HANDLE hProcess) +{ + size_t i; + + if (!hProcess || hProcess == INVALID_HANDLE_VALUE) + { + return; + } + + EnterCriticalSection(&kwsysProcesses.Lock); + + /* Find the given process in the set. */ + for(i=0; i < kwsysProcesses.Count; ++i) + { + if(kwsysProcesses.Processes[i].hProcess == hProcess) + { + break; + } + } + if(i < kwsysProcesses.Count) + { + /* Found it! Remove the process from the set. */ + --kwsysProcesses.Count; + for(; i < kwsysProcesses.Count; ++i) + { + kwsysProcesses.Processes[i] = kwsysProcesses.Processes[i+1]; + } + + /* If this was the last process, free the array. */ + if(kwsysProcesses.Count == 0) + { + kwsysProcesses.Size = 0; + free(kwsysProcesses.Processes); + kwsysProcesses.Processes = 0; + } + } + + LeaveCriticalSection(&kwsysProcesses.Lock); +} + +/*--------------------------------------------------------------------------*/ +static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType) +{ + size_t i; + (void)dwCtrlType; + /* Enter critical section. */ + EnterCriticalSection(&kwsysProcesses.Lock); + + /* Set flag indicating that we are exiting. */ + kwsysProcesses.Exiting = 1; + + /* If some of our processes were created in a new process group, we must + manually interrupt them. They won't otherwise receive a Ctrl+C/Break. */ + for(i=0; i < kwsysProcesses.Count; ++i) + { + if(kwsysProcesses.Processes[i].NewProcessGroup) + { + DWORD groupId = kwsysProcesses.Processes[i].dwProcessId; + if(groupId) + { + GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, groupId); + } + } + } + + /* Wait for each child process to exit. This is the key step that prevents + us from leaving several orphaned children processes running in the + background when the user presses Ctrl+C. */ + for(i=0; i < kwsysProcesses.Count; ++i) + { + WaitForSingleObject(kwsysProcesses.Processes[i].hProcess, INFINITE); + } + + /* Leave critical section. */ + LeaveCriticalSection(&kwsysProcesses.Lock); + + /* Continue on to default Ctrl handler (which calls ExitProcess). */ + return FALSE; +} diff --git a/Source/kwsys/System.c b/Source/kwsys/System.c index 1ee26fa..ccc7e81 100644 --- a/Source/kwsys/System.c +++ b/Source/kwsys/System.c @@ -20,8 +20,8 @@ #include <stddef.h> /* ptrdiff_t */ #include <stdlib.h> /* malloc, free */ -#include <string.h> /* strlen */ -#include <ctype.h> /* isalpha */ +#include <string.h> /* memcpy */ +#include <ctype.h> /* isspace */ #include <stdio.h> @@ -31,587 +31,6 @@ typedef ptrdiff_t kwsysSystem_ptrdiff_t; typedef int kwsysSystem_ptrdiff_t; #endif -/* - -Notes: - -Make variable replacements open a can of worms. Sometimes they should -be quoted and sometimes not. Sometimes their replacement values are -already quoted. - -VS variables cause problems. In order to pass the referenced value -with spaces the reference must be quoted. If the variable value ends -in a backslash then it will escape the ending quote! In order to make -the ending backslash appear we need this: - - "$(InputDir)\" - -However if there is not a trailing backslash then this will put a -quote in the value so we need: - - "$(InputDir)" - -Make variable references are platform specific so we should probably -just NOT quote them and let the listfile author deal with it. - -*/ - -/* -TODO: For windows echo: - -To display a pipe (|) or redirection character (< or >) when using the -echo command, use a caret character immediately before the pipe or -redirection character (for example, ^>, ^<, or ^| ). If you need to -use the caret character itself (^), use two in a row (^^). -*/ - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__CharIsWhitespace(char c) -{ - return ((c == ' ') || (c == '\t')); -} - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__CharNeedsQuotesOnUnix(char c) -{ - return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') || - (c == '&') || (c == '$') || (c == '(') || (c == ')') || - (c == '~') || (c == '<') || (c == '>') || (c == '|') || - (c == '*') || (c == '^') || (c == '\\')); -} - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__CharNeedsQuotesOnWindows(char c) -{ - return ((c == '\'') || (c == '#') || (c == '&') || - (c == '<') || (c == '>') || (c == '|') || (c == '^')); -} - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__CharNeedsQuotes(char c, int isUnix, int flags) -{ - /* On Windows the built-in command shell echo never needs quotes. */ - if(!isUnix && (flags & kwsysSystem_Shell_Flag_EchoWindows)) - { - return 0; - } - - /* On all platforms quotes are needed to preserve whitespace. */ - if(kwsysSystem_Shell__CharIsWhitespace(c)) - { - return 1; - } - - if(isUnix) - { - /* On UNIX several special characters need quotes to preserve them. */ - if(kwsysSystem_Shell__CharNeedsQuotesOnUnix(c)) - { - return 1; - } - } - else - { - /* On Windows several special characters need quotes to preserve them. */ - if(kwsysSystem_Shell__CharNeedsQuotesOnWindows(c)) - { - return 1; - } - } - return 0; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__CharIsMakeVariableName(char c) -{ - return c && (c == '_' || isalpha(((int)c))); -} - -/*--------------------------------------------------------------------------*/ -static const char* kwsysSystem_Shell__SkipMakeVariables(const char* c) -{ - while(*c == '$' && *(c+1) == '(') - { - const char* skip = c+2; - while(kwsysSystem_Shell__CharIsMakeVariableName(*skip)) - { - ++skip; - } - if(*skip == ')') - { - c = skip+1; - } - else - { - break; - } - } - return c; -} - -/* -Allowing make variable replacements opens a can of worms. Sometimes -they should be quoted and sometimes not. Sometimes their replacement -values are already quoted or contain escapes. - -Some Visual Studio variables cause problems. In order to pass the -referenced value with spaces the reference must be quoted. If the -variable value ends in a backslash then it will escape the ending -quote! In order to make the ending backslash appear we need this: - - "$(InputDir)\" - -However if there is not a trailing backslash then this will put a -quote in the value so we need: - - "$(InputDir)" - -This macro decides whether we quote an argument just because it -contains a make variable reference. This should be replaced with a -flag later when we understand applications of this better. -*/ -#define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0 - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__ArgumentNeedsQuotes(const char* in, int isUnix, - int flags) -{ - /* The empty string needs quotes. */ - if(!*in) - { - return 1; - } - - /* Scan the string for characters that require quoting. */ - { - const char* c; - for(c=in; *c; ++c) - { - /* Look for $(MAKEVAR) syntax if requested. */ - if(flags & kwsysSystem_Shell_Flag_AllowMakeVariables) - { -#if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES - const char* skip = kwsysSystem_Shell__SkipMakeVariables(c); - if(skip != c) - { - /* We need to quote make variable references to preserve the - string with contents substituted in its place. */ - return 1; - } -#else - /* Skip over the make variable references if any are present. */ - c = kwsysSystem_Shell__SkipMakeVariables(c); - - /* Stop if we have reached the end of the string. */ - if(!*c) - { - break; - } -#endif - } - - /* Check whether this character needs quotes. */ - if(kwsysSystem_Shell__CharNeedsQuotes(*c, isUnix, flags)) - { - return 1; - } - } - } - - /* On Windows some single character arguments need quotes. */ - if(!isUnix && *in && !*(in+1)) - { - char c = *in; - if((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) - { - return 1; - } - } - - return 0; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem_Shell__GetArgumentSize(const char* in, - int isUnix, int flags) -{ - /* Start with the length of the original argument, plus one for - either a terminating null or a separating space. */ - int size = (int)strlen(in) + 1; - - /* String iterator. */ - const char* c; - - /* Keep track of how many backslashes have been encountered in a row. */ - int windows_backslashes = 0; - - /* Scan the string for characters that require escaping or quoting. */ - for(c=in; *c; ++c) - { - /* Look for $(MAKEVAR) syntax if requested. */ - if(flags & kwsysSystem_Shell_Flag_AllowMakeVariables) - { - /* Skip over the make variable references if any are present. */ - c = kwsysSystem_Shell__SkipMakeVariables(c); - - /* Stop if we have reached the end of the string. */ - if(!*c) - { - break; - } - } - - /* Check whether this character needs escaping for the shell. */ - if(isUnix) - { - /* On Unix a few special characters need escaping even inside a - quoted argument. */ - if(*c == '\\' || *c == '"' || *c == '`' || *c == '$') - { - /* This character needs a backslash to escape it. */ - ++size; - } - } - else if(flags & kwsysSystem_Shell_Flag_EchoWindows) - { - /* On Windows the built-in command shell echo never needs escaping. */ - } - else - { - /* On Windows only backslashes and double-quotes need escaping. */ - if(*c == '\\') - { - /* Found a backslash. It may need to be escaped later. */ - ++windows_backslashes; - } - else if(*c == '"') - { - /* Found a double-quote. We need to escape it and all - immediately preceding backslashes. */ - size += windows_backslashes + 1; - windows_backslashes = 0; - } - else - { - /* Found another character. This eliminates the possibility - that any immediately preceding backslashes will be - escaped. */ - windows_backslashes = 0; - } - } - - /* Check whether this character needs escaping for a make tool. */ - if(*c == '$') - { - if(flags & kwsysSystem_Shell_Flag_Make) - { - /* In Makefiles a dollar is written $$ so we need one extra - character. */ - ++size; - } - else if(flags & kwsysSystem_Shell_Flag_VSIDE) - { - /* In a VS IDE a dollar is written "$" so we need two extra - characters. */ - size += 2; - } - } - else if(*c == '#') - { - if((flags & kwsysSystem_Shell_Flag_Make) && - (flags & kwsysSystem_Shell_Flag_WatcomWMake)) - { - /* In Watcom WMake makefiles a pound is written $# so we need - one extra character. */ - ++size; - } - } - else if(*c == '%') - { - if((flags & kwsysSystem_Shell_Flag_VSIDE) || - ((flags & kwsysSystem_Shell_Flag_Make) && - ((flags & kwsysSystem_Shell_Flag_MinGWMake) || - (flags & kwsysSystem_Shell_Flag_NMake)))) - { - /* In the VS IDE, NMake, or MinGW make a percent is written %% - so we need one extra characters. */ - size += 1; - } - } - else if(*c == ';') - { - if(flags & kwsysSystem_Shell_Flag_VSIDE) - { - /* In a VS IDE a semicolon is written ";" so we need two extra - characters. */ - size += 2; - } - } - } - - /* Check whether the argument needs surrounding quotes. */ - if(kwsysSystem_Shell__ArgumentNeedsQuotes(in, isUnix, flags)) - { - /* Surrounding quotes are needed. Allocate space for them. */ - if((flags & kwsysSystem_Shell_Flag_WatcomQuote) && (isUnix)) - { - size += 2; - } - size += 2; - - /* We must escape all ending backslashes when quoting on windows. */ - size += windows_backslashes; - } - - return size; -} - -/*--------------------------------------------------------------------------*/ -static char* kwsysSystem_Shell__GetArgument(const char* in, char* out, - int isUnix, int flags) -{ - /* String iterator. */ - const char* c; - - /* Keep track of how many backslashes have been encountered in a row. */ - int windows_backslashes = 0; - - /* Whether the argument must be quoted. */ - int needQuotes = kwsysSystem_Shell__ArgumentNeedsQuotes(in, isUnix, flags); - if(needQuotes) - { - /* Add the opening quote for this argument. */ - if(flags & kwsysSystem_Shell_Flag_WatcomQuote) - { - if(isUnix) - { - *out++ = '"'; - } - *out++ = '\''; - } - else - { - *out++ = '"'; - } - } - - /* Scan the string for characters that require escaping or quoting. */ - for(c=in; *c; ++c) - { - /* Look for $(MAKEVAR) syntax if requested. */ - if(flags & kwsysSystem_Shell_Flag_AllowMakeVariables) - { - const char* skip = kwsysSystem_Shell__SkipMakeVariables(c); - if(skip != c) - { - /* Copy to the end of the make variable references. */ - while(c != skip) - { - *out++ = *c++; - } - - /* The make variable reference eliminates any escaping needed - for preceding backslashes. */ - windows_backslashes = 0; - - /* Stop if we have reached the end of the string. */ - if(!*c) - { - break; - } - } - } - - /* Check whether this character needs escaping for the shell. */ - if(isUnix) - { - /* On Unix a few special characters need escaping even inside a - quoted argument. */ - if(*c == '\\' || *c == '"' || *c == '`' || *c == '$') - { - /* This character needs a backslash to escape it. */ - *out++ = '\\'; - } - } - else if(flags & kwsysSystem_Shell_Flag_EchoWindows) - { - /* On Windows the built-in command shell echo never needs escaping. */ - } - else - { - /* On Windows only backslashes and double-quotes need escaping. */ - if(*c == '\\') - { - /* Found a backslash. It may need to be escaped later. */ - ++windows_backslashes; - } - else if(*c == '"') - { - /* Found a double-quote. Escape all immediately preceding - backslashes. */ - while(windows_backslashes > 0) - { - --windows_backslashes; - *out++ = '\\'; - } - - /* Add the backslash to escape the double-quote. */ - *out++ = '\\'; - } - else - { - /* We encountered a normal character. This eliminates any - escaping needed for preceding backslashes. */ - windows_backslashes = 0; - } - } - - /* Check whether this character needs escaping for a make tool. */ - if(*c == '$') - { - if(flags & kwsysSystem_Shell_Flag_Make) - { - /* In Makefiles a dollar is written $$. The make tool will - replace it with just $ before passing it to the shell. */ - *out++ = '$'; - *out++ = '$'; - } - else if(flags & kwsysSystem_Shell_Flag_VSIDE) - { - /* In a VS IDE a dollar is written "$". If this is written in - an un-quoted argument it starts a quoted segment, inserts - the $ and ends the segment. If it is written in a quoted - argument it ends quoting, inserts the $ and restarts - quoting. Either way the $ is isolated from surrounding - text to avoid looking like a variable reference. */ - *out++ = '"'; - *out++ = '$'; - *out++ = '"'; - } - else - { - /* Otherwise a dollar is written just $. */ - *out++ = '$'; - } - } - else if(*c == '#') - { - if((flags & kwsysSystem_Shell_Flag_Make) && - (flags & kwsysSystem_Shell_Flag_WatcomWMake)) - { - /* In Watcom WMake makefiles a pound is written $#. The make - tool will replace it with just # before passing it to the - shell. */ - *out++ = '$'; - *out++ = '#'; - } - else - { - /* Otherwise a pound is written just #. */ - *out++ = '#'; - } - } - else if(*c == '%') - { - if((flags & kwsysSystem_Shell_Flag_VSIDE) || - ((flags & kwsysSystem_Shell_Flag_Make) && - ((flags & kwsysSystem_Shell_Flag_MinGWMake) || - (flags & kwsysSystem_Shell_Flag_NMake)))) - { - /* In the VS IDE, NMake, or MinGW make a percent is written %%. */ - *out++ = '%'; - *out++ = '%'; - } - else - { - /* Otherwise a percent is written just %. */ - *out++ = '%'; - } - } - else if(*c == ';') - { - if(flags & kwsysSystem_Shell_Flag_VSIDE) - { - /* In a VS IDE a semicolon is written ";". If this is written - in an un-quoted argument it starts a quoted segment, - inserts the ; and ends the segment. If it is written in a - quoted argument it ends quoting, inserts the ; and restarts - quoting. Either way the ; is isolated. */ - *out++ = '"'; - *out++ = ';'; - *out++ = '"'; - } - else - { - /* Otherwise a semicolon is written just ;. */ - *out++ = ';'; - } - } - else - { - /* Store this character. */ - *out++ = *c; - } - } - - if(needQuotes) - { - /* Add enough backslashes to escape any trailing ones. */ - while(windows_backslashes > 0) - { - --windows_backslashes; - *out++ = '\\'; - } - - /* Add the closing quote for this argument. */ - if(flags & kwsysSystem_Shell_Flag_WatcomQuote) - { - *out++ = '\''; - if(isUnix) - { - *out++ = '"'; - } - } - else - { - *out++ = '"'; - } - } - - /* Store a terminating null without incrementing. */ - *out = 0; - - return out; -} - -/*--------------------------------------------------------------------------*/ -char* kwsysSystem_Shell_GetArgumentForWindows(const char* in, - char* out, - int flags) -{ - return kwsysSystem_Shell__GetArgument(in, out, 0, flags); -} - -/*--------------------------------------------------------------------------*/ -char* kwsysSystem_Shell_GetArgumentForUnix(const char* in, - char* out, - int flags) -{ - return kwsysSystem_Shell__GetArgument(in, out, 1, flags); -} - -/*--------------------------------------------------------------------------*/ -int kwsysSystem_Shell_GetArgumentSizeForWindows(const char* in, int flags) -{ - return kwsysSystem_Shell__GetArgumentSize(in, 0, flags); -} - -/*--------------------------------------------------------------------------*/ -int kwsysSystem_Shell_GetArgumentSizeForUnix(const char* in, int flags) -{ - return kwsysSystem_Shell__GetArgumentSize(in, 1, flags); -} - /*--------------------------------------------------------------------------*/ static int kwsysSystem__AppendByte(char* local, char** begin, char** end, diff --git a/Source/kwsys/System.h.in b/Source/kwsys/System.h.in index f21bf0d..3f3d3f4 100644 --- a/Source/kwsys/System.h.in +++ b/Source/kwsys/System.h.in @@ -24,28 +24,6 @@ #endif #if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS # define kwsysSystem_Parse_CommandForUnix kwsys_ns(System_Parse_CommandForUnix) -# define kwsysSystem_Shell_GetArgumentForWindows kwsys_ns(System_Shell_GetArgumentForWindows) -# define kwsysSystem_Shell_GetArgumentForUnix kwsys_ns(System_Shell_GetArgumentForUnix) -# define kwsysSystem_Shell_GetArgumentSizeForWindows kwsys_ns(System_Shell_GetArgumentSizeForWindows) -# define kwsysSystem_Shell_GetArgumentSizeForUnix kwsys_ns(System_Shell_GetArgumentSizeForUnix) -# define kwsysSystem_Shell_Flag_e kwsys_ns(System_Shell_Flag_e) -# define kwsysSystem_Shell_Flag_Make kwsys_ns(System_Shell_Flag_Make) -# define kwsysSystem_Shell_Flag_VSIDE kwsys_ns(System_Shell_Flag_VSIDE) -# define kwsysSystem_Shell_Flag_EchoWindows kwsys_ns(System_Shell_Flag_EchoWindows) -# define kwsysSystem_Shell_Flag_WatcomWMake kwsys_ns(System_Shell_Flag_WatcomWMake) -# define kwsysSystem_Shell_Flag_MinGWMake kwsys_ns(System_Shell_Flag_MinGWMake) -# define kwsysSystem_Shell_Flag_NMake kwsys_ns(System_Shell_Flag_NMake) -# define kwsysSystem_Shell_Flag_AllowMakeVariables kwsys_ns(System_Shell_Flag_AllowMakeVariables) -# define kwsysSystem_Shell_Flag_WatcomQuote kwsys_ns(System_Shell_Flag_WatcomQuote) -#endif - -#ifdef __VMS -#define @KWSYS_NAMESPACE@System_Shell_GetArgumentForUnix \ - @KWSYS_NAMESPACE@System_Shell_UnixGA -#define @KWSYS_NAMESPACE@System_Shell_GetArgumentSizeForUnix \ - @KWSYS_NAMESPACE@System_Shell_UnixGAS -#define @KWSYS_NAMESPACE@System_Shell_GetArgumentForWindows \ - @KWSYS_NAMESPACE@System_Shell_WindowsGA #endif #if defined(__cplusplus) @@ -54,69 +32,6 @@ extern "C" #endif /** - * Transform the given command line argument for use in a Windows or - * Unix shell. Returns a pointer to the end of the command line - * argument in the provided output buffer. Flags may be passed to - * modify the generated quoting and escape sequences to work under - * alternative environments. - */ -kwsysEXPORT char* kwsysSystem_Shell_GetArgumentForWindows(const char* in, - char* out, - int flags); -kwsysEXPORT char* kwsysSystem_Shell_GetArgumentForUnix(const char* in, - char* out, - int flags); - -/** - * Compute the size of the buffer required to store the output from - * kwsysSystem_Shell_GetArgumentForWindows or - * kwsysSystem_Shell_GetArgumentForUnix. The flags passed must be - * identical between the two calls. - */ -kwsysEXPORT int kwsysSystem_Shell_GetArgumentSizeForWindows(const char* in, - int flags); -kwsysEXPORT int kwsysSystem_Shell_GetArgumentSizeForUnix(const char* in, - int flags); - -/** - * Flags to pass to kwsysSystem_Shell_GetArgumentForWindows or - * kwsysSystem_Shell_GetArgumentForUnix. These modify the generated - * quoting and escape sequences to work under alternative - * environments. - */ -enum kwsysSystem_Shell_Flag_e -{ - /** The target shell is in a makefile. */ - kwsysSystem_Shell_Flag_Make = (1<<0), - - /** The target shell is in a VS project file. Do not use with - Shell_Flag_Make. */ - kwsysSystem_Shell_Flag_VSIDE = (1<<1), - - /** In a windows shell the argument is being passed to "echo". */ - kwsysSystem_Shell_Flag_EchoWindows = (1<<2), - - /** The target shell is in a Watcom WMake makefile. */ - kwsysSystem_Shell_Flag_WatcomWMake = (1<<3), - - /** The target shell is in a MinGW Make makefile. */ - kwsysSystem_Shell_Flag_MinGWMake = (1<<4), - - /** The target shell is in a NMake makefile. */ - kwsysSystem_Shell_Flag_NMake = (1<<5), - - /** Make variable reference syntax $(MAKEVAR) should not be escaped - to allow a build tool to replace it. Replacement values - containing spaces, quotes, backslashes, or other - non-alphanumeric characters that have significance to some makes - or shells produce undefined behavior. */ - kwsysSystem_Shell_Flag_AllowMakeVariables = (1<<6), - - /** The target shell quoting uses extra single Quotes for Watcom tools. */ - kwsysSystem_Shell_Flag_WatcomQuote = (1<<7) -}; - -/** * Parse a unix-style command line string into separate arguments. * * On success, returns a pointer to an array of pointers to individual @@ -148,19 +63,6 @@ kwsysEXPORT char** kwsysSystem_Parse_CommandForUnix(const char* command, # undef kwsysEXPORT # if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS # undef kwsysSystem_Parse_CommandForUnix -# undef kwsysSystem_Shell_GetArgumentForWindows -# undef kwsysSystem_Shell_GetArgumentForUnix -# undef kwsysSystem_Shell_GetArgumentSizeForWindows -# undef kwsysSystem_Shell_GetArgumentSizeForUnix -# undef kwsysSystem_Shell_Flag_e -# undef kwsysSystem_Shell_Flag_Make -# undef kwsysSystem_Shell_Flag_VSIDE -# undef kwsysSystem_Shell_Flag_EchoWindows -# undef kwsysSystem_Shell_Flag_WatcomWMake -# undef kwsysSystem_Shell_Flag_MinGWMake -# undef kwsysSystem_Shell_Flag_NMake -# undef kwsysSystem_Shell_Flag_AllowMakeVariables -# undef kwsysSystem_Shell_Flag_WatcomQuote # endif #endif diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index b0434f4..6e81b0b 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -81,6 +81,11 @@ typedef int siginfo_t; # include <errno.h> // extern int errno; #endif +#if defined (__CYGWIN__) && !defined(_WIN32) +# include <windows.h> +# undef _WIN32 +#endif + #ifdef __FreeBSD__ # include <sys/sysctl.h> # include <fenv.h> @@ -366,6 +371,8 @@ public: const char *procLimitEnvVarName); LongLong GetProcMemoryUsed(); + double GetLoadAverage(); + // enable/disable stack trace signal handler. static void SetStackTraceOnError(int enable); @@ -820,6 +827,11 @@ SystemInformation::LongLong SystemInformation::GetProcMemoryUsed() return this->Implementation->GetProcMemoryUsed(); } +double SystemInformation::GetLoadAverage() +{ + return this->Implementation->GetLoadAverage(); +} + SystemInformation::LongLong SystemInformation::GetProcessId() { return this->Implementation->GetProcessId(); @@ -1490,6 +1502,60 @@ void SymbolProperties::Initialize(void *address) } #endif // don't define this class if we're not using it +// -------------------------------------------------------------------------- +#if defined(_WIN32) || defined(__CYGWIN__) +# define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes +#endif +#if defined(_MSC_VER) && _MSC_VER < 1310 +# undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes +#endif +#if defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes) +double calculateCPULoad(unsigned __int64 idleTicks, + unsigned __int64 totalTicks) +{ + static double previousLoad = -0.0; + static unsigned __int64 previousIdleTicks = 0; + static unsigned __int64 previousTotalTicks = 0; + + unsigned __int64 const idleTicksSinceLastTime = + idleTicks - previousIdleTicks; + unsigned __int64 const totalTicksSinceLastTime = + totalTicks - previousTotalTicks; + + double load; + if (previousTotalTicks == 0 || totalTicksSinceLastTime == 0) + { + // No new information. Use previous result. + load = previousLoad; + } + else + { + // Calculate load since last time. + load = 1.0 - double(idleTicksSinceLastTime) / totalTicksSinceLastTime; + + // Smooth if possible. + if (previousLoad > 0) + { + load = 0.25 * load + 0.75 * previousLoad; + } + } + + previousLoad = load; + previousIdleTicks = idleTicks; + previousTotalTicks = totalTicks; + + return load; +} + +unsigned __int64 fileTimeToUInt64(FILETIME const& ft) +{ + LARGE_INTEGER out; + out.HighPart = ft.dwHighDateTime; + out.LowPart = ft.dwLowDateTime; + return out.QuadPart; +} +#endif + } // anonymous namespace @@ -3612,6 +3678,38 @@ SystemInformationImplementation::GetProcMemoryUsed() #endif } +double SystemInformationImplementation::GetLoadAverage() +{ +#if defined(KWSYS_CXX_HAS_GETLOADAVG) + double loadavg[3] = { 0.0, 0.0, 0.0 }; + if (getloadavg(loadavg, 3) > 0) + { + return loadavg[0]; + } + return -0.0; +#elif defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes) + // Old windows.h headers do not provide GetSystemTimes. + typedef BOOL (WINAPI *GetSystemTimesType)(LPFILETIME, LPFILETIME, + LPFILETIME); + static GetSystemTimesType pGetSystemTimes = + (GetSystemTimesType)GetProcAddress(GetModuleHandleW(L"kernel32"), + "GetSystemTimes"); + FILETIME idleTime, kernelTime, userTime; + if (pGetSystemTimes && pGetSystemTimes(&idleTime, &kernelTime, &userTime)) + { + unsigned __int64 const idleTicks = + fileTimeToUInt64(idleTime); + unsigned __int64 const totalTicks = + fileTimeToUInt64(kernelTime) + fileTimeToUInt64(userTime); + return calculateCPULoad(idleTicks, totalTicks) * GetNumberOfPhysicalCPU(); + } + return -0.0; +#else + // Not implemented on this platform. + return -0.0; +#endif +} + /** Get the process id of the running process. */ diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index a9fd05d..4acdc4f 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -130,6 +130,10 @@ public: // Get system RAM used by this process id in units of KiB. LongLong GetProcMemoryUsed(); + // Return the load average of the machine or -0.0 if it cannot + // be determined. + double GetLoadAverage(); + // enable/disable stack trace signal handler. In order to // produce an informative stack trace the application should // be dynamically linked and compiled with debug symbols. diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index c834e34..0714344 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -385,6 +385,26 @@ class SystemToolsTranslationMap : { }; +#ifdef _WIN32 +struct SystemToolsPathCaseCmp +{ + bool operator()(kwsys_stl::string const& l, kwsys_stl::string const& r) const + { +# ifdef _MSC_VER + return _stricmp(l.c_str(), r.c_str()) < 0; +# elif defined(__GNUC__) + return strcasecmp(l.c_str(), r.c_str()) < 0; +# else + return SystemTools::Strucmp(l.c_str(), r.c_str()) < 0; +# endif + } +}; + +class SystemToolsPathCaseMap: + public kwsys_stl::map<kwsys_stl::string, kwsys_stl::string, + SystemToolsPathCaseCmp> {}; +#endif + // adds the elements of the env variable path to the arg passed in void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env) { @@ -3178,8 +3198,16 @@ bool SystemTools::FileIsDirectory(const kwsys_stl::string& inName) bool SystemTools::FileIsSymlink(const kwsys_stl::string& name) { #if defined( _WIN32 ) - (void)name; - return false; + DWORD attr = GetFileAttributesW( + SystemTools::ConvertToWindowsExtendedPath(name).c_str()); + if (attr != INVALID_FILE_ATTRIBUTES) + { + return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + } + else + { + return false; + } #else struct stat fs; if(lstat(name.c_str(), &fs) == 0) @@ -3690,6 +3718,11 @@ static int GetCasePathName(const kwsys_stl::string & pathIn, // Start with root component. kwsys_stl::vector<kwsys_stl::string>::size_type idx = 0; casePath = path_components[idx++]; + // make sure drive letter is always upper case + if(casePath.size() > 1 && casePath[1] == ':') + { + casePath[0] = toupper(casePath[0]); + } const char* sep = ""; // If network path, fill casePath with server/share so FindFirstFile @@ -3745,27 +3778,21 @@ kwsys_stl::string SystemTools::GetActualCaseForPath(const kwsys_stl::string& p) #ifndef _WIN32 return p; #else - kwsys_stl::string casePath = p; - // make sure drive letter is always upper case - if(casePath.size() > 1 && casePath[1] == ':') - { - casePath[0] = toupper(casePath[0]); - } - // Check to see if actual case has already been called - // for this path, and the result is stored in the LongPathMap - SystemToolsTranslationMap::iterator i = - SystemTools::LongPathMap->find(casePath); - if(i != SystemTools::LongPathMap->end()) + // for this path, and the result is stored in the PathCaseMap + SystemToolsPathCaseMap::iterator i = + SystemTools::PathCaseMap->find(p); + if(i != SystemTools::PathCaseMap->end()) { return i->second; } + kwsys_stl::string casePath; int len = GetCasePathName(p, casePath); if(len == 0 || len > MAX_PATH+1) { return p; } - (*SystemTools::LongPathMap)[p] = casePath; + (*SystemTools::PathCaseMap)[p] = casePath; return casePath; #endif } @@ -4211,6 +4238,11 @@ SystemTools::DetectFileType(const char *filename, return SystemTools::FileTypeUnknown; } + if (SystemTools::FileIsDirectory(filename)) + { + return SystemTools::FileTypeUnknown; + } + FILE *fp = Fopen(filename, "rb"); if (!fp) { @@ -4224,6 +4256,7 @@ SystemTools::DetectFileType(const char *filename, fclose(fp); if (read_length == 0) { + delete [] buffer; return SystemTools::FileTypeUnknown; } @@ -4408,7 +4441,7 @@ bool SystemTools::FileIsFullPath(const char* in_name, size_t len) bool SystemTools::GetShortPath(const kwsys_stl::string& path, kwsys_stl::string& shortPath) { -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) const int size = int(path.size()) +1; // size of return char *tempPath = new char[size]; // create a buffer DWORD ret; @@ -5139,7 +5172,9 @@ bool SystemTools::ParseURL( const kwsys_stl::string& URL, // necessary. static unsigned int SystemToolsManagerCount; SystemToolsTranslationMap *SystemTools::TranslationMap; -SystemToolsTranslationMap *SystemTools::LongPathMap; +#ifdef _WIN32 +SystemToolsPathCaseMap *SystemTools::PathCaseMap; +#endif #ifdef __CYGWIN__ SystemToolsTranslationMap *SystemTools::Cyg2Win32Map; #endif @@ -5187,7 +5222,9 @@ void SystemTools::ClassInitialize() #endif // Allocate the translation map first. SystemTools::TranslationMap = new SystemToolsTranslationMap; - SystemTools::LongPathMap = new SystemToolsTranslationMap; +#ifdef _WIN32 + SystemTools::PathCaseMap = new SystemToolsPathCaseMap; +#endif #ifdef __CYGWIN__ SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap; #endif @@ -5244,7 +5281,9 @@ void SystemTools::ClassInitialize() void SystemTools::ClassFinalize() { delete SystemTools::TranslationMap; - delete SystemTools::LongPathMap; +#ifdef _WIN32 + delete SystemTools::PathCaseMap; +#endif #ifdef __CYGWIN__ delete SystemTools::Cyg2Win32Map; #endif diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 93cde02..7899141 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -54,6 +54,8 @@ namespace @KWSYS_NAMESPACE@ { class SystemToolsTranslationMap; +class SystemToolsPathCaseMap; + /** \class SystemToolsManager * \brief Use to make sure SystemTools is initialized before it is used * and is the last static object destroyed @@ -944,7 +946,9 @@ private: * Each time 'dir' will be found it will be replace by 'refdir' */ static SystemToolsTranslationMap *TranslationMap; - static SystemToolsTranslationMap *LongPathMap; +#ifdef _WIN32 + static SystemToolsPathCaseMap *PathCaseMap; +#endif #ifdef __CYGWIN__ static SystemToolsTranslationMap *Cyg2Win32Map; #endif diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index 82620da..1596fe4 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -452,6 +452,19 @@ int main() } #endif +#ifdef TEST_KWSYS_CXX_HAS_GETLOADAVG +// Match feature definitions from SystemInformation.cxx +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include <stdlib.h> +int main() +{ + double loadavg[3] = { 0.0, 0.0, 0.0 }; + return getloadavg(loadavg, 3); +} +#endif + #ifdef TEST_KWSYS_CXX_HAS_RLIMIT64 # if defined(KWSYS_HAS_LFS) # define _LARGEFILE_SOURCE diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index 47c3fb0..d0e20c1 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -29,26 +29,48 @@ # include <windows.h> #else # include <unistd.h> +# include <signal.h> #endif #if defined(__BORLANDC__) # pragma warn -8060 /* possibly incorrect assignment */ #endif +/* Platform-specific sleep functions. */ + #if defined(__BEOS__) && !defined(__ZETA__) /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */ # include <be/kernel/OS.h> -static inline void testProcess_usleep(unsigned int msec) +static inline void testProcess_usleep(unsigned int usec) +{ + snooze(usec); +} +#elif defined(_WIN32) +/* Windows can only sleep in millisecond intervals. */ +static void testProcess_usleep(unsigned int usec) { - snooze(msec); + Sleep(usec / 1000); } #else # define testProcess_usleep usleep #endif +#if defined(_WIN32) +static void testProcess_sleep(unsigned int sec) +{ + Sleep(sec*1000); +} +#else +static void testProcess_sleep(unsigned int sec) +{ + sleep(sec); +} +#endif + int runChild(const char* cmd[], int state, int exception, int value, int share, int output, int delay, double timeout, int poll, - int repeat, int disown); + int repeat, int disown, int createNewGroup, + unsigned int interruptDelay); static int test1(int argc, const char* argv[]) { @@ -73,11 +95,7 @@ static int test3(int argc, const char* argv[]) fprintf(stderr, "Output before sleep on stderr from timeout test.\n"); fflush(stdout); fflush(stderr); -#if defined(_WIN32) - Sleep(15000); -#else - sleep(15); -#endif + testProcess_sleep(15); fprintf(stdout, "Output after sleep on stdout from timeout test.\n"); fprintf(stderr, "Output after sleep on stderr from timeout test.\n"); return 0; @@ -102,7 +120,7 @@ static int test4(int argc, const char* argv[]) #endif (void)argc; (void)argv; fprintf(stdout, "Output before crash on stdout from crash test.\n"); - fprintf(stderr, "Output before crash on stderr from crash test.\n"); + fprintf(stderr, "Output before crash on stderr from crash test.\n"); fflush(stdout); fflush(stderr); assert(invalidAddress); /* Quiet Clang scan-build. */ @@ -127,7 +145,7 @@ static int test5(int argc, const char* argv[]) fflush(stdout); fflush(stderr); r = runChild(cmd, kwsysProcess_State_Exception, - kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0, 1, 0); + kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0, 1, 0, 0, 0); fprintf(stdout, "Output on stdout after recursive test.\n"); fprintf(stderr, "Output on stderr after recursive test.\n"); fflush(stdout); @@ -168,11 +186,7 @@ static int test7(int argc, const char* argv[]) fflush(stdout); fflush(stderr); /* Sleep for 1 second. */ -#if defined(_WIN32) - Sleep(1000); -#else - sleep(1); -#endif + testProcess_sleep(1); fprintf(stdout, "Output on stdout after sleep.\n"); fprintf(stderr, "Output on stderr after sleep.\n"); fflush(stdout); @@ -196,7 +210,7 @@ static int test8(int argc, const char* argv[]) fflush(stdout); fflush(stderr); r = runChild(cmd, kwsysProcess_State_Disowned, kwsysProcess_Exception_None, - 1, 1, 1, 0, 10, 0, 1, 1); + 1, 1, 1, 0, 10, 0, 1, 1, 0, 0); fprintf(stdout, "Output on stdout after grandchild test.\n"); fprintf(stderr, "Output on stderr after grandchild test.\n"); fflush(stdout); @@ -217,18 +231,137 @@ static int test8_grandchild(int argc, const char* argv[]) implemented. */ fclose(stdout); fclose(stderr); + testProcess_sleep(15); + return 0; +} + +static int test9(int argc, const char* argv[]) +{ + /* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this + process. Here, we start a child process that sleeps for a long time + while ignoring signals. The test is successful if this process waits + for the child to return before exiting from the Ctrl+C handler. + + WARNING: This test will falsely pass if the share parameter of runChild + was set to 0 when invoking the test9 process. */ + int r; + const char* cmd[4]; + (void)argc; + cmd[0] = argv[0]; + cmd[1] = "run"; + cmd[2] = "109"; + cmd[3] = 0; + fprintf(stdout, "Output on stdout before grandchild test.\n"); + fprintf(stderr, "Output on stderr before grandchild test.\n"); + fflush(stdout); + fflush(stderr); + r = runChild(cmd, kwsysProcess_State_Exited, + kwsysProcess_Exception_None, + 0, 1, 1, 0, 30, 0, 1, 0, 0, 0); + /* This sleep will avoid a race condition between this function exiting + normally and our Ctrl+C handler exiting abnormally after the process + exits. */ + testProcess_sleep(1); + fprintf(stdout, "Output on stdout after grandchild test.\n"); + fprintf(stderr, "Output on stderr after grandchild test.\n"); + fflush(stdout); + fflush(stderr); + return r; +} + #if defined(_WIN32) - Sleep(15000); +static BOOL WINAPI test9_grandchild_handler(DWORD dwCtrlType) +{ + /* Ignore all Ctrl+C/Break signals. We must use an actual handler function + instead of using SetConsoleCtrlHandler(NULL, TRUE) so that we can also + ignore Ctrl+Break in addition to Ctrl+C. */ + (void)dwCtrlType; + return TRUE; +} +#endif + +static int test9_grandchild(int argc, const char* argv[]) +{ + /* The grandchild just sleeps for a few seconds while ignoring signals. */ + (void)argc; (void)argv; +#if defined(_WIN32) + if(!SetConsoleCtrlHandler(test9_grandchild_handler, TRUE)) + { + return 1; + } #else - sleep(15); + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + if(sigaction(SIGINT, &sa, 0) < 0) + { + return 1; + } #endif + fprintf(stdout, "Output on stdout from grandchild before sleep.\n"); + fprintf(stderr, "Output on stderr from grandchild before sleep.\n"); + fflush(stdout); + fflush(stderr); + /* Sleep for 9 seconds. */ + testProcess_sleep(9); + fprintf(stdout, "Output on stdout from grandchild after sleep.\n"); + fprintf(stderr, "Output on stderr from grandchild after sleep.\n"); + fflush(stdout); + fflush(stderr); + return 0; +} + +static int test10(int argc, const char* argv[]) +{ + /* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this + process. Here, we start a child process that sleeps for a long time and + processes signals normally. However, this grandchild is created in a new + process group - ensuring that Ctrl+C we receive is sent to our process + groups. We make sure it exits anyway. */ + int r; + const char* cmd[4]; + (void)argc; + cmd[0] = argv[0]; + cmd[1] = "run"; + cmd[2] = "110"; + cmd[3] = 0; + fprintf(stdout, "Output on stdout before grandchild test.\n"); + fprintf(stderr, "Output on stderr before grandchild test.\n"); + fflush(stdout); + fflush(stderr); + r = runChild(cmd, kwsysProcess_State_Exception, + kwsysProcess_Exception_Interrupt, + 0, 1, 1, 0, 30, 0, 1, 0, 1, 0); + fprintf(stdout, "Output on stdout after grandchild test.\n"); + fprintf(stderr, "Output on stderr after grandchild test.\n"); + fflush(stdout); + fflush(stderr); + return r; +} + +static int test10_grandchild(int argc, const char* argv[]) +{ + /* The grandchild just sleeps for a few seconds and handles signals. */ + (void)argc; (void)argv; + fprintf(stdout, "Output on stdout from grandchild before sleep.\n"); + fprintf(stderr, "Output on stderr from grandchild before sleep.\n"); + fflush(stdout); + fflush(stderr); + /* Sleep for 6 seconds. */ + testProcess_sleep(6); + fprintf(stdout, "Output on stdout from grandchild after sleep.\n"); + fprintf(stderr, "Output on stderr from grandchild after sleep.\n"); + fflush(stdout); + fflush(stderr); return 0; } static int runChild2(kwsysProcess* kp, const char* cmd[], int state, int exception, int value, int share, int output, int delay, double timeout, - int poll, int disown) + int poll, int disown, int createNewGroup, + unsigned int interruptDelay) { int result = 0; char* data = 0; @@ -249,6 +382,10 @@ static int runChild2(kwsysProcess* kp, { kwsysProcess_SetOption(kp, kwsysProcess_Option_Detach, 1); } + if(createNewGroup) + { + kwsysProcess_SetOption(kp, kwsysProcess_Option_CreateProcessGroup, 1); + } kwsysProcess_Execute(kp); if(poll) @@ -256,6 +393,12 @@ static int runChild2(kwsysProcess* kp, pUserTimeout = &userTimeout; } + if(interruptDelay) + { + testProcess_sleep(interruptDelay); + kwsysProcess_Interrupt(kp); + } + if(!share && !disown) { int p; @@ -286,17 +429,13 @@ static int runChild2(kwsysProcess* kp, if(poll) { /* Delay to avoid busy loop during polling. */ -#if defined(_WIN32) - Sleep(100); -#else testProcess_usleep(100000); -#endif } if(delay) { /* Purposely sleeping only on Win32 to let pipe fill up. */ #if defined(_WIN32) - Sleep(100); + testProcess_usleep(100000); #endif } } @@ -337,7 +476,7 @@ static int runChild2(kwsysProcess* kp, printf("Error in administrating child process: [%s]\n", kwsysProcess_GetErrorString(kp)); break; }; - + if(result) { if(exception != kwsysProcess_GetExitException(kp)) @@ -353,7 +492,7 @@ static int runChild2(kwsysProcess* kp, value, kwsysProcess_GetExitValue(kp)); } } - + if(kwsysProcess_GetState(kp) != state) { fprintf(stderr, "Mismatch in state. " @@ -374,9 +513,37 @@ static int runChild2(kwsysProcess* kp, return result; } +/** + * Runs a child process and blocks until it returns. Arguments as follows: + * + * cmd = Command line to run. + * state = Expected return value of kwsysProcess_GetState after exit. + * exception = Expected return value of kwsysProcess_GetExitException. + * value = Expected return value of kwsysProcess_GetExitValue. + * share = Whether to share stdout/stderr child pipes with our pipes + * by way of kwsysProcess_SetPipeShared. If false, new pipes + * are created. + * output = If !share && !disown, whether to write the child's stdout + * and stderr output to our stdout. + * delay = If !share && !disown, adds an additional short delay to + * the pipe loop to allow the pipes to fill up; Windows only. + * timeout = Non-zero to sets a timeout in seconds via + * kwsysProcess_SetTimeout. + * poll = If !share && !disown, we count the number of 0.1 second + * intervals where the child pipes had no new data. We fail + * if not in the bounds of MINPOLL/MAXPOLL. + * repeat = Number of times to run the process. + * disown = If set, the process is disowned. + * createNewGroup = If set, the process is created in a new process group. + * interruptDelay = If non-zero, number of seconds to delay before + * interrupting the process. Note that this delay will occur + * BEFORE any reading/polling of pipes occurs and before any + * detachment occurs. + */ int runChild(const char* cmd[], int state, int exception, int value, int share, int output, int delay, double timeout, - int poll, int repeat, int disown) + int poll, int repeat, int disown, int createNewGroup, + unsigned int interruptDelay) { int result = 1; kwsysProcess* kp = kwsysProcess_New(); @@ -388,7 +555,8 @@ int runChild(const char* cmd[], int state, int exception, int value, while(repeat-- > 0) { result = runChild2(kp, cmd, state, exception, value, share, - output, delay, timeout, poll, disown); + output, delay, timeout, poll, disown, createNewGroup, + interruptDelay); } kwsysProcess_Delete(kp); return result; @@ -435,7 +603,7 @@ int main(int argc, const char* argv[]) n = atoi(argv[2]); } /* Check arguments. */ - if(((n >= 1 && n <= 8) || n == 108) && argc == 3) + if(((n >= 1 && n <= 10) || n == 108 || n == 109 || n == 110) && argc == 3) { /* This is the child process for a requested test number. */ switch (n) @@ -448,15 +616,19 @@ int main(int argc, const char* argv[]) case 6: test6(argc, argv); return 0; case 7: return test7(argc, argv); case 8: return test8(argc, argv); + case 9: return test9(argc, argv); + case 10: return test10(argc, argv); case 108: return test8_grandchild(argc, argv); + case 109: return test9_grandchild(argc, argv); + case 110: return test10_grandchild(argc, argv); } fprintf(stderr, "Invalid test number %d.\n", n); return 1; } - else if(n >= 1 && n <= 8) + else if(n >= 1 && n <= 10) { /* This is the parent process for a requested test number. */ - int states[8] = + int states[10] = { kwsysProcess_State_Exited, kwsysProcess_State_Exited, @@ -465,9 +637,11 @@ int main(int argc, const char* argv[]) kwsysProcess_State_Exited, kwsysProcess_State_Expired, kwsysProcess_State_Exited, - kwsysProcess_State_Exited + kwsysProcess_State_Exited, + kwsysProcess_State_Expired, /* Ctrl+C handler test */ + kwsysProcess_State_Exception /* Process group test */ }; - int exceptions[8] = + int exceptions[10] = { kwsysProcess_Exception_None, kwsysProcess_Exception_None, @@ -476,14 +650,19 @@ int main(int argc, const char* argv[]) kwsysProcess_Exception_None, kwsysProcess_Exception_None, kwsysProcess_Exception_None, - kwsysProcess_Exception_None + kwsysProcess_Exception_None, + kwsysProcess_Exception_None, + kwsysProcess_Exception_Interrupt }; - int values[8] = {0, 123, 1, 1, 0, 0, 0, 0}; - int outputs[8] = {1, 1, 1, 1, 1, 0, 1, 1}; - int delays[8] = {0, 0, 0, 0, 0, 1, 0, 0}; - double timeouts[8] = {10, 10, 10, 30, 30, 10, -1, 10}; - int polls[8] = {0, 0, 0, 0, 0, 0, 1, 0}; - int repeat[8] = {2, 1, 1, 1, 1, 1, 1, 1}; + int values[10] = {0, 123, 1, 1, 0, 0, 0, 0, 1, 1}; + int shares[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1}; + int outputs[10] = {1, 1, 1, 1, 1, 0, 1, 1, 1, 1}; + int delays[10] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0}; + double timeouts[10] = {10, 10, 10, 30, 30, 10, -1, 10, 6, 4}; + int polls[10] = {0, 0, 0, 0, 0, 0, 1, 0, 0, 0}; + int repeat[10] = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + int createNewGroups[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1}; + unsigned int interruptDelays[10] = {0, 0, 0, 0, 0, 0, 0, 0, 3, 2}; int r; const char* cmd[4]; #ifdef _WIN32 @@ -515,9 +694,10 @@ int main(int argc, const char* argv[]) fprintf(stderr, "Output on stderr before test %d.\n", n); fflush(stdout); fflush(stderr); - r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0, + r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], shares[n-1], outputs[n-1], delays[n-1], timeouts[n-1], - polls[n-1], repeat[n-1], 0); + polls[n-1], repeat[n-1], 0, createNewGroups[n-1], + interruptDelays[n-1]); fprintf(stdout, "Output on stdout after test %d.\n", n); fprintf(stderr, "Output on stderr after test %d.\n", n); fflush(stdout); @@ -536,7 +716,8 @@ int main(int argc, const char* argv[]) int exception = kwsysProcess_Exception_None; int value = 0; double timeout = 0; - int r = runChild(cmd, state, exception, value, 0, 1, 0, timeout, 0, 1, 0); + int r = runChild(cmd, state, exception, value, 0, 1, 0, timeout, + 0, 1, 0, 0, 0); return r; } else diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 53d51ac..fc8ea55 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -87,6 +87,7 @@ int testSystemInformation(int, char*[]) printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB"); printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB"); + printMethod(info, GetLoadAverage); for (long int i = 0; i <= 31; i++) { diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 15d8eab..7b5c025 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -98,6 +98,10 @@ static bool CheckEscapeChars(kwsys_stl::string input, static bool CheckFileOperations() { bool res = true; + const kwsys_stl::string testNonExistingFile(TEST_SYSTEMTOOLS_SOURCE_DIR + "/testSystemToolsNonExistingFile"); + const kwsys_stl::string testDotFile(TEST_SYSTEMTOOLS_SOURCE_DIR + "/."); const kwsys_stl::string testBinFile(TEST_SYSTEMTOOLS_SOURCE_DIR "/testSystemTools.bin"); const kwsys_stl::string testTxtFile(TEST_SYSTEMTOOLS_SOURCE_DIR @@ -106,6 +110,24 @@ static bool CheckFileOperations() "/testSystemToolsNewDir"); const kwsys_stl::string testNewFile(testNewDir + "/testNewFile.txt"); + if (kwsys::SystemTools::DetectFileType(testNonExistingFile.c_str()) != + kwsys::SystemTools::FileTypeUnknown) + { + kwsys_ios::cerr + << "Problem with DetectFileType - failed to detect type of: " + << testNonExistingFile << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::DetectFileType(testDotFile.c_str()) != + kwsys::SystemTools::FileTypeUnknown) + { + kwsys_ios::cerr + << "Problem with DetectFileType - failed to detect type of: " + << testDotFile << kwsys_ios::endl; + res = false; + } + if (kwsys::SystemTools::DetectFileType(testBinFile.c_str()) != kwsys::SystemTools::FileTypeBinary) { |