diff options
Diffstat (limited to 'Source')
78 files changed, 2121 insertions, 834 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 354f123..8bf6c40 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -176,6 +176,10 @@ set(SRCS cmExportFileGenerator.cxx cmExportInstallFileGenerator.h cmExportInstallFileGenerator.cxx + cmExportSet.h + cmExportSet.cxx + cmExportSetMap.h + cmExportSetMap.cxx cmExtraCodeBlocksGenerator.cxx cmExtraCodeBlocksGenerator.h cmExtraEclipseCDT4Generator.cxx @@ -183,6 +187,8 @@ set(SRCS cmFileTimeComparison.cxx cmFileTimeComparison.h cmGeneratedFileStream.cxx + cmGeneratorExpressionDAGChecker.cxx + cmGeneratorExpressionDAGChecker.h cmGeneratorExpressionEvaluator.cxx cmGeneratorExpressionEvaluator.h cmGeneratorExpressionLexer.cxx @@ -257,6 +263,7 @@ set(SRCS cmSystemTools.h cmTarget.cxx cmTarget.h + cmTargetExport.h cmTest.cxx cmTest.h cmTestGenerator.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3dbb051..0894fa0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,6 +1,6 @@ # CMake version number components. set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) -set(CMake_VERSION_PATCH 9) -set(CMake_VERSION_TWEAK 20120921) -#set(CMake_VERSION_RC 1) +set(CMake_VERSION_PATCH 10) +set(CMake_VERSION_TWEAK 0) +#set(CMake_VERSION_RC 3) diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx index 7fa401c..6a841fa 100644 --- a/Source/CPack/cmCPackDocumentVariables.cxx +++ b/Source/CPack/cmCPackDocumentVariables.cxx @@ -31,15 +31,25 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm) "Each CPack generator as a built-in default value for this" " variable. E.g. Archive generators (ZIP, TGZ, ...) includes" " the top level whereas RPM or DEB don't. The user may override" - " the default value byt setting this variable.\n" + " the default value by setting this variable.\n" "There is a similar variable " - "CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY" + "CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY " "which may be used to override the behavior for the component" - "packaging case which may have different default value for" - "historical (now backward compatibility) reason.", false, + " packaging case which may have different default value for" + " historical (now backward compatibility) reason.", false, "Variables common to all CPack generators"); cm->DefineProperty + ("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY", cmProperty::VARIABLE, + "Boolean toggle to include/exclude top level directory " + "(component case).", + "Similar usage as CPACK_INCLUDE_TOPLEVEL_DIRECTORY" + " but for the component case. " + "See CPACK_INCLUDE_TOPLEVEL_DIRECTORY documentation for" + " the detail.", false, + "Variables common to all CPack generators"); + + cm->DefineProperty ("CPACK_SET_DESTDIR", cmProperty::VARIABLE, "Boolean toggle to make CPack use DESTDIR mechanism when" " packaging.", "DESTDIR means DESTination DIRectory." diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index f113400..e964696 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -855,7 +855,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION // then forward request to cmake_install.cmake script - if (this->GetOption("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) + if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) { mf->AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); @@ -865,7 +865,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // then ask cmake_install.cmake script to error out // as soon as it occurs (before installing file) if (!SupportsAbsoluteDestination() || - this->GetOption("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) + this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) { mf->AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); @@ -905,7 +905,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( localFileName = cmSystemTools::RelativePath(InstallPrefix, fit->c_str()); localFileName = - localFileName.substr(localFileName.find('/')+1, + localFileName.substr(localFileName.find_first_not_of('/'), std::string::npos); Components[installComponent].Files.push_back(localFileName); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <" diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index a2a16d3..80218ad 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -247,7 +247,8 @@ void cmCTestMemCheckHandler::GenerateTestCommand( { std::vector<cmStdString>::size_type pp; std::string memcheckcommand = ""; - memcheckcommand = this->MemoryTester; + memcheckcommand + = cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str()); for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ ) { args.push_back(this->MemoryTesterOptions[pp]); @@ -410,29 +411,46 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() "MemoryCheckCommand").c_str()) ) { this->MemoryTester - = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration( - "MemoryCheckCommand").c_str()); + = this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str(); + + // determine the checker type + if ( this->MemoryTester.find("valgrind") != std::string::npos ) + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + } + else if ( this->MemoryTester.find("purify") != std::string::npos ) + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; + } + else if ( this->MemoryTester.find("BC") != std::string::npos ) + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; + } + else + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN; + } } else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( "PurifyCommand").c_str()) ) { this->MemoryTester - = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration( - "PurifyCommand").c_str()); + = this->CTest->GetCTestConfiguration("PurifyCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; } else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( "ValgrindCommand").c_str()) ) { this->MemoryTester - = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration( - "ValgrindCommand").c_str()); + = this->CTest->GetCTestConfiguration("ValgrindCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; } else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( "BoundsCheckerCommand").c_str()) ) { this->MemoryTester - = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration( - "BoundsCheckerCommand").c_str()); + = this->CTest->GetCTestConfiguration("BoundsCheckerCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; } else { @@ -470,82 +488,81 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterOutputFile = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.log"; - if ( this->MemoryTester.find("valgrind") != std::string::npos ) + switch ( this->MemoryTesterStyle ) { - this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; - if ( this->MemoryTesterOptions.empty() ) - { - this->MemoryTesterOptions.push_back("-q"); - this->MemoryTesterOptions.push_back("--tool=memcheck"); - this->MemoryTesterOptions.push_back("--leak-check=yes"); - this->MemoryTesterOptions.push_back("--show-reachable=yes"); - this->MemoryTesterOptions.push_back("--workaround-gcc296-bugs=yes"); - this->MemoryTesterOptions.push_back("--num-callers=50"); - } - if ( this->CTest->GetCTestConfiguration( - "MemoryCheckSuppressionFile").size() ) - { - if ( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( - "MemoryCheckSuppressionFile").c_str()) ) + case cmCTestMemCheckHandler::VALGRIND: + if ( this->MemoryTesterOptions.empty() ) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Cannot find memory checker suppression file: " - << this->CTest->GetCTestConfiguration( - "MemoryCheckSuppressionFile").c_str() << std::endl); - return false; - } - std::string suppressions = "--suppressions=" - + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); - this->MemoryTesterOptions.push_back(suppressions); - } - } - else if ( this->MemoryTester.find("purify") != std::string::npos ) - { - this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; - std::string outputFile; -#ifdef _WIN32 - if( this->CTest->GetCTestConfiguration( + this->MemoryTesterOptions.push_back("-q"); + this->MemoryTesterOptions.push_back("--tool=memcheck"); + this->MemoryTesterOptions.push_back("--leak-check=yes"); + this->MemoryTesterOptions.push_back("--show-reachable=yes"); + this->MemoryTesterOptions.push_back("--workaround-gcc296-bugs=yes"); + this->MemoryTesterOptions.push_back("--num-callers=50"); + } + if ( this->CTest->GetCTestConfiguration( "MemoryCheckSuppressionFile").size() ) + { + if ( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile").c_str()) ) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot find memory checker suppression file: " + << this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile").c_str() << std::endl); + return false; + } + std::string suppressions = "--suppressions=" + + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); + this->MemoryTesterOptions.push_back(suppressions); + } + break; + case cmCTestMemCheckHandler::PURIFY: { - if( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( - "MemoryCheckSuppressionFile").c_str()) ) + std::string outputFile; +#ifdef _WIN32 + if( this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile").size() ) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Cannot find memory checker suppression file: " - << this->CTest->GetCTestConfiguration( - "MemoryCheckSuppressionFile").c_str() << std::endl); - return false; - } - std::string filterFiles = "/FilterFiles=" - + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); - this->MemoryTesterOptions.push_back(filterFiles); - } - outputFile = "/SAVETEXTDATA="; + if( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile").c_str()) ) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot find memory checker suppression file: " + << this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile").c_str() << std::endl); + return false; + } + std::string filterFiles = "/FilterFiles=" + + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); + this->MemoryTesterOptions.push_back(filterFiles); + } + outputFile = "/SAVETEXTDATA="; #else - outputFile = "-log-file="; + outputFile = "-log-file="; #endif - outputFile += this->MemoryTesterOutputFile; - this->MemoryTesterOptions.push_back(outputFile); - } - else if ( this->MemoryTester.find("BC") != std::string::npos ) - { - this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile; - std::string dpbdFile = this->CTest->GetBinaryDir() - + "/Testing/Temporary/MemoryChecker.DPbd"; - this->BoundsCheckerDPBDFile = dpbdFile; - this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; - this->MemoryTesterOptions.push_back("/B"); - this->MemoryTesterOptions.push_back(dpbdFile); - this->MemoryTesterOptions.push_back("/X"); - this->MemoryTesterOptions.push_back(this->MemoryTesterOutputFile); - this->MemoryTesterOptions.push_back("/M"); - } - else - { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Do not understand memory checker: " << this->MemoryTester.c_str() - << std::endl); - return false; + outputFile += this->MemoryTesterOutputFile; + this->MemoryTesterOptions.push_back(outputFile); + break; + } + case cmCTestMemCheckHandler::BOUNDS_CHECKER: + { + this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile; + std::string dpbdFile = this->CTest->GetBinaryDir() + + "/Testing/Temporary/MemoryChecker.DPbd"; + this->BoundsCheckerDPBDFile = dpbdFile; + this->MemoryTesterOptions.push_back("/B"); + this->MemoryTesterOptions.push_back(dpbdFile); + this->MemoryTesterOptions.push_back("/X"); + this->MemoryTesterOptions.push_back(this->MemoryTesterOutputFile); + this->MemoryTesterOptions.push_back("/M"); + break; + } + default: + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Do not understand memory checker: " << this->MemoryTester.c_str() + << std::endl); + return false; } std::vector<cmStdString>::size_type cc; diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 49cea2e..2668c8e 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -38,11 +38,11 @@ cmCTestSVN::~cmCTestSVN() //---------------------------------------------------------------------------- void cmCTestSVN::CleanupImpl() { - const char* svn = this->CommandLineTool.c_str(); - const char* svn_cleanup[] = {svn, "cleanup", 0}; + std::vector<const char*> svn_cleanup; + svn_cleanup.push_back("cleanup"); OutputLogger out(this->Log, "cleanup-out> "); OutputLogger err(this->Log, "cleanup-err> "); - this->RunChild(svn_cleanup, &out, &err); + this->RunSVNCommand(svn_cleanup, &out, &err); } //---------------------------------------------------------------------------- @@ -106,12 +106,13 @@ static bool cmCTestSVNPathStarts(std::string const& p1, std::string const& p2) std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo) { // Run "svn info" to get the repository info from the work tree. - const char* svn = this->CommandLineTool.c_str(); - const char* svn_info[] = {svn, "info", svninfo.LocalPath.c_str(), 0}; + std::vector<const char*> svn_info; + svn_info.push_back("info"); + svn_info.push_back(svninfo.LocalPath.c_str()); std::string rev; InfoParser out(this, "info-out> ", rev, svninfo); OutputLogger err(this->Log, "info-err> "); - this->RunChild(svn_info, &out, &err); + this->RunSVNCommand(svn_info, &out, &err); return rev; } @@ -285,19 +286,52 @@ bool cmCTestSVN::UpdateImpl() } std::vector<char const*> svn_update; - svn_update.push_back(this->CommandLineTool.c_str()); svn_update.push_back("update"); - svn_update.push_back("--non-interactive"); for(std::vector<cmStdString>::const_iterator ai = args.begin(); ai != args.end(); ++ai) { svn_update.push_back(ai->c_str()); } - svn_update.push_back(0); UpdateParser out(this, "up-out> "); OutputLogger err(this->Log, "up-err> "); - return this->RunUpdateCommand(&svn_update[0], &out, &err); + return this->RunSVNCommand(svn_update, &out, &err); +} + +//---------------------------------------------------------------------------- +bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters, + OutputParser* out, OutputParser* err) +{ + if(parameters.empty()) return false; + + std::vector<char const*> args; + args.push_back(this->CommandLineTool.c_str()); + + args.insert(args.end(), parameters.begin(), parameters.end()); + + args.push_back("--non-interactive"); + + std::string userOptions = + this->CTest->GetCTestConfiguration("SVNOptions"); + + std::vector<cmStdString> parsedUserOptions = + cmSystemTools::ParseArguments(userOptions.c_str()); + for(std::vector<cmStdString>::iterator i = parsedUserOptions.begin(); + i != parsedUserOptions.end(); ++i) + { + args.push_back(i->c_str()); + } + + args.push_back(0); + + if(strcmp(parameters[0], "update") == 0) + { + return RunUpdateCommand(&args[0], out, err); + } + else + { + return RunChild(&args[0], out, err); + } } //---------------------------------------------------------------------------- @@ -417,14 +451,15 @@ void cmCTestSVN::LoadRevisions(SVNInfo &svninfo) } // Run "svn log" to get all global revisions of interest. - const char* svn = this->CommandLineTool.c_str(); - const char* svn_log[] = {svn, "log", "--xml", "-v", revs.c_str(), - svninfo.LocalPath.c_str(), 0}; - { + std::vector<const char*> svn_log; + svn_log.push_back("log"); + svn_log.push_back("--xml"); + svn_log.push_back("-v"); + svn_log.push_back(revs.c_str()); + svn_log.push_back(svninfo.LocalPath.c_str()); LogParser out(this, "log-out> ", svninfo); OutputLogger err(this->Log, "log-err> "); - this->RunChild(svn_log, &out, &err); - } + this->RunSVNCommand(svn_log, &out, &err); } //---------------------------------------------------------------------------- @@ -492,11 +527,11 @@ private: void cmCTestSVN::LoadModifications() { // Run "svn status" which reports local modifications. - const char* svn = this->CommandLineTool.c_str(); - const char* svn_status[] = {svn, "status", "--non-interactive", 0}; + std::vector<const char*> svn_status; + svn_status.push_back("status"); StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); - this->RunChild(svn_status, &out, &err); + this->RunSVNCommand(svn_status, &out, &err); } //---------------------------------------------------------------------------- @@ -550,11 +585,11 @@ private: void cmCTestSVN::LoadExternals() { // Run "svn status" to get the list of external repositories - const char* svn = this->CommandLineTool.c_str(); - const char* svn_status[] = {svn, "status", 0}; + std::vector<const char*> svn_status; + svn_status.push_back("status"); ExternalParser out(this, "external-out> "); OutputLogger err(this->Log, "external-err> "); - this->RunChild(svn_status, &out, &err); + this->RunSVNCommand(svn_status, &out, &err); } //---------------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index 56265d0..c6548e3 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -33,6 +33,9 @@ private: virtual void NoteNewRevision(); virtual bool UpdateImpl(); + bool RunSVNCommand(std::vector<char const*> const& parameters, + OutputParser* out, OutputParser* err); + // Information about an SVN repository (root repository or external) struct SVNInfo { @@ -60,6 +63,7 @@ private: // Extended revision structure to include info about external it refers to. struct Revision; + friend struct Revision; // Info of all the repositories (root, externals and nested ones). std::list<SVNInfo> Repositories; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index ead449e..b796b83 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1304,9 +1304,10 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec) for ( it = vec.begin(); it != vec.end(); ++it ) { int retVal = 0; - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << *it + std::string cmd = cmSystemTools::ConvertToOutputPath(it->c_str()); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << cmd << std::endl); - if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0, + if ( !cmSystemTools::RunSingleCommand(cmd.c_str(), 0, &retVal, 0, cmSystemTools::OUTPUT_MERGE /*this->Verbose*/) || retVal != 0 ) { diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 8414349..2ca9f6c 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -44,6 +44,8 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "SVNUpdateOptions", "CTEST_SVN_UPDATE_OPTIONS"); this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, + "SVNOptions", "CTEST_SVN_OPTIONS"); + this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "BZRCommand", "CTEST_BZR_COMMAND"); this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "BZRUpdateOptions", "CTEST_BZR_UPDATE_OPTIONS"); diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 44e1dac..9dd0651 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -67,6 +67,9 @@ protected: virtual void NoteNewRevision(); virtual bool WriteXMLUpdates(std::ostream& xml); +#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510 +public: // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this +#endif /** Basic information about one revision of a tree or file. */ struct Revision { @@ -80,6 +83,7 @@ protected: std::string Log; }; +protected: struct File; friend struct File; diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index a1ffa20..29daffd 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -25,6 +25,8 @@ if (Qt5Widgets_FOUND) qt5_add_resources(${ARGN}) endmacro() set(QT_LIBRARIES ${Qt5Widgets_LIBRARIES}) + # Remove this when the minimum version of Qt is 4.6. + add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0) else() set(QT_MIN_VERSION "4.4.0") find_package(Qt4 REQUIRED) diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h index b11bff9..6a0cd9d 100644 --- a/Source/cmAddTestCommand.h +++ b/Source/cmAddTestCommand.h @@ -81,7 +81,7 @@ public: "\n" "Arguments after COMMAND may use \"generator expressions\" with the " "syntax \"$<...>\". " - CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS "Example usage:\n" " add_test(NAME mytest\n" " COMMAND testDriver --config $<CONFIGURATION>\n" diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 74c673a..445fd0e 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -12,7 +12,7 @@ #ifndef cmDocumentGeneratorExpressions_h #define cmDocumentGeneratorExpressions_h -#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \ +#define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \ "Generator expressions are evaluted during build system generation " \ "to produce information specific to each build configuration. " \ "Valid expressions are:\n" \ @@ -20,6 +20,12 @@ " $<1:...> = content of \"...\"\n" \ " $<CONFIG:cfg> = '1' if config is \"cfg\", else '0'\n" \ " $<CONFIGURATION> = configuration name\n" \ + " $<BOOL:...> = '1' if the '...' is true, else '0'\n" \ + " $<STREQUAL:a,b> = '1' if a is STREQUAL b, else '0'\n" \ + " $<ANGLE-R> = A literal '>'. Used to compare " \ + "strings which contain a '>' for example.\n" \ + " $<COMMA> = A literal ','. Used to compare " \ + "strings which contain a ',' for example.\n" \ " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \ " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \ " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \ @@ -29,6 +35,10 @@ " $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \ " $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \ " $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \ + "\n" \ + " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \ + "on the target tgt. Note that tgt is not added as a dependency of\n" \ + "the target this expression is evaluated on.\n" \ "Boolean expressions:\n" \ " $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \ " $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \ @@ -36,4 +46,11 @@ "where '?' is always either '0' or '1'.\n" \ "" +#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \ + CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \ + "Expressions with an implicit 'this' target:\n" \ + " $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \ + "the target on which the generator expression is evaluated.\n" \ + "" + #endif diff --git a/Source/cmDocumentLocationUndefined.h b/Source/cmDocumentLocationUndefined.h index d1be77a..9aecf21 100644 --- a/Source/cmDocumentLocationUndefined.h +++ b/Source/cmDocumentLocationUndefined.h @@ -16,8 +16,8 @@ "\n" \ "Do not set properties that affect the location of a target after " \ action ". These include properties whose names match " \ - "\"(RUNTIME|LIBRARY|ARCHIVE)_OUTPUT_(NAME|DIRECTORY)(_<CONFIG>)?\" " \ - "or \"(IMPLIB_)?(PREFIX|SUFFIX)\". " \ + "\"(RUNTIME|LIBRARY|ARCHIVE)_OUTPUT_(NAME|DIRECTORY)(_<CONFIG>)?\", " \ + "\"(IMPLIB_)?(PREFIX|SUFFIX)\", or \"LINKER_LANGUAGE\". " \ "Failure to follow this rule is not diagnosed and leaves the location " \ "of the target undefined." diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 5e7e081..8db0e8f 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -701,7 +701,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_SYSTEM_IGNORE_PATH", cmProperty::VARIABLE, "Path to be ignored by FIND_XXX() commands.", - "Specifies directories to be ignored by searches in FIND_XXX() commands " + "Specifies directories to be ignored by searches in FIND_XXX() " + "commands. " "This is useful in cross-compiled environments where some system " "directories contain incompatible but possibly linkable libraries. For " "example, on cross-compiled cluster environments, this allows a user to " @@ -716,7 +717,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_IGNORE_PATH", cmProperty::VARIABLE, "Path to be ignored by FIND_XXX() commands.", - "Specifies directories to be ignored by searches in FIND_XXX() commands " + "Specifies directories to be ignored by searches in FIND_XXX() " + "commands. " "This is useful in cross-compiled environments where some system " "directories contain incompatible but possibly linkable libraries. For " "example, on cross-compiled cluster environments, this allows a user to " @@ -1211,6 +1213,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Variables that Control the Build"); cm->DefineProperty + ("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE, + "Where to put all the MS debug symbol files.", + "This variable is used to initialize the " + "PDB_OUTPUT_DIRECTORY property on all the targets. " + "See that target property for additional information.", + false, + "Variables that Control the Build"); + + cm->DefineProperty ("CMAKE_AUTOMOC", cmProperty::VARIABLE, "Whether to handle moc automatically for Qt targets.", "This variable is used to initialize the " diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index c1360ef..debde3b 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -155,7 +155,7 @@ static const char *cmDocumentationStandardSeeAlso[][3] = static const char *cmDocumentationCopyright[][3] = { {0, - "Copyright 2000-2009 Kitware, Inc., Insight Software Consortium. " + "Copyright 2000-2012 Kitware, Inc., Insight Software Consortium. " "All rights reserved.", 0}, {0, "Redistribution and use in source and binary forms, with or without " diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 32595ee..fb3f39f 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -72,8 +72,9 @@ cmExportBuildFileGenerator if(!properties.empty()) { // Get the rest of the target details. + std::vector<std::string> missingTargets; this->SetImportDetailProperties(config, suffix, - target, properties); + target, properties, missingTargets); // TOOD: PUBLIC_HEADER_LOCATION // This should wait until the build feature propagation stuff @@ -82,6 +83,7 @@ cmExportBuildFileGenerator // properties); // Generate code in the export file. + this->GenerateMissingTargetsCheckCode(os, missingTargets); this->GenerateImportPropertyCode(os, config, target, properties); } } @@ -133,6 +135,25 @@ cmExportBuildFileGenerator //---------------------------------------------------------------------------- void +cmExportBuildFileGenerator::HandleMissingTarget( + std::string& link_libs, std::vector<std::string>&, + cmMakefile*, cmTarget* depender, cmTarget* dependee) +{ + // The target is not in the export. + if(!this->AppendMode) + { + // We are not appending, so all exported targets should be + // known here. This is probably user-error. + this->ComplainAboutMissingTarget(depender, dependee); + } + // Assume the target will be exported by another command. + // Append it with the export namespace. + link_libs += this->Namespace; + link_libs += dependee->GetName(); +} + +//---------------------------------------------------------------------------- +void cmExportBuildFileGenerator ::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee) diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 0f37626..726537b 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -45,8 +45,14 @@ protected: virtual void GenerateImportTargetsConfig(std::ostream& os, const char* config, std::string const& suffix); - virtual void ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee); + virtual void HandleMissingTarget(std::string& link_libs, + std::vector<std::string>& missingTargets, + cmMakefile* mf, + cmTarget* depender, + cmTarget* dependee); + + void ComplainAboutMissingTarget(cmTarget* depender, + cmTarget* dependee); /** Fill in properties indicating built file locations. */ void SetImportLocationProperty(const char* config, diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index eb19df5e..8dffae4 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -11,10 +11,15 @@ ============================================================================*/ #include "cmExportFileGenerator.h" +#include "cmExportSet.h" #include "cmGeneratedFileStream.h" +#include "cmGlobalGenerator.h" +#include "cmInstallExportGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmTargetExport.h" #include "cmVersion.h" #include <cmsys/auto_ptr.hxx> @@ -123,7 +128,9 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, void cmExportFileGenerator ::SetImportDetailProperties(const char* config, std::string const& suffix, - cmTarget* target, ImportPropertyMap& properties) + cmTarget* target, ImportPropertyMap& properties, + std::vector<std::string>& missingTargets + ) { // Get the makefile in which to lookup target information. cmMakefile* mf = target->GetMakefile(); @@ -159,13 +166,13 @@ cmExportFileGenerator { this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", - iface->Languages, properties); + iface->Languages, properties, missingTargets); this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", - iface->Libraries, properties); + iface->Libraries, properties, missingTargets); this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", - iface->SharedDeps, properties); + iface->SharedDeps, properties, missingTargets); if(iface->Multiplicity > 0) { std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; @@ -184,7 +191,9 @@ cmExportFileGenerator cmTarget* target, const char* propName, std::vector<std::string> const& libs, - ImportPropertyMap& properties) + ImportPropertyMap& properties, + std::vector<std::string>& missingTargets + ) { // Skip the property if there are no libraries. if(libs.empty()) @@ -224,17 +233,7 @@ cmExportFileGenerator } else { - // The target is not in the export. - if(!this->AppendMode) - { - // We are not appending, so all exported targets should be - // known here. This is probably user-error. - this->ComplainAboutMissingTarget(target, tgt); - } - // Assume the target will be exported by another command. - // Append it with the export namespace. - link_libs += this->Namespace; - link_libs += *li; + this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt); } } else @@ -250,6 +249,7 @@ cmExportFileGenerator properties[prop] = link_libs; } + //---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os, const char* config) @@ -381,6 +381,30 @@ cmExportFileGenerator //---------------------------------------------------------------------------- +void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os, + const std::vector<std::string>& missingTargets) +{ + os << "# Make sure the targets which have been exported in some other \n" + "# export set exist.\n"; + for(unsigned int i=0; i<missingTargets.size(); ++i) + { + os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n" + << " IF(CMAKE_FIND_PACKAGE_NAME)\n" + << " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n" + << " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE " + << "\"Required imported target \\\"" << missingTargets[i] + << "\\\" not found ! \")\n" + << " ELSE()\n" + << " MESSAGE(FATAL_ERROR \"Required imported target \\\"" + << missingTargets[i] << "\\\" not found ! \")\n" + << " ENDIF()\n" + << "ENDIF()\n"; + } + os << "\n"; +} + + +//---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) { diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index f271e55..70bc65d 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -60,17 +60,21 @@ protected: ImportPropertyMap const& properties, const std::set<std::string>& importedLocations); void GenerateImportedFileCheckLoop(std::ostream& os); + void GenerateMissingTargetsCheckCode(std::ostream& os, + const std::vector<std::string>& missingTargets); // Collect properties with detailed information about targets beyond // their location on disk. void SetImportDetailProperties(const char* config, std::string const& suffix, cmTarget* target, - ImportPropertyMap& properties); + ImportPropertyMap& properties, + std::vector<std::string>& missingTargets); void SetImportLinkProperty(std::string const& suffix, cmTarget* target, const char* propName, std::vector<std::string> const& libs, - ImportPropertyMap& properties); + ImportPropertyMap& properties, + std::vector<std::string>& missingTargets); /** Each subclass knows how to generate its kind of export file. */ virtual bool GenerateMainFile(std::ostream& os) = 0; @@ -80,10 +84,13 @@ protected: const char* config, std::string const& suffix) = 0; - /** Each subclass knows how to complain about a target that is - missing from an export set. */ - virtual void ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee) = 0; + /** Each subclass knows how to deal with a target that is missing from an + * export set. */ + virtual void HandleMissingTarget(std::string& link_libs, + std::vector<std::string>& missingTargets, + cmMakefile* mf, + cmTarget* depender, + cmTarget* dependee) = 0; // The namespace in which the exports are placed in the generated file. std::string Namespace; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index da14dd7..7841731 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -11,14 +11,19 @@ ============================================================================*/ #include "cmExportInstallFileGenerator.h" +#include "cmExportSet.h" +#include "cmExportSetMap.h" #include "cmGeneratedFileStream.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" #include "cmInstallExportGenerator.h" #include "cmInstallTargetGenerator.h" +#include "cmTargetExport.h" //---------------------------------------------------------------------------- cmExportInstallFileGenerator ::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen): - InstallExportGenerator(iegen) + IEGen(iegen) { } @@ -36,10 +41,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) { // Create all the imported targets. for(std::vector<cmTargetExport*>::const_iterator - tei = this->ExportSet->begin(); - tei != this->ExportSet->end(); ++tei) + tei = this->IEGen->GetExportSet()->GetTargetExports()->begin(); + tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) { - cmTargetExport* te = *tei; + cmTargetExport const* te = *tei; if(this->ExportedTargets.insert(te->Target).second) { this->GenerateImportTargetCode(os, te->Target); @@ -47,8 +52,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) else { cmOStringStream e; - e << "INSTALL(EXPORT \"" << this->Name << "\" ...) " - << "includes target \"" << te->Target->GetName() + e << "INSTALL(EXPORT \"" + << this->IEGen->GetExportSet()->GetName() + << "\" ...) " << "includes target \"" << te->Target->GetName() << "\" more than once in the export set."; cmSystemTools::Error(e.str().c_str()); return false; @@ -84,7 +90,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config) { // Skip configurations not enabled for this export. - if(!this->InstallExportGenerator->InstallsForConfig(config)) + if(!this->IEGen->InstallsForConfig(config)) { return true; } @@ -140,7 +146,7 @@ cmExportInstallFileGenerator { // Add code to compute the installation prefix relative to the // import file location. - const char* installDest = this->InstallExportGenerator->GetDestination(); + const char* installDest = this->IEGen->GetDestination(); if(!cmSystemTools::FileIsFullPath(installDest)) { std::string dest = installDest; @@ -161,11 +167,11 @@ cmExportInstallFileGenerator // Add each target in the set to the export. for(std::vector<cmTargetExport*>::const_iterator - tei = this->ExportSet->begin(); - tei != this->ExportSet->end(); ++tei) + tei = this->IEGen->GetExportSet()->GetTargetExports()->begin(); + tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) { // Collect import properties for this target. - cmTargetExport* te = *tei; + cmTargetExport const* te = *tei; ImportPropertyMap properties; std::set<std::string> importedLocations; this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator, @@ -185,8 +191,9 @@ cmExportInstallFileGenerator if(!properties.empty()) { // Get the rest of the target details. + std::vector<std::string> missingTargets; this->SetImportDetailProperties(config, suffix, - te->Target, properties); + te->Target, properties, missingTargets); // TOOD: PUBLIC_HEADER_LOCATION // This should wait until the build feature propagation stuff @@ -195,6 +202,7 @@ cmExportInstallFileGenerator // properties); // Generate code in the export file. + this->GenerateMissingTargetsCheckCode(os, missingTargets); this->GenerateImportPropertyCode(os, config, te->Target, properties); this->GenerateImportedFileChecksCode(os, te->Target, properties, importedLocations); @@ -306,12 +314,80 @@ cmExportInstallFileGenerator //---------------------------------------------------------------------------- void +cmExportInstallFileGenerator::HandleMissingTarget( + std::string& link_libs, std::vector<std::string>& missingTargets, + cmMakefile* mf, cmTarget* depender, cmTarget* dependee) +{ + std::string name = dependee->GetName(); + std::vector<std::string> namespaces = this->FindNamespaces(mf, name); + int targetOccurrences = (int)namespaces.size(); + if (targetOccurrences == 1) + { + std::string missingTarget = namespaces[0]; + missingTarget += name; + link_libs += missingTarget; + missingTargets.push_back(missingTarget); + } + else + { + // We are not appending, so all exported targets should be + // known here. This is probably user-error. + this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences); + } +} + +//---------------------------------------------------------------------------- +std::vector<std::string> +cmExportInstallFileGenerator +::FindNamespaces(cmMakefile* mf, const std::string& name) +{ + std::vector<std::string> namespaces; + cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator(); + const cmExportSetMap& exportSets = gg->GetExportSets(); + + for(cmExportSetMap::const_iterator expIt = exportSets.begin(); + expIt != exportSets.end(); + ++expIt) + { + const cmExportSet* exportSet = expIt->second; + std::vector<cmTargetExport*> const* targets = + exportSet->GetTargetExports(); + + bool containsTarget = false; + for(unsigned int i=0; i<targets->size(); i++) + { + if (name == (*targets)[i]->Target->GetName()) + { + containsTarget = true; + break; + } + } + + if (containsTarget) + { + std::vector<cmInstallExportGenerator const*> const* installs = + exportSet->GetInstallations(); + for(unsigned int i=0; i<installs->size(); i++) + { + namespaces.push_back((*installs)[i]->GetNamespace()); + } + } + } + + return namespaces; +} + + +//---------------------------------------------------------------------------- +void cmExportInstallFileGenerator ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen) { - const char* installDest = this->InstallExportGenerator->GetDestination(); + const char* installDest = this->IEGen->GetDestination(); cmOStringStream e; - e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute " + e << "INSTALL(EXPORT \"" + << this->IEGen->GetExportSet()->GetName() + << "\") given absolute " << "DESTINATION \"" << installDest << "\" but the export " << "references an installation of target \"" << itgen->GetTarget()->GetName() << "\" which has relative " @@ -322,12 +398,24 @@ cmExportInstallFileGenerator //---------------------------------------------------------------------------- void cmExportInstallFileGenerator -::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee) +::ComplainAboutMissingTarget(cmTarget* depender, + cmTarget* dependee, + int occurrences) { cmOStringStream e; - e << "INSTALL(EXPORT \"" << this->Name << "\" ...) " + e << "INSTALL(EXPORT \"" + << this->IEGen->GetExportSet()->GetName() + << "\" ...) " << "includes target \"" << depender->GetName() - << "\" which requires target \"" << dependee->GetName() - << "\" that is not in the export set."; + << "\" which requires target \"" << dependee->GetName() << "\" "; + if (occurrences == 0) + { + e << "that is not in the export set."; + } + else + { + e << "that is not in this export set, but " << occurrences + << " times in others."; + } cmSystemTools::Error(e.str().c_str()); } diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index fb678e8..e719ecc 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -18,6 +18,7 @@ class cmInstallExportGenerator; class cmInstallFilesGenerator; class cmInstallTargetGenerator; class cmTargetExport; +class cmExportSet; /** \class cmExportInstallFileGenerator * \brief Generate a file exporting targets from an install tree. @@ -40,15 +41,6 @@ public: files. */ cmExportInstallFileGenerator(cmInstallExportGenerator* iegen); - /** Set the name of the export associated with the files. This is - the name given to the install(EXPORT) command mode. */ - void SetName(const char* name) { this->Name = name; } - - /** Set the set of targets to be exported. These are the targets - associated with the export name. */ - void SetExportSet(std::vector<cmTargetExport*> const* eSet) - { this->ExportSet = eSet; } - /** Get the per-config file generated for each configuraiton. This maps from the configuration name to the file temporary location for installation. */ @@ -65,8 +57,19 @@ protected: virtual void GenerateImportTargetsConfig(std::ostream& os, const char* config, std::string const& suffix); - virtual void ComplainAboutMissingTarget(cmTarget* depender, - cmTarget* dependee); + virtual void HandleMissingTarget(std::string& link_libs, + std::vector<std::string>& missingTargets, + cmMakefile* mf, + cmTarget* depender, + cmTarget* dependee); + + void ComplainAboutMissingTarget(cmTarget* depender, + cmTarget* dependee, + int occurrences); + + std::vector<std::string> FindNamespaces(cmMakefile* mf, + const std::string& name); + /** Generate a per-configuration file for the targets. */ bool GenerateImportFileConfig(const char* config); @@ -81,9 +84,7 @@ protected: void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen); - cmInstallExportGenerator* InstallExportGenerator; - std::string Name; - std::vector<cmTargetExport*> const* ExportSet; + cmInstallExportGenerator* IEGen; std::string ImportPrefix; @@ -91,34 +92,4 @@ protected: std::map<cmStdString, cmStdString> ConfigImportFiles; }; -/* - cmTargetExport is used in cmGlobalGenerator to collect the install - generators for targets associated with an export. -*/ -class cmTargetExport -{ -public: - cmTargetExport(cmTarget* tgt, - cmInstallTargetGenerator* archive, - cmInstallTargetGenerator* runtime, - cmInstallTargetGenerator* library, - cmInstallTargetGenerator* framework, - cmInstallTargetGenerator* bundle, - cmInstallFilesGenerator* headers - ) : Target(tgt), ArchiveGenerator(archive), - RuntimeGenerator(runtime), LibraryGenerator(library), - FrameworkGenerator(framework), BundleGenerator(bundle), - HeaderGenerator(headers) {} - - cmTarget* Target; - cmInstallTargetGenerator* ArchiveGenerator; - cmInstallTargetGenerator* RuntimeGenerator; - cmInstallTargetGenerator* LibraryGenerator; - cmInstallTargetGenerator* FrameworkGenerator; - cmInstallTargetGenerator* BundleGenerator; - cmInstallFilesGenerator* HeaderGenerator; -private: - cmTargetExport(); -}; - #endif diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx new file mode 100644 index 0000000..33b0630 --- /dev/null +++ b/Source/cmExportSet.cxx @@ -0,0 +1,32 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 "cmExportSet.h" +#include "cmTargetExport.h" + +cmExportSet::~cmExportSet() +{ + for(unsigned int i = 0; i < this->TargetExports.size(); ++ i) + { + delete this->TargetExports[i]; + } +} + +void cmExportSet::AddTargetExport(cmTargetExport* te) +{ + this->TargetExports.push_back(te); +} + +void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation) +{ + this->Installations.push_back(installation); +} diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h new file mode 100644 index 0000000..a57aa12 --- /dev/null +++ b/Source/cmExportSet.h @@ -0,0 +1,46 @@ +/*============================================================================ + 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 cmExportSet_h +#define cmExportSet_h + +#include "cmSystemTools.h" +class cmTargetExport; +class cmInstallExportGenerator; + +/// A set of targets that were installed with the same EXPORT parameter. +class cmExportSet +{ +public: + /// Construct an empty export set named \a name + cmExportSet(const std::string &name) : Name(name) {} + /// Destructor + ~cmExportSet(); + + void AddTargetExport(cmTargetExport* tgt); + + void AddInstallation(cmInstallExportGenerator const* installation); + + std::string const& GetName() const { return this->Name; } + + std::vector<cmTargetExport*> const* GetTargetExports() const + { return &this->TargetExports; } + + std::vector<cmInstallExportGenerator const*> const* GetInstallations() const + { return &this->Installations; } + +private: + std::vector<cmTargetExport*> TargetExports; + std::string Name; + std::vector<cmInstallExportGenerator const*> Installations; +}; + +#endif diff --git a/Source/cmExportSetMap.cxx b/Source/cmExportSetMap.cxx new file mode 100644 index 0000000..96fdb3e --- /dev/null +++ b/Source/cmExportSetMap.cxx @@ -0,0 +1,34 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 "cmExportSetMap.h" +#include "cmExportSet.h" + +cmExportSet* cmExportSetMap::operator[](const std::string &name) +{ + std::map<std::string, cmExportSet*>::iterator it = this->find(name); + if (it == this->end()) // Export set not found + { + it = this->insert(std::make_pair(name, new cmExportSet(name))).first; + } + return it->second; +} + +cmExportSetMap::~cmExportSetMap() +{ + for(std::map<std::string, cmExportSet*>::iterator it = this->begin(); + it != this->end(); + ++ it) + { + delete it->second; + } +} diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h new file mode 100644 index 0000000..4663c55 --- /dev/null +++ b/Source/cmExportSetMap.h @@ -0,0 +1,33 @@ +/*============================================================================ + 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 cmExportSetMap_h +#define cmExportSetMap_h + +#include "cmSystemTools.h" +class cmExportSet; + +/// A name -> cmExportSet map with overloaded operator[]. +class cmExportSetMap : public std::map<std::string, cmExportSet*> +{ +public: + /** \brief Overloaded operator[]. + * + * The operator is overloaded because cmExportSet has no default constructor: + * we do not want unnamed export sets. + */ + cmExportSet* operator[](const std::string &name); + + /// Overloaded destructor deletes all member export sets. + ~cmExportSetMap(); +}; + +#endif diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index ad4ab76..25b13e5 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -617,14 +617,17 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, " <Option compiler=\"" << compiler << "\" />\n" " <Compiler>\n"; + cmGeneratorTarget *gtgt = this->GlobalGenerator + ->GetGeneratorTarget(target); + // the compilerdefines for this target - const char* cdefs = target->GetMakefile()->GetProperty( - "COMPILE_DEFINITIONS"); - if(cdefs) + std::string cdefs = gtgt->GetCompileDefinitions(); + + if(!cdefs.empty()) { // Expand the list. std::vector<std::string> defs; - cmSystemTools::ExpandListArgument(cdefs, defs); + cmSystemTools::ExpandListArgument(cdefs.c_str(), defs); for(std::vector<std::string>::const_iterator di = defs.begin(); di != defs.end(); ++di) { @@ -633,57 +636,59 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, } } - // the include directories for this target - std::set<std::string> uniqIncludeDirs; + // the include directories for this target + std::set<std::string> uniqIncludeDirs; + + std::vector<std::string> includes; + const char *config = target->GetMakefile() + ->GetDefinition("CMAKE_BUILD_TYPE"); + target->GetMakefile()->GetLocalGenerator()-> + GetIncludeDirectories(includes, gtgt, "C", config); + for(std::vector<std::string>::const_iterator dirIt=includes.begin(); + dirIt != includes.end(); + ++dirIt) + { + uniqIncludeDirs.insert(*dirIt); + } - std::vector<std::string> includes; - target->GetMakefile()->GetLocalGenerator()-> - GetIncludeDirectories(includes, target); - for(std::vector<std::string>::const_iterator dirIt=includes.begin(); - dirIt != includes.end(); + std::string systemIncludeDirs = makefile->GetSafeDefinition( + "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); + if (!systemIncludeDirs.empty()) + { + std::vector<std::string> dirs; + cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs); + for(std::vector<std::string>::const_iterator dirIt=dirs.begin(); + dirIt != dirs.end(); ++dirIt) { uniqIncludeDirs.insert(*dirIt); } + } - std::string systemIncludeDirs = makefile->GetSafeDefinition( - "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); - if (!systemIncludeDirs.empty()) - { - std::vector<std::string> dirs; - cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs); - for(std::vector<std::string>::const_iterator dirIt=dirs.begin(); - dirIt != dirs.end(); - ++dirIt) - { - uniqIncludeDirs.insert(*dirIt); - } - } - - systemIncludeDirs = makefile->GetSafeDefinition( - "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); - if (!systemIncludeDirs.empty()) - { - std::vector<std::string> dirs; - cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs); - for(std::vector<std::string>::const_iterator dirIt=dirs.begin(); - dirIt != dirs.end(); - ++dirIt) - { - uniqIncludeDirs.insert(*dirIt); - } - } - - for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin(); - dirIt != uniqIncludeDirs.end(); + systemIncludeDirs = makefile->GetSafeDefinition( + "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); + if (!systemIncludeDirs.empty()) + { + std::vector<std::string> dirs; + cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs); + for(std::vector<std::string>::const_iterator dirIt=dirs.begin(); + dirIt != dirs.end(); ++dirIt) { - fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n"; + uniqIncludeDirs.insert(*dirIt); } + } - fout<<" </Compiler>\n"; + for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin(); + dirIt != uniqIncludeDirs.end(); + ++dirIt) + { + fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n"; } - else // e.g. all and the GLOBAL and UTILITY targets + + fout<<" </Compiler>\n"; + } + else // e.g. all and the GLOBAL and UTILITY targets { fout<<" <Option working_dir=\"" << makefile->GetStartOutputDirectory() << "\" />\n" diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 1f976f7..96b8a09 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -884,11 +884,18 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) { - cmTargets & targets = (*it)->GetMakefile()->GetTargets(); - for (cmTargets::iterator l = targets.begin(); l != targets.end(); ++l) + cmGeneratorTargetsType targets = (*it)->GetMakefile() + ->GetGeneratorTargets(); + for (cmGeneratorTargetsType::iterator l = targets.begin(); + l != targets.end(); ++l) { + if (l->first->IsImported()) + { + continue; + } std::vector<std::string> includeDirs; - (*it)->GetIncludeDirectories(includeDirs, &l->second); + const char *config = mf->GetDefinition("CMAKE_BUILD_TYPE"); + (*it)->GetIncludeDirectories(includeDirs, l->second, "C", config); this->AppendIncludeDirectories(fout, includeDirs, emmited); } } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 2bc4290..8de24b3 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2767,30 +2767,31 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) else if(*i == "EXPECTED_HASH") { ++i; - if(i != args.end()) + if(i == args.end()) { - hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New(i->c_str())); - if(!hash.get()) - { - std::string err = "DOWNLOAD bad SHA type: "; - err += *i; - this->SetError(err.c_str()); - return false; - } - hashMatchMSG = *i; - hashMatchMSG += " hash"; - - ++i; + this->SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH."); + return false; } - if(i != args.end()) + std::string::size_type pos = i->find("="); + if(pos == std::string::npos) { - expectedHash = cmSystemTools::LowerCase(*i); + std::string err = + "DOWNLOAD EXPECTED_HASH expects ALGO=value but got: "; + err += *i; + this->SetError(err.c_str()); + return false; } - else + std::string algo = i->substr(0, pos); + expectedHash = cmSystemTools::LowerCase(i->substr(pos+1)); + hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New(algo.c_str())); + if(!hash.get()) { - this->SetError("DOWNLOAD missing time for EXPECTED_HASH."); + std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: "; + err += algo; + this->SetError(err.c_str()); return false; } + hashMatchMSG = algo + " hash"; } ++i; } diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index bd6f612..b4aa903 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -83,8 +83,7 @@ public: " file(TO_NATIVE_PATH path result)\n" " file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]\n" - " [EXPECTED_HASH MD5|SHA1|SHA224|SHA256|SHA384|SHA512 hash]\n" - " [EXPECTED_MD5 sum]\n" + " [EXPECTED_HASH ALGO=value] [EXPECTED_MD5 sum]\n" " [TLS_VERIFY on|off] [TLS_CAINFO file])\n" " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" @@ -170,10 +169,11 @@ public: "timeout after time seconds, time should be specified as an integer. " "The INACTIVITY_TIMEOUT specifies an integer number of seconds of " "inactivity after which the operation should terminate. " - "If EXPECTED_HASH is specified, the operation will verify that the " - "downloaded file's actual hash matches the expected value. If it " - "does not match, the operation fails with an error. " - "(EXPECTED_MD5 is short-hand for EXPECTED_HASH MD5.) " + "If EXPECTED_HASH ALGO=value is specified, the operation will verify " + "that the downloaded file's actual hash matches the expected value, " + "where ALGO is one of MD5, SHA1, SHA224, SHA256, SHA384, or SHA512. " + "If it does not match, the operation fails with an error. " + "(\"EXPECTED_MD5 sum\" is short-hand for \"EXPECTED_HASH MD5=sum\".) " "If SHOW_PROGRESS is specified, progress information will be printed " "as status messages until the operation is complete. " "For https URLs CMake must be built with OpenSSL. " diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index be47f95..470ceca 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -840,6 +840,8 @@ bool cmFindPackageCommand //---------------------------------------------------------------------------- void cmFindPackageCommand::SetModuleVariables(const std::string& components) { + this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name.c_str()); + // Store the list of components. std::string components_var = this->Name + "_FIND_COMPONENTS"; this->AddFindDefinition(components_var.c_str(), components.c_str()); @@ -1016,6 +1018,9 @@ bool cmFindPackageCommand::HandlePackageMode() std::string foundVar = this->Name; foundVar += "_FOUND"; + std::string notFoundMessageVar = this->Name; + notFoundMessageVar += "_NOT_FOUND_MESSAGE"; + std::string notFoundMessage; // If the directory for the config file was found, try to read the file. bool result = true; @@ -1033,6 +1038,7 @@ bool cmFindPackageCommand::HandlePackageMode() // has set Foo_FOUND to FALSE itself: this->Makefile->RemoveDefinition(foundVar.c_str()); } + this->Makefile->RemoveDefinition(notFoundMessageVar.c_str()); // Set the version variables before loading the config file. // It may override them. @@ -1051,6 +1057,8 @@ bool cmFindPackageCommand::HandlePackageMode() // we get here if the Config file has set Foo_FOUND actively to FALSE found = false; configFileSetFOUNDFalse = true; + notFoundMessage = this->Makefile->GetSafeDefinition( + notFoundMessageVar.c_str()); } } else @@ -1071,6 +1079,10 @@ bool cmFindPackageCommand::HandlePackageMode() " " << this->FileFound << "\n" "but it set " << foundVar << " to FALSE so package \"" << this->Name << "\" is considered to be NOT FOUND."; + if (!notFoundMessage.empty()) + { + e << " Reason given by package: \n" << notFoundMessage << "\n"; + } } // If there are files in ConsideredConfigs, it means that FooConfig.cmake // have been found, but they didn't have appropriate versions. diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 0885616..7d8df37 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -13,12 +13,14 @@ #include "cmMakefile.h" #include "cmTarget.h" +#include "assert.h" #include <cmsys/String.h> #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionLexer.h" #include "cmGeneratorExpressionParser.h" +#include "cmGeneratorExpressionDAGChecker.h" //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( @@ -65,7 +67,9 @@ cmGeneratorExpression::~cmGeneratorExpression() //---------------------------------------------------------------------------- const char *cmCompiledGeneratorExpression::Evaluate( - cmMakefile* mf, const char* config, bool quiet) const + cmMakefile* mf, const char* config, bool quiet, + cmGeneratorTarget *target, + cmGeneratorExpressionDAGChecker *dagChecker) const { if (!this->NeedsParsing) { @@ -84,11 +88,12 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Config = config; context.Quiet = quiet; context.HadError = false; + context.Target = target; context.Backtrace = this->Backtrace; for ( ; it != end; ++it) { - this->Output += (*it)->Evaluate(&context); + this->Output += (*it)->Evaluate(&context, dagChecker); if (context.HadError) { this->Output = ""; @@ -125,3 +130,51 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() delete *it; } } + +std::string cmGeneratorExpression::Preprocess(const std::string &input, + PreprocessContext context) +{ + if (context != StripAllGeneratorExpressions) + { + assert(!"cmGeneratorExpression::Preprocess called with invalid args"); + return std::string(); + } + + std::string result; + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + while((pos = input.find("$<", lastPos)) != input.npos) + { + result += input.substr(lastPos, pos - lastPos); + pos += 2; + int nestingLevel = 1; + const char *c = input.c_str() + pos; + const char * const cStart = c; + for ( ; *c; ++c) + { + if(c[0] == '$' && c[1] == '<') + { + ++nestingLevel; + ++c; + continue; + } + if(c[0] == '>') + { + --nestingLevel; + if (nestingLevel == 0) + { + break; + } + } + } + const std::string::size_type traversed = (c - cStart) + 1; + if (!*c) + { + result += "$<" + input.substr(pos, traversed); + } + pos += traversed; + lastPos = pos; + } + result += input.substr(lastPos); + return result; +} diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index b8467c2..29d3f44 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -9,6 +9,10 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ + +#ifndef cmGeneratorExpression_h +#define cmGeneratorExpression_h + #include "cmStandardIncludes.h" #include <stack> @@ -16,10 +20,12 @@ #include <cmsys/RegularExpression.hxx> class cmTarget; +class cmGeneratorTarget; class cmMakefile; class cmListFileBacktrace; struct cmGeneratorExpressionEvaluator; +struct cmGeneratorExpressionDAGChecker; class cmCompiledGeneratorExpression; @@ -42,6 +48,13 @@ public: const cmCompiledGeneratorExpression& Parse(std::string const& input); const cmCompiledGeneratorExpression& Parse(const char* input); + enum PreprocessContext { + StripAllGeneratorExpressions + }; + + static std::string Preprocess(const std::string &input, + PreprocessContext context); + private: cmGeneratorExpression(const cmGeneratorExpression &); void operator=(const cmGeneratorExpression &); @@ -54,7 +67,9 @@ class cmCompiledGeneratorExpression { public: const char* Evaluate(cmMakefile* mf, const char* config, - bool quiet = false) const; + bool quiet = false, + cmGeneratorTarget *target = 0, + cmGeneratorExpressionDAGChecker *dagChecker = 0) const; /** Get set of targets found during evaluations. */ std::set<cmTarget*> const& GetTargets() const @@ -80,3 +95,5 @@ private: mutable std::set<cmTarget*> Targets; mutable std::string Output; }; + +#endif diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx new file mode 100644 index 0000000..bfb0ddf --- /dev/null +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -0,0 +1,106 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 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. +============================================================================*/ + +#include "cmGeneratorExpressionDAGChecker.h" + +#include "cmMakefile.h" + +//---------------------------------------------------------------------------- +cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( + const cmListFileBacktrace &backtrace, + const std::string &target, + const std::string &property, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *parent) + : Parent(parent), Target(target), Property(property), + Content(content), Backtrace(backtrace) +{ + this->IsDAG = this->isDAG(); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::check() const +{ + return this->IsDAG; +} + +//---------------------------------------------------------------------------- +void cmGeneratorExpressionDAGChecker::reportError( + cmGeneratorExpressionContext *context, + const std::string &expr) +{ + if (this->IsDAG) + { + return; + } + + context->HadError = true; + if (context->Quiet) + { + return; + } + + const cmGeneratorExpressionDAGChecker *parent = this->Parent; + + if (parent && !parent->Parent) + { + cmOStringStream e; + e << "Error evaluating generator expression:\n" + << " " << expr << "\n" + << "Self reference on target \"" + << context->Target->GetName() << "\".\n"; + context->Makefile->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), + parent->Backtrace); + return; + } + + { + cmOStringStream e; + e << "Error evaluating generator expression:\n" + << " " << expr << "\n" + << "Dependency loop found."; + context->Makefile->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), + context->Backtrace); + } + + int loopStep = 1; + while (parent) + { + cmOStringStream e; + e << "Loop step " << loopStep << "\n" + << " " + << (parent->Content ? parent->Content->GetOriginalExpression() : expr) + << "\n"; + context->Makefile->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), + parent->Backtrace); + parent = parent->Parent; + ++loopStep; + } +} + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::isDAG() const +{ + const cmGeneratorExpressionDAGChecker *parent = this->Parent; + while (parent) + { + if (this->Target == parent->Target && this->Property == parent->Property) + { + return false; + } + parent = parent->Parent; + } + return true; +} diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h new file mode 100644 index 0000000..ffc84f8 --- /dev/null +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -0,0 +1,44 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 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 cmGeneratorExpressionDAGChecker_h +#define cmGeneratorExpressionDAGChecker_h + +#include "cmStandardIncludes.h" + +#include "cmGeneratorExpressionEvaluator.h" + +//---------------------------------------------------------------------------- +struct cmGeneratorExpressionDAGChecker +{ + cmGeneratorExpressionDAGChecker(const cmListFileBacktrace &backtrace, + const std::string &target, + const std::string &property, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *parent); + + bool check() const; + + void reportError(cmGeneratorExpressionContext *context, + const std::string &expr); +private: + bool isDAG() const; + +private: + const cmGeneratorExpressionDAGChecker * const Parent; + const std::string Target; + const std::string Property; + const GeneratorExpressionContent * const Content; + const cmListFileBacktrace Backtrace; + bool IsDAG; +}; + +#endif diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index acc844a..2e123a4 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -13,9 +13,16 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionParser.h" +#include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorExpression.h" + +#include <cmsys/String.h> //---------------------------------------------------------------------------- -static void reportError(cmGeneratorExpressionContext *context, +#if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510 +static +#endif +void reportError(cmGeneratorExpressionContext *context, const std::string &expr, const std::string &result) { context->HadError = true; @@ -47,7 +54,8 @@ struct cmGeneratorExpressionNode virtual std::string Evaluate(const std::vector<std::string> ¶meters, cmGeneratorExpressionContext *context, - const GeneratorExpressionContent *content + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker ) const = 0; }; @@ -60,7 +68,8 @@ static const struct ZeroNode : public cmGeneratorExpressionNode std::string Evaluate(const std::vector<std::string> &, cmGeneratorExpressionContext *, - const GeneratorExpressionContent *) const + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const { // Unreachable return std::string(); @@ -76,7 +85,8 @@ static const struct OneNode : public cmGeneratorExpressionNode std::string Evaluate(const std::vector<std::string> &, cmGeneratorExpressionContext *, - const GeneratorExpressionContent *) const + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const { // Unreachable return std::string(); @@ -93,7 +103,8 @@ static const struct OP ## Node : public cmGeneratorExpressionNode \ \ std::string Evaluate(const std::vector<std::string> ¶meters, \ cmGeneratorExpressionContext *context, \ - const GeneratorExpressionContent *content) const \ + const GeneratorExpressionContent *content, \ + cmGeneratorExpressionDAGChecker *) const \ { \ std::vector<std::string>::const_iterator it = parameters.begin(); \ const std::vector<std::string>::const_iterator end = parameters.end(); \ @@ -123,9 +134,11 @@ BOOLEAN_OP_NODE(orNode, OR, 0, 1) static const struct NotNode : public cmGeneratorExpressionNode { NotNode() {} + std::string Evaluate(const std::vector<std::string> ¶meters, cmGeneratorExpressionContext *context, - const GeneratorExpressionContent *content) const + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const { if (*parameters.begin() != "0" && *parameters.begin() != "1") { @@ -138,14 +151,80 @@ static const struct NotNode : public cmGeneratorExpressionNode } notNode; //---------------------------------------------------------------------------- +static const struct BoolNode : public cmGeneratorExpressionNode +{ + BoolNode() {} + + virtual int NumExpectedParameters() const { return 1; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0"; + } +} boolNode; + +//---------------------------------------------------------------------------- +static const struct StrEqualNode : public cmGeneratorExpressionNode +{ + StrEqualNode() {} + + virtual int NumExpectedParameters() const { return 2; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return *parameters.begin() == parameters[1] ? "1" : "0"; + } +} strEqualNode; + +//---------------------------------------------------------------------------- +static const struct Angle_RNode : public cmGeneratorExpressionNode +{ + Angle_RNode() {} + + virtual int NumExpectedParameters() const { return 0; } + + std::string Evaluate(const std::vector<std::string> &, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return ">"; + } +} angle_rNode; + +//---------------------------------------------------------------------------- +static const struct CommaNode : public cmGeneratorExpressionNode +{ + CommaNode() {} + + virtual int NumExpectedParameters() const { return 0; } + + std::string Evaluate(const std::vector<std::string> &, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return ","; + } +} commaNode; + +//---------------------------------------------------------------------------- static const struct ConfigurationNode : public cmGeneratorExpressionNode { ConfigurationNode() {} + virtual int NumExpectedParameters() const { return 0; } std::string Evaluate(const std::vector<std::string> &, cmGeneratorExpressionContext *context, - const GeneratorExpressionContent *) const + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const { return context->Config ? context->Config : ""; } @@ -160,13 +239,9 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode std::string Evaluate(const std::vector<std::string> ¶meters, cmGeneratorExpressionContext *context, - const GeneratorExpressionContent *content) const + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const { - if (!context->Config) - { - return std::string(); - } - cmsys::RegularExpression configValidator; configValidator.compile("^[A-Za-z0-9_]*$"); if (!configValidator.find(parameters.begin()->c_str())) @@ -175,11 +250,123 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } - return *parameters.begin() == context->Config ? "1" : "0"; + if (!context->Config) + { + return parameters.front().empty() ? "1" : "0"; + } + + return cmsysString_strcasecmp(parameters.begin()->c_str(), + context->Config) == 0 ? "1" : "0"; } } configurationTestNode; //---------------------------------------------------------------------------- +static const struct TargetPropertyNode : public cmGeneratorExpressionNode +{ + TargetPropertyNode() {} + + // This node handles errors on parameter count itself. + virtual int NumExpectedParameters() const { return -1; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagCheckerParent + ) const + { + if (parameters.size() != 1 && parameters.size() != 2) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_PROPERTY:...> expression requires one or two parameters"); + return std::string(); + } + cmsys::RegularExpression targetNameValidator; + // The ':' is supported to allow use with IMPORTED targets. At least + // Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter. + targetNameValidator.compile("^[A-Za-z0-9_.:-]+$"); + cmsys::RegularExpression propertyNameValidator; + propertyNameValidator.compile("^[A-Za-z0-9_]+$"); + + cmGeneratorTarget* target = context->Target; + std::string propertyName = *parameters.begin(); + if (parameters.size() == 2) + { + if (parameters.begin()->empty() && parameters[1].empty()) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty " + "target name and property name."); + return std::string(); + } + if (parameters.begin()->empty()) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty " + "target name."); + return std::string(); + } + + std::string targetName = parameters.front(); + propertyName = parameters[1]; + if (!targetNameValidator.find(targetName.c_str())) + { + if (!propertyNameValidator.find(propertyName.c_str())) + { + ::reportError(context, content->GetOriginalExpression(), + "Target name and property name not supported."); + return std::string(); + } + ::reportError(context, content->GetOriginalExpression(), + "Target name not supported."); + return std::string(); + } + target = context->Makefile->FindGeneratorTargetToUse( + targetName.c_str()); + + if (!target) + { + cmOStringStream e; + e << "Target \"" + << targetName + << "\" not found."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + } + + if (propertyName.empty()) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_PROPERTY:...> expression requires a non-empty property " + "name."); + return std::string(); + } + + if (!propertyNameValidator.find(propertyName.c_str())) + { + ::reportError(context, content->GetOriginalExpression(), + "Property name not supported."); + return std::string(); + } + + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, + target->GetName(), + propertyName, + content, + dagCheckerParent); + + if (!dagChecker.check()) + { + dagChecker.reportError(context, content->GetOriginalExpression()); + return std::string(); + } + + const char *prop = target->GetProperty(propertyName.c_str()); + return prop ? prop : ""; + } +} targetPropertyNode; + +//---------------------------------------------------------------------------- template<bool linker, bool soname> struct TargetFilesystemArtifactResultCreator { @@ -293,13 +480,15 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode std::string Evaluate(const std::vector<std::string> ¶meters, cmGeneratorExpressionContext *context, - const GeneratorExpressionContent *content) const + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const { // Lookup the referenced target. std::string name = *parameters.begin(); cmsys::RegularExpression targetValidator; - targetValidator.compile("^[A-Za-z0-9_]+$"); + // The ':' is supported to allow use with IMPORTED targets. + targetValidator.compile("^[A-Za-z0-9_.:-]+$"); if (!targetValidator.find(name.c_str())) { ::reportError(context, content->GetOriginalExpression(), @@ -392,7 +581,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &targetLinkerFileDirNode; else if (identifier == "TARGET_SONAME_FILE_DIR") return &targetSoNameFileDirNode; + else if (identifier == "STREQUAL") + return &strEqualNode; + else if (identifier == "BOOL") + return &boolNode; + else if (identifier == "ANGLE-R") + return &angle_rNode; + else if (identifier == "COMMA") + return &commaNode; + else if (identifier == "TARGET_PROPERTY") + return &targetPropertyNode; return 0; + } //---------------------------------------------------------------------------- @@ -412,7 +612,8 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const //---------------------------------------------------------------------------- std::string GeneratorExpressionContent::Evaluate( - cmGeneratorExpressionContext *context) const + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker) const { std::string identifier; { @@ -422,7 +623,7 @@ std::string GeneratorExpressionContent::Evaluate( = this->IdentifierChildren.end(); for ( ; it != end; ++it) { - identifier += (*it)->Evaluate(context); + identifier += (*it)->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -465,7 +666,7 @@ std::string GeneratorExpressionContent::Evaluate( = pit->end(); for ( ; it != end; ++it) { - result += (*it)->Evaluate(context); + result += (*it)->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -491,7 +692,7 @@ std::string GeneratorExpressionContent::Evaluate( pit->end(); for ( ; it != end; ++it) { - parameter += (*it)->Evaluate(context); + parameter += (*it)->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -534,7 +735,7 @@ std::string GeneratorExpressionContent::Evaluate( return std::string(); } - return node->Evaluate(parameters, context, this); + return node->Evaluate(parameters, context, this, dagChecker); } //---------------------------------------------------------------------------- diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 5163ca0..04a2acd 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -15,6 +15,11 @@ #include <vector> #include <string> +#include "cmListFileCache.h" + +class cmTarget; +class cmGeneratorTarget; + //---------------------------------------------------------------------------- struct cmGeneratorExpressionContext { @@ -22,11 +27,13 @@ struct cmGeneratorExpressionContext std::set<cmTarget*> Targets; cmMakefile *Makefile; const char *Config; - cmTarget *Target; + cmGeneratorTarget *Target; bool Quiet; bool HadError; }; +struct cmGeneratorExpressionDAGChecker; + //---------------------------------------------------------------------------- struct cmGeneratorExpressionEvaluator { @@ -41,8 +48,8 @@ struct cmGeneratorExpressionEvaluator virtual Type GetType() const = 0; - virtual std::string Evaluate(cmGeneratorExpressionContext *context - ) const = 0; + virtual std::string Evaluate(cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *) const = 0; private: cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator &); @@ -57,7 +64,8 @@ struct TextContent : public cmGeneratorExpressionEvaluator } - std::string Evaluate(cmGeneratorExpressionContext *) const + std::string Evaluate(cmGeneratorExpressionContext *, + cmGeneratorExpressionDAGChecker *) const { return std::string(this->Content, this->Length); } @@ -102,7 +110,8 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator return cmGeneratorExpressionEvaluator::Generator; } - std::string Evaluate(cmGeneratorExpressionContext *context) const; + std::string Evaluate(cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *) const; std::string GetOriginalExpression() const; diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index 2a5cc7a..7a8fc51 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -14,6 +14,8 @@ #include "cmGeneratorExpressionEvaluator.h" +#include "assert.h" + //---------------------------------------------------------------------------- cmGeneratorExpressionParser::cmGeneratorExpressionParser( const std::vector<cmGeneratorExpressionToken> &tokens) @@ -75,6 +77,7 @@ static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result, void cmGeneratorExpressionParser::ParseGeneratorExpression( std::vector<cmGeneratorExpressionEvaluator*> &result) { + assert(this->it != this->Tokens.end()); unsigned int nestedLevel = this->NestingLevel; ++this->NestingLevel; @@ -96,12 +99,14 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( // ERROR } - if (this->it->TokenType == cmGeneratorExpressionToken::EndExpression) + if (this->it != this->Tokens.end() && + this->it->TokenType == cmGeneratorExpressionToken::EndExpression) { GeneratorExpressionContent *content = new GeneratorExpressionContent( startToken->Content, this->it->Content - startToken->Content + this->it->Length); + assert(this->it != this->Tokens.end()); ++this->it; --this->NestingLevel; content->SetIdentifier(identifier); @@ -113,34 +118,60 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator> commaTokens; std::vector<cmGeneratorExpressionToken>::const_iterator colonToken; - if (this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) + if (this->it != this->Tokens.end() && + this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) { colonToken = this->it; parameters.resize(parameters.size() + 1); + assert(this->it != this->Tokens.end()); ++this->it; - while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression) + + while (this->it != this->Tokens.end() && + this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) + { + commaTokens.push_back(this->it); + parameters.resize(parameters.size() + 1); + assert(this->it != this->Tokens.end()); + ++this->it; + } + while (this->it != this->Tokens.end() && + this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) + { + extendText(*(parameters.end() - 1), this->it); + assert(this->it != this->Tokens.end()); + ++this->it; + } + while (this->it != this->Tokens.end() && + this->it->TokenType != cmGeneratorExpressionToken::EndExpression) { this->ParseContent(*(parameters.end() - 1)); - if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) + if (this->it == this->Tokens.end()) + { + break; + } + while (this->it != this->Tokens.end() && + this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) { commaTokens.push_back(this->it); parameters.resize(parameters.size() + 1); + assert(this->it != this->Tokens.end()); ++this->it; } - if (this->it == this->Tokens.end()) + while (this->it != this->Tokens.end() && + this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) { - break; + extendText(*(parameters.end() - 1), this->it); + assert(this->it != this->Tokens.end()); + ++this->it; } } - if(this->it->TokenType == cmGeneratorExpressionToken::EndExpression) + if(this->it != this->Tokens.end() + && this->it->TokenType == cmGeneratorExpressionToken::EndExpression) { --this->NestingLevel; + assert(this->it != this->Tokens.end()); ++this->it; } - if (parameters.empty()) - { - // ERROR - } } if (nestedLevel != this->NestingLevel) @@ -161,6 +192,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.end(); std::vector<TokenVector::const_iterator>::const_iterator commaIt = commaTokens.begin(); + assert(parameters.size() > commaTokens.size()); for ( ; pit != pend; ++pit, ++commaIt) { extendResult(result, *pit); @@ -168,6 +200,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( { extendText(result, *commaIt); } + else + { + break; + } } } return; @@ -187,6 +223,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( void cmGeneratorExpressionParser::ParseContent( std::vector<cmGeneratorExpressionEvaluator*> &result) { + assert(this->it != this->Tokens.end()); switch(this->it->TokenType) { case cmGeneratorExpressionToken::Text: @@ -203,6 +240,7 @@ void cmGeneratorExpressionParser::ParseContent( TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1)); textContent->Extend(this->it->Length); + assert(this->it != this->Tokens.end()); ++this->it; return; } @@ -210,10 +248,12 @@ void cmGeneratorExpressionParser::ParseContent( cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content, this->it->Length); result.push_back(n); + assert(this->it != this->Tokens.end()); ++this->it; return ; } case cmGeneratorExpressionToken::BeginExpression: + assert(this->it != this->Tokens.end()); ++this->it; this->ParseGeneratorExpression(result); return; @@ -226,10 +266,11 @@ void cmGeneratorExpressionParser::ParseContent( } else { - // TODO: Unreachable. Assert? + assert(!"Got unexpected syntax token."); } + assert(this->it != this->Tokens.end()); ++this->it; return; } - // Unreachable. Assert? + assert(!"Unhandled token in generator expression."); } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6e2e23d..19b55c6 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -14,8 +14,13 @@ #include "cmTarget.h" #include "cmMakefile.h" #include "cmLocalGenerator.h" +#include "cmComputeLinkInformation.h" #include "cmGlobalGenerator.h" #include "cmSourceFile.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionDAGChecker.h" + +#include <assert.h> //---------------------------------------------------------------------------- cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) @@ -27,6 +32,45 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) this->LookupObjectLibraries(); } +cmGeneratorTarget::~cmGeneratorTarget() +{ + for(std::map<cmStdString, cmComputeLinkInformation*>::iterator i + = LinkInformation.begin(); i != LinkInformation.end(); ++i) + { + delete i->second; + } +} + +//---------------------------------------------------------------------------- +int cmGeneratorTarget::GetType() const +{ + return this->Target->GetType(); +} + +//---------------------------------------------------------------------------- +const char *cmGeneratorTarget::GetName() const +{ + return this->Target->GetName(); +} + +//---------------------------------------------------------------------------- +const char *cmGeneratorTarget::GetProperty(const char *prop) +{ + return this->Target->GetProperty(prop); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::GetPropertyAsBool(const char *prop) +{ + return this->Target->GetPropertyAsBool(prop); +} + +//---------------------------------------------------------------------------- +std::vector<cmSourceFile*> const& cmGeneratorTarget::GetSourceFiles() +{ + return this->Target->GetSourceFiles(); +} + //---------------------------------------------------------------------------- void cmGeneratorTarget::ClassifySources() { @@ -175,3 +219,143 @@ void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) } } } + +//---------------------------------------------------------------------------- +cmComputeLinkInformation* +cmGeneratorTarget::GetLinkInformation(const char* config) +{ + // Lookup any existing information for this configuration. + std::map<cmStdString, cmComputeLinkInformation*>::iterator + i = this->LinkInformation.find(config?config:""); + if(i == this->LinkInformation.end()) + { + // Compute information for this configuration. + cmComputeLinkInformation* info = + new cmComputeLinkInformation(this->Target, config); + if(!info || !info->Compute()) + { + delete info; + info = 0; + } + + // Store the information for this configuration. + std::map<cmStdString, cmComputeLinkInformation*>::value_type + entry(config?config:"", info); + i = this->LinkInformation.insert(entry).first; + } + return i->second; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetAppleArchs(const char* config, + std::vector<std::string>& archVec) +{ + const char* archs = 0; + if(config && *config) + { + std::string defVarName = "OSX_ARCHITECTURES_"; + defVarName += cmSystemTools::UpperCase(config); + archs = this->Target->GetProperty(defVarName.c_str()); + } + if(!archs) + { + archs = this->Target->GetProperty("OSX_ARCHITECTURES"); + } + if(archs) + { + cmSystemTools::ExpandListArgument(std::string(archs), archVec); + } +} + +//---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetCreateRuleVariable() +{ + switch(this->GetType()) + { + case cmTarget::STATIC_LIBRARY: + return "_CREATE_STATIC_LIBRARY"; + case cmTarget::SHARED_LIBRARY: + return "_CREATE_SHARED_LIBRARY"; + case cmTarget::MODULE_LIBRARY: + return "_CREATE_SHARED_MODULE"; + case cmTarget::EXECUTABLE: + return "_LINK_EXECUTABLE"; + default: + break; + } + return ""; +} + +//---------------------------------------------------------------------------- +std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories( + const char *config) +{ + std::vector<std::string> includes; + const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES"); + if(!prop) + { + return includes; + } + + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "INCLUDE_DIRECTORIES", 0, 0); + + cmSystemTools::ExpandListArgument(ge.Parse(prop) + .Evaluate(this->Makefile, + config, + false, + this, + &dagChecker), + includes); + + std::set<std::string> uniqueIncludes; + std::vector<std::string> orderedAndUniqueIncludes; + for(std::vector<std::string>::const_iterator + li = includes.begin(); li != includes.end(); ++li) + { + std::string inc = *li; + if (!cmSystemTools::IsOff(inc.c_str())) + { + cmSystemTools::ConvertToUnixSlashes(inc); + } + if(uniqueIncludes.insert(inc).second) + { + orderedAndUniqueIncludes.push_back(inc); + } + } + + return orderedAndUniqueIncludes; +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetCompileDefinitions(const char *config) +{ + std::string defPropName = "COMPILE_DEFINITIONS"; + if (config) + { + defPropName += "_" + cmSystemTools::UpperCase(config); + } + + const char *prop = this->Target->GetProperty(defPropName.c_str()); + + if (!prop) + { + return ""; + } + + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + defPropName, 0, 0); + return ge.Parse(prop).Evaluate(this->Makefile, + config, + false, + this, + &dagChecker); +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 5c7578d..a29a9f9 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -14,6 +14,7 @@ #include "cmStandardIncludes.h" +class cmComputeLinkInformation; class cmCustomCommand; class cmGlobalGenerator; class cmLocalGenerator; @@ -25,6 +26,13 @@ class cmGeneratorTarget { public: cmGeneratorTarget(cmTarget*); + ~cmGeneratorTarget(); + + int GetType() const; + const char *GetName() const; + const char *GetProperty(const char *prop); + bool GetPropertyAsBool(const char *prop); + std::vector<cmSourceFile*> const& GetSourceFiles(); cmTarget* Target; cmMakefile* Makefile; @@ -52,6 +60,22 @@ public: void UseObjectLibraries(std::vector<std::string>& objs); + std::map<cmStdString, cmComputeLinkInformation*> LinkInformation; + + cmComputeLinkInformation* GetLinkInformation(const char* config); + + void GetAppleArchs(const char* config, + std::vector<std::string>& archVec); + + ///! Return the rule variable used to create this type of target, + // need to add CMAKE_(LANG) for full name. + const char* GetCreateRuleVariable(); + + /** Get the include directories for this target. */ + std::vector<std::string> GetIncludeDirectories(const char *config); + + std::string GetCompileDefinitions(const char *config = 0); + private: void ClassifySources(); void LookupObjectLibraries(); @@ -60,4 +84,6 @@ private: void operator=(cmGeneratorTarget const&); }; +typedef std::map<cmTarget*, cmGeneratorTarget*> cmGeneratorTargetsType; + #endif diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 578fa9e..b9de4d8 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -21,10 +21,11 @@ #include "cmQtAutomoc.h" #include "cmSourceFile.h" #include "cmVersion.h" -#include "cmExportInstallFileGenerator.h" +#include "cmTargetExport.h" #include "cmComputeTargetDepends.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" +#include "cmGeneratorExpression.h" #include <cmsys/Directory.hxx> @@ -76,12 +77,12 @@ cmGlobalGenerator::~cmGlobalGenerator() } this->ClearGeneratorTargets(); - this->ClearExportSets(); } void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, cmMakefile *mf, - bool optional) { + bool optional) +{ std::string langComp = "CMAKE_"; langComp += lang; langComp += "_COMPILER"; @@ -817,7 +818,7 @@ void cmGlobalGenerator::Configure() { this->FirstTimeProgress = 0.0f; this->ClearGeneratorTargets(); - this->ClearExportSets(); + this->ExportSets.clear(); // Delete any existing cmLocalGenerators unsigned int i; for (i = 0; i < this->LocalGenerators.size(); ++i) @@ -893,7 +894,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() << "The \"" << this->GetName() << "\" generator does not support " << "duplicate custom targets. " << "Consider using a Makefiles generator or fix the project to not " - << "use duplicat target names."; + << "use duplicate target names."; cmSystemTools::Error(e.str().c_str()); return false; } @@ -1075,23 +1076,56 @@ void cmGlobalGenerator::CreateGeneratorTargets() // Construct per-target generator information. for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) { - cmTargets& targets = - this->LocalGenerators[i]->GetMakefile()->GetTargets(); + cmGeneratorTargetsType generatorTargets; + + cmMakefile *mf = this->LocalGenerators[i]->GetMakefile(); + const char *noconfig_compile_definitions = + mf->GetProperty("COMPILE_DEFINITIONS"); + + std::vector<std::string> configs; + mf->GetConfigurations(configs); + + cmTargets& targets = mf->GetTargets(); for(cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) { cmTarget* t = &ti->second; + + { + t->AppendProperty("COMPILE_DEFINITIONS", noconfig_compile_definitions); + for(std::vector<std::string>::const_iterator ci = configs.begin(); + ci != configs.end(); ++ci) + { + std::string defPropName = "COMPILE_DEFINITIONS_"; + defPropName += cmSystemTools::UpperCase(*ci); + t->AppendProperty(defPropName.c_str(), + mf->GetProperty(defPropName.c_str())); + } + } + cmGeneratorTarget* gt = new cmGeneratorTarget(t); this->GeneratorTargets[t] = gt; this->ComputeTargetObjects(gt); + generatorTargets[t] = gt; + } + + for(std::vector<cmTarget*>::const_iterator + j = mf->GetOwnedImportedTargets().begin(); + j != mf->GetOwnedImportedTargets().end(); ++j) + { + cmGeneratorTarget* gt = new cmGeneratorTarget(*j); + this->GeneratorTargets[*j] = gt; + generatorTargets[*j] = gt; } + + mf->SetGeneratorTargets(generatorTargets); } } //---------------------------------------------------------------------------- void cmGlobalGenerator::ClearGeneratorTargets() { - for(GeneratorTargetsType::iterator i = this->GeneratorTargets.begin(); + for(cmGeneratorTargetsType::iterator i = this->GeneratorTargets.begin(); i != this->GeneratorTargets.end(); ++i) { delete i->second; @@ -1102,7 +1136,7 @@ void cmGlobalGenerator::ClearGeneratorTargets() //---------------------------------------------------------------------------- cmGeneratorTarget* cmGlobalGenerator::GetGeneratorTarget(cmTarget* t) const { - GeneratorTargetsType::const_iterator ti = this->GeneratorTargets.find(t); + cmGeneratorTargetsType::const_iterator ti = this->GeneratorTargets.find(t); if(ti == this->GeneratorTargets.end()) { this->CMakeInstance->IssueMessage( @@ -1129,7 +1163,7 @@ void cmGlobalGenerator::CheckLocalGenerators() { manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager(); this->LocalGenerators[i]->ConfigureFinalPass(); - cmTargets & targets = + cmTargets &targets = this->LocalGenerators[i]->GetMakefile()->GetTargets(); for (cmTargets::iterator l = targets.begin(); l != targets.end(); l++) @@ -1158,7 +1192,16 @@ void cmGlobalGenerator::CheckLocalGenerators() } } std::vector<std::string> incs; - this->LocalGenerators[i]->GetIncludeDirectories(incs, &l->second); + const char *incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES"); + if (!incDirProp) + { + continue; + } + + std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp, + cmGeneratorExpression::StripAllGeneratorExpressions); + + cmSystemTools::ExpandListArgument(incDirs.c_str(), incs); for( std::vector<std::string>::const_iterator incDir = incs.begin(); incDir != incs.end(); ++incDir) @@ -1466,52 +1509,6 @@ void cmGlobalGenerator::AddInstallComponent(const char* component) } } -void cmGlobalGenerator::AddTargetToExports(const char* exportSetName, - cmTarget* target, - cmInstallTargetGenerator* archive, - cmInstallTargetGenerator* runTime, - cmInstallTargetGenerator* library, - cmInstallTargetGenerator* framework, - cmInstallTargetGenerator* bundle, - cmInstallFilesGenerator* headers) -{ - if ((exportSetName) && (*exportSetName) && (target)) - { - cmTargetExport* te = new cmTargetExport(target, archive, runTime, library, - framework, bundle, headers); - this->ExportSets[exportSetName].push_back(te); - } -} - -//---------------------------------------------------------------------------- -void cmGlobalGenerator::ClearExportSets() -{ - for(std::map<cmStdString, std::vector<cmTargetExport*> >::iterator - setIt = this->ExportSets.begin(); - setIt != this->ExportSets.end(); ++setIt) - { - for(unsigned int i = 0; i < setIt->second.size(); ++i) - { - delete setIt->second[i]; - } - } - this->ExportSets.clear(); -} - -const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet( - const char* name) const -{ - std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator - exportSetIt = this->ExportSets.find(name); - if (exportSetIt != this->ExportSets.end()) - { - return &exportSetIt->second; - } - - return 0; -} - - void cmGlobalGenerator::EnableInstallTarget() { this->InstallTargetEnabled = true; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index ce91793..0aab2d6 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -18,13 +18,15 @@ #include "cmTarget.h" // For cmTargets #include "cmTargetDepend.h" // For cmTargetDependSet #include "cmSystemTools.h" // for cmSystemTools::OutputOption +#include "cmExportSetMap.h" // For cmExportSetMap +#include "cmGeneratorTarget.h" + class cmake; class cmGeneratorTarget; class cmMakefile; class cmLocalGenerator; class cmExternalMakefileProjectGenerator; class cmTarget; -class cmTargetExport; class cmInstallTargetGenerator; class cmInstallFilesGenerator; @@ -127,8 +129,8 @@ public: void SetCMakeInstance(cmake *cm); ///! Get the CMake instance - cmake *GetCMakeInstance() { return this->CMakeInstance; }; - const cmake *GetCMakeInstance() const { return this->CMakeInstance; }; + cmake *GetCMakeInstance() { return this->CMakeInstance; } + const cmake *GetCMakeInstance() const { return this->CMakeInstance; } void SetConfiguredFilesPath(cmGlobalGenerator* gen); const std::vector<cmLocalGenerator *>& GetLocalGenerators() const { @@ -151,18 +153,9 @@ public: void AddInstallComponent(const char* component); const std::set<cmStdString>* GetInstallComponents() const - { return &InstallComponents; } - - ///! Add one installed target to the sets of the exports - void AddTargetToExports(const char* exportSet, cmTarget* target, - cmInstallTargetGenerator* archive, - cmInstallTargetGenerator* runTime, - cmInstallTargetGenerator* library, - cmInstallTargetGenerator* framework, - cmInstallTargetGenerator* bundle, - cmInstallFilesGenerator* publicHeaders); - ///! Get the export target set with the given name - const std::vector<cmTargetExport*>* GetExportSet(const char* name) const; + { return &this->InstallComponents; } + + cmExportSetMap& GetExportSets() {return this->ExportSets;} /** Add a file to the manifest of generated targets for a configuration. */ void AddToManifest(const char* config, std::string const& f); @@ -222,7 +215,7 @@ public: /** 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; } + { return this->TargetManifest; } /** Get the content of a directory. Directory listings are loaded from disk at most once and cached. During the generation step @@ -328,15 +321,13 @@ protected: cmLocalGenerator* CurrentLocalGenerator; // map from project name to vector of local generators in that project std::map<cmStdString, std::vector<cmLocalGenerator*> > ProjectMap; - std::map<cmLocalGenerator*, std::set<cmTarget *> > - LocalGeneratorToTargetMap; + std::map<cmLocalGenerator*, std::set<cmTarget *> > LocalGeneratorToTargetMap; // Set of named installation components requested by the project. std::set<cmStdString> InstallComponents; bool InstallTargetEnabled; // Sets of named target exports - std::map<cmStdString, std::vector<cmTargetExport*> > ExportSets; - void ClearExportSets(); + cmExportSetMap ExportSets; // Manifest of all targets that will be built for each configuration. // This is computed just before local generators generate. @@ -383,8 +374,7 @@ private: TargetDependMap TargetDependencies; // Per-target generator information. - typedef std::map<cmTarget*, cmGeneratorTarget*> GeneratorTargetsType; - GeneratorTargetsType GeneratorTargets; + cmGeneratorTargetsType GeneratorTargets; void CreateGeneratorTargets(); void ClearGeneratorTargets(); virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 3f3cfbb..05f5b4c 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -106,6 +106,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables, + const std::string& rspfile, int cmdLineLimit) { // Make sure there is a rule. @@ -181,12 +182,17 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, // check if a response file rule should be used std::string buildstr = build.str(); - const std::string assignments = variable_assignments.str(); + std::string assignments = variable_assignments.str(); const std::string args = arguments.str(); if (cmdLineLimit > 0 && args.size() + buildstr.size() + assignments.size() - > (size_t) cmdLineLimit) - buildstr += "_RSPFILE"; + > (size_t) cmdLineLimit) { + buildstr += "_RSP_FILE"; + variable_assignments.clear(); + cmGlobalNinjaGenerator::WriteVariable(variable_assignments, + "RSP_FILE", rspfile, "", 1); + assignments += variable_assignments.str(); + } os << buildstr << args << assignments; } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index b2fe243..24c3916 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -84,6 +84,7 @@ public: const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables, + const std::string& rspfile = std::string(), int cmdLineLimit = -1); /** diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 2e3b530..bca1754 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -48,7 +48,7 @@ void cmGlobalVisualStudio8Generator ::GetDocumentation(cmDocumentationEntry& entry) const { entry.Name = this->GetName(); - entry.Brief = "Generates Visual Studio .NET 2005 project files."; + entry.Brief = "Generates Visual Studio 8 2005 project files."; entry.Full = ""; } diff --git a/Source/cmGlobalVisualStudio8Win64Generator.cxx b/Source/cmGlobalVisualStudio8Win64Generator.cxx index 164d116..4cbc275 100644 --- a/Source/cmGlobalVisualStudio8Win64Generator.cxx +++ b/Source/cmGlobalVisualStudio8Win64Generator.cxx @@ -27,7 +27,7 @@ void cmGlobalVisualStudio8Win64Generator ::GetDocumentation(cmDocumentationEntry& entry) const { entry.Name = this->GetName(); - entry.Brief = "Generates Visual Studio .NET 2005 Win64 project files."; + entry.Brief = "Generates Visual Studio 8 2005 Win64 project files."; entry.Full = ""; } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 5fdfcf8..30d8f18 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1647,16 +1647,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Add the export symbol definition for shared library objects. this->AppendDefines(ppDefs, exportMacro); } - this->AppendDefines - (ppDefs, this->CurrentMakefile->GetProperty("COMPILE_DEFINITIONS")); - this->AppendDefines(ppDefs, target.GetProperty("COMPILE_DEFINITIONS")); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); + this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str()); if(configName) { - std::string defVarName = "COMPILE_DEFINITIONS_"; - defVarName += cmSystemTools::UpperCase(configName); - this->AppendDefines - (ppDefs, this->CurrentMakefile->GetProperty(defVarName.c_str())); - this->AppendDefines(ppDefs, target.GetProperty(defVarName.c_str())); + this->AppendDefines(ppDefs, + gtgt->GetCompileDefinitions(configName).c_str()); } buildSettings->AddAttribute ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); @@ -1713,7 +1709,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Set target-specific architectures. std::vector<std::string> archs; - target.GetAppleArchs(configName, archs); + gtgt->GetAppleArchs(configName, archs); + if(!archs.empty()) { // Enable ARCHS attribute. @@ -1950,7 +1947,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, BuildObjectListOrString dirs(this, this->XcodeVersion >= 30); BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30); std::vector<std::string> includes; - this->CurrentLocalGenerator->GetIncludeDirectories(includes, &target); + this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, + "C", configName); std::set<cmStdString> emitted; emitted.insert("/System/Library/Frameworks"); for(std::vector<std::string>::iterator i = includes.begin(); @@ -2625,7 +2623,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; diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 0a1fe06..f794b78 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -114,7 +114,7 @@ public: "will be evaluated. Possible expressions are:\n" " if(<constant>)\n" "True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. " - "False if the constant is 0, OFF, NO, FALSE, N, IGNORE, \"\", " + "False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, '', " "or ends in the suffix '-NOTFOUND'. " "Named boolean constants are case-insensitive. " "If the argument is not one of these constants, " diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index 4dd98a1..ba81849 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -55,6 +55,11 @@ bool cmIncludeDirectoryCommand return true; } +static bool StartsWithGeneratorExpression(const std::string &input) +{ + return input[0] == '$' && input[1] == '<'; +} + // do a lot of cleanup on the arguments because this is one place where folks // sometimes take the output of a program and pass it directly into this // command not thinking that a single argument could be filled with spaces @@ -105,10 +110,13 @@ void cmIncludeDirectoryCommand::AddDirectory(const char *i, cmSystemTools::ConvertToUnixSlashes(ret); if(!cmSystemTools::FileIsFullPath(ret.c_str())) { - std::string tmp = this->Makefile->GetStartDirectory(); - tmp += "/"; - tmp += ret; - ret = tmp; + if(!StartsWithGeneratorExpression(ret)) + { + std::string tmp = this->Makefile->GetStartDirectory(); + tmp += "/"; + tmp += ret; + ret = tmp; + } } } this->Makefile->AddIncludeDirectory(ret.c_str(), before); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 4016734..dcd418b 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -17,6 +17,8 @@ #include "cmInstallTargetGenerator.h" #include "cmInstallExportGenerator.h" #include "cmInstallCommandArguments.h" +#include "cmTargetExport.h" +#include "cmExportSet.h" #include <cmsys/Glob.hxx> @@ -735,11 +737,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // this is not a namelink-only rule. if(!exports.GetString().empty() && !namelinkOnly) { + cmTargetExport *te = new cmTargetExport; + te->Target = ⌖ + te->ArchiveGenerator = archiveGenerator; + te->BundleGenerator = bundleGenerator; + te->FrameworkGenerator = frameworkGenerator; + te->HeaderGenerator = publicHeaderGenerator; + te->LibraryGenerator = libraryGenerator; + te->RuntimeGenerator = runtimeGenerator; this->Makefile->GetLocalGenerator()->GetGlobalGenerator() - ->AddTargetToExports(exports.GetCString(), &target, - archiveGenerator, runtimeGenerator, - libraryGenerator, frameworkGenerator, - bundleGenerator, publicHeaderGenerator); + ->GetExportSets()[exports.GetString()]->AddTargetExport(te); } } @@ -1264,7 +1271,9 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) // Create the export install generator. cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - exp.GetCString(), ica.GetDestination().c_str(), + this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->GetExportSets()[exp.GetString()], + ica.GetDestination().c_str(), ica.GetPermissions().c_str(), ica.GetConfigurations(), ica.GetComponent().c_str(), fname.c_str(), name_space.GetCString(), this->Makefile); diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 28a19d7..0a645a8 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -23,10 +23,11 @@ #include "cmInstallFilesGenerator.h" #include "cmExportInstallFileGenerator.h" +#include "cmExportSet.h" //---------------------------------------------------------------------------- cmInstallExportGenerator::cmInstallExportGenerator( - const char* name, + cmExportSet* exportSet, const char* destination, const char* file_permissions, std::vector<std::string> const& configurations, @@ -34,13 +35,14 @@ cmInstallExportGenerator::cmInstallExportGenerator( const char* filename, const char* name_space, cmMakefile* mf) :cmInstallGenerator(destination, configurations, component) - ,Name(name) + ,ExportSet(exportSet) ,FilePermissions(file_permissions) ,FileName(filename) ,Namespace(name_space) ,Makefile(mf) { this->EFGen = new cmExportInstallFileGenerator(this); + exportSet->AddInstallation(this); } //---------------------------------------------------------------------------- @@ -113,16 +115,12 @@ void cmInstallExportGenerator::ComputeTempDir() //---------------------------------------------------------------------------- void cmInstallExportGenerator::GenerateScript(std::ostream& os) { - // Get the export set requested. - ExportSet const* exportSet = - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() - ->GetExportSet(this->Name.c_str()); - // Skip empty sets. - if(!exportSet) + if(ExportSet->GetTargetExports()->empty()) { cmOStringStream e; - e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\""; + e << "INSTALL(EXPORT) given unknown export \"" + << ExportSet->GetName() << "\""; cmSystemTools::Error(e.str().c_str()); return; } @@ -137,8 +135,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) this->MainImportFile += this->FileName; // Generate the import file for this export set. - this->EFGen->SetName(this->Name.c_str()); - this->EFGen->SetExportSet(exportSet); this->EFGen->SetExportFile(this->MainImportFile.c_str()); this->EFGen->SetNamespace(this->Namespace.c_str()); if(this->ConfigurationTypes->empty()) diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 1ff6e38..ee92906 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -17,8 +17,7 @@ class cmExportInstallFileGenerator; class cmInstallFilesGenerator; class cmInstallTargetGenerator; -class cmTarget; -class cmTargetExport; +class cmExportSet; class cmMakefile; /** \class cmInstallExportGenerator @@ -27,24 +26,27 @@ class cmMakefile; class cmInstallExportGenerator: public cmInstallGenerator { public: - cmInstallExportGenerator(const char* name, + cmInstallExportGenerator(cmExportSet* exportSet, const char* dest, const char* file_permissions, const std::vector<std::string>& configurations, const char* component, const char* filename, const char* name_space, cmMakefile* mf); ~cmInstallExportGenerator(); -protected: - typedef std::vector<cmTargetExport*> ExportSet; + cmExportSet* GetExportSet() {return this->ExportSet;} + + const std::string& GetNamespace() const { return this->Namespace; } + +protected: virtual void GenerateScript(std::ostream& os); virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent); virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); - void GenerateImportFile(ExportSet const* exportSet); - void GenerateImportFile(const char* config, ExportSet const* exportSet); + void GenerateImportFile(cmExportSet const* exportSet); + void GenerateImportFile(const char* config, cmExportSet const* exportSet); void ComputeTempDir(); - std::string Name; + cmExportSet* ExportSet; std::string FilePermissions; std::string FileName; std::string Namespace; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 5f9b658..347ad3e 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -16,6 +16,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmake.h" +#include "cmGeneratorTarget.h" #include <assert.h> @@ -26,7 +27,8 @@ cmInstallTargetGenerator std::vector<std::string> const& configurations, const char* component, bool optional): cmInstallGenerator(dest, configurations, component), Target(&t), - ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional) + ImportLibrary(implib), FilePermissions(file_permissions), + Optional(optional), GeneratorTarget(0) { this->ActionsPerConfig = true; this->NamelinkMode = NamelinkModeNone; @@ -484,6 +486,17 @@ void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os, this->AddStripRule(os, indent, file); } +void cmInstallTargetGenerator::CreateGeneratorTarget() +{ + if (!this->GeneratorTarget) + { + this->GeneratorTarget = this->Target->GetMakefile() + ->GetLocalGenerator() + ->GetGlobalGenerator() + ->GetGeneratorTarget(this->Target); + } +} + //---------------------------------------------------------------------------- void cmInstallTargetGenerator @@ -507,10 +520,13 @@ cmInstallTargetGenerator return; } + this->CreateGeneratorTarget(); + // Build a map of build-tree install_name to install-tree install_name for // shared libraries linked to this target. std::map<cmStdString, cmStdString> install_name_remap; - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config)) + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(config)) { std::set<cmTarget*> const& sharedLibs = cli->GetSharedLibrariesLinked(); for(std::set<cmTarget*>::const_iterator j = sharedLibs.begin(); @@ -608,9 +624,12 @@ cmInstallTargetGenerator return; } + this->CreateGeneratorTarget(); + // Get the link information for this target. // It can provide the RPATH. - cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); + cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(config); if(!cli) { return; @@ -639,9 +658,12 @@ cmInstallTargetGenerator return; } + this->CreateGeneratorTarget(); + // Get the link information for this target. // It can provide the RPATH. - cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); + cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(config); if(!cli) { return; diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 5d158b8..cab3e90 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -15,6 +15,8 @@ #include "cmInstallGenerator.h" #include "cmTarget.h" +class cmGeneratorTarget; + /** \class cmInstallTargetGenerator * \brief Generate target installation rules. */ @@ -92,11 +94,14 @@ protected: void AddRanlibRule(std::ostream& os, Indent const& indent, const std::string& toDestDirPath); + void CreateGeneratorTarget(); + cmTarget* Target; bool ImportLibrary; std::string FilePermissions; bool Optional; NamelinkModeType NamelinkMode; + cmGeneratorTarget* GeneratorTarget; }; #endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index f2bced4..4952a8c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -554,9 +554,9 @@ void cmLocalGenerator::GenerateTargetManifest() } void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, - const char* lang, - cmSourceFile& source, - cmTarget& target) + const char* lang, + cmSourceFile& source, + cmGeneratorTarget& target) { std::string objectDir = cmSystemTools::GetFilenamePath(std::string(ofname)); objectDir = this->Convert(objectDir.c_str(),START_OUTPUT,SHELL); @@ -635,7 +635,8 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, ); } -void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) +void cmLocalGenerator::AddBuildTargetRule(const char* llang, + cmGeneratorTarget& target) { cmStdString objs; std::vector<std::string> objVector; @@ -669,15 +670,19 @@ void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) std::string createRule = "CMAKE_"; createRule += llang; createRule += target.GetCreateRuleVariable(); - std::string targetName = target.GetFullName(); + 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, flags, linkFlags, target); + this->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags, + &target); + linkLibs = frameworkPath + linkPath + linkLibs; cmLocalGenerator::RuleVariables vars; vars.Language = llang; vars.Objects = objs.c_str(); @@ -714,7 +719,7 @@ void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) // Store this command line. commandLines.push_back(commandLine); } - std::string targetFullPath = target.GetFullPath(); + std::string targetFullPath = target.Target->GetFullPath(); // Generate a meaningful comment for the command. std::string comment = "Linking "; comment += llang; @@ -728,7 +733,7 @@ void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) comment.c_str(), this->Makefile->GetStartOutputDirectory() ); - target.AddSourceFile + target.Target->AddSourceFile (this->Makefile->GetSource(targetFullPath.c_str())); } @@ -736,11 +741,15 @@ void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) void cmLocalGenerator ::CreateCustomTargetsAndCommands(std::set<cmStdString> const& lang) { - cmTargets &tgts = this->Makefile->GetTargets(); - for(cmTargets::iterator l = tgts.begin(); + cmGeneratorTargetsType tgts = this->Makefile->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator l = tgts.begin(); l != tgts.end(); l++) { - cmTarget& target = l->second; + if (l->first->IsImported()) + { + continue; + } + cmGeneratorTarget& target = *l->second; switch(target.GetType()) { case cmTarget::STATIC_LIBRARY: @@ -748,12 +757,12 @@ void cmLocalGenerator case cmTarget::MODULE_LIBRARY: case cmTarget::EXECUTABLE: { - const char* llang = target.GetLinkerLanguage(); + const char* llang = target.Target->GetLinkerLanguage(); if(!llang) { cmSystemTools::Error ("CMake can not determine linker language for target:", - target.GetName()); + target.Target->GetName()); return; } // if the language is not in the set lang then create custom @@ -1318,8 +1327,9 @@ std::string cmLocalGenerator::GetIncludeFlags( //---------------------------------------------------------------------------- void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, - cmTarget* target, - const char* lang) + cmGeneratorTarget* target, + const char* lang, + const char *config) { // Need to decide whether to automatically include the source and // binary directories at the beginning of the include path. @@ -1389,6 +1399,11 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, } } + if(!target) + { + return; + } + // Load implicit include directories for this language. std::string impDirVar = "CMAKE_"; impDirVar += lang; @@ -1406,10 +1421,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, // Get the target-specific include directories. std::vector<std::string> includes; - if(target) - { - includes = target->GetIncludeDirectories(); - } + + includes = target->GetIncludeDirectories(config); // Support putting all the in-project include directories first if // it is requested by the project. @@ -1449,7 +1462,9 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, std::string& flags, std::string& linkFlags, - cmTarget& target) + std::string& frameworkPath, + std::string& linkPath, + cmGeneratorTarget* target) { std::string buildType = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); @@ -1457,12 +1472,12 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, const char* libraryLinkVariable = "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library - switch(target.GetType()) + switch(target->GetType()) { case cmTarget::STATIC_LIBRARY: { const char* targetLinkFlags = - target.GetProperty("STATIC_LIBRARY_FLAGS"); + target->GetProperty("STATIC_LIBRARY_FLAGS"); if(targetLinkFlags) { linkFlags += targetLinkFlags; @@ -1472,7 +1487,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, { std::string build = "STATIC_LIBRARY_FLAGS_"; build += buildType; - targetLinkFlags = target.GetProperty(build.c_str()); + targetLinkFlags = target->GetProperty(build.c_str()); if(targetLinkFlags) { linkFlags += targetLinkFlags; @@ -1498,7 +1513,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW"))) { - const std::vector<cmSourceFile*>& sources = target.GetSourceFiles(); + const std::vector<cmSourceFile*>& sources = target->GetSourceFiles(); for(std::vector<cmSourceFile*>::const_iterator i = sources.begin(); i != sources.end(); ++i) { @@ -1513,7 +1528,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, } } } - const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"); + const char* targetLinkFlags = target->GetProperty("LINK_FLAGS"); if(targetLinkFlags) { linkFlags += targetLinkFlags; @@ -1523,16 +1538,15 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, { std::string configLinkFlags = "LINK_FLAGS_"; configLinkFlags += buildType; - targetLinkFlags = target.GetProperty(configLinkFlags.c_str()); + targetLinkFlags = target->GetProperty(configLinkFlags.c_str()); if(targetLinkFlags) { linkFlags += targetLinkFlags; linkFlags += " "; } } - cmOStringStream linklibsStr; - this->OutputLinkLibraries(linklibsStr, target, false); - linkLibs = linklibsStr.str(); + this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, + *target, false); } break; case cmTarget::EXECUTABLE: @@ -1547,18 +1561,17 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, linkFlags += this->Makefile->GetSafeDefinition(build.c_str()); linkFlags += " "; } - const char* linkLanguage = target.GetLinkerLanguage(); + const char* linkLanguage = target->Target->GetLinkerLanguage(); if(!linkLanguage) { cmSystemTools::Error ("CMake can not determine linker language for target:", - target.GetName()); + target->Target->GetName()); return; } this->AddLanguageFlags(flags, linkLanguage, buildType.c_str()); - cmOStringStream linklibs; - this->OutputLinkLibraries(linklibs, target, false); - linkLibs = linklibs.str(); + this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, + *target, false); if(cmSystemTools::IsOn (this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) { @@ -1567,7 +1580,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, linkFlags += this->Makefile->GetSafeDefinition(sFlagVar.c_str()); linkFlags += " "; } - if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") ) + if ( target->GetPropertyAsBool("WIN32_EXECUTABLE") ) { linkFlags += this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); @@ -1579,7 +1592,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"); linkFlags += " "; } - if (target.IsExecutableWithExports()) + if (target->Target->IsExecutableWithExports()) { std::string exportFlagVar = "CMAKE_EXE_EXPORTS_"; exportFlagVar += linkLanguage; @@ -1589,7 +1602,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, this->Makefile->GetSafeDefinition(exportFlagVar.c_str()); linkFlags += " "; } - const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"); + const char* targetLinkFlags = target->GetProperty("LINK_FLAGS"); if(targetLinkFlags) { linkFlags += targetLinkFlags; @@ -1599,7 +1612,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, { std::string configLinkFlags = "LINK_FLAGS_"; configLinkFlags += buildType; - targetLinkFlags = target.GetProperty(configLinkFlags.c_str()); + targetLinkFlags = target->GetProperty(configLinkFlags.c_str()); if(targetLinkFlags) { linkFlags += targetLinkFlags; @@ -1650,10 +1663,13 @@ std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib) * targetLibrary should be a NULL pointer. For libraries, it should point * to the name of the library. This will not link a library against itself. */ -void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout, - cmTarget& tgt, +void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, + std::string& frameworkPath, + std::string& linkPath, + cmGeneratorTarget &tgt, bool relink) { + cmOStringStream fout; const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config); if(!pcli) @@ -1687,9 +1703,9 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout, for(std::vector<std::string>::const_iterator fdi = fwDirs.begin(); fdi != fwDirs.end(); ++fdi) { - linkLibs += "-F"; - linkLibs += this->Convert(fdi->c_str(), NONE, SHELL, false); - linkLibs += " "; + frameworkPath = " -F"; + frameworkPath += this->Convert(fdi->c_str(), NONE, SHELL, false); + frameworkPath += " "; } // Append the library search path flags. @@ -1698,10 +1714,10 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout, libDir != libDirs.end(); ++libDir) { std::string libpath = this->ConvertToOutputForExisting(libDir->c_str()); - linkLibs += libPathFlag; - linkLibs += libpath; - linkLibs += libPathTerminator; - linkLibs += " "; + linkPath += " " + libPathFlag; + linkPath += libpath; + linkPath += libPathTerminator; + linkPath += " "; } // Append the link items. @@ -1773,12 +1789,14 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout, { fout << stdLibs << " "; } + + linkLibraries = fout.str(); } //---------------------------------------------------------------------------- void cmLocalGenerator::AddArchitectureFlags(std::string& flags, - cmTarget* target, + cmGeneratorTarget* target, const char *lang, const char* config) { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b3396e3..bd58218 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -16,6 +16,7 @@ class cmMakefile; class cmGlobalGenerator; +class cmGeneratorTarget; class cmTarget; class cmTargetManifest; class cmSourceFile; @@ -135,7 +136,7 @@ public: std::vector<cmLocalGenerator*>& GetChildren() { return this->Children; }; - void AddArchitectureFlags(std::string& flags, cmTarget* target, + void AddArchitectureFlags(std::string& flags, cmGeneratorTarget* target, const char *lang, const char* config); void AddLanguageFlags(std::string& flags, const char* lang, @@ -156,6 +157,11 @@ public: */ void AppendDefines(std::set<std::string>& defines, const char* defines_list); + void AppendDefines(std::set<std::string>& defines, + std::string defines_list) + { + this->AppendDefines(defines, defines_list.c_str()); + } /** * Join a set of defines into a definesString with a space separator. */ @@ -205,8 +211,8 @@ public: /** Get the include flags for the current makefile and language. */ void GetIncludeDirectories(std::vector<std::string>& dirs, - cmTarget* target, - const char* lang = "C"); + cmGeneratorTarget* target, + const char* lang = "C", const char *config = 0); /** Compute the language used to compile the given source file. */ const char* GetSourceFileLanguage(const cmSourceFile& source); @@ -334,11 +340,17 @@ public: void GetTargetFlags(std::string& linkLibs, std::string& flags, std::string& linkFlags, - cmTarget&target); + std::string& frameworkPath, + std::string& linkPath, + cmGeneratorTarget* target); protected: ///! put all the libraries for a target on into the given stream - virtual void OutputLinkLibraries(std::ostream&, cmTarget&, bool relink); + virtual void OutputLinkLibraries(std::string& linkLibraries, + std::string& frameworkPath, + std::string& linkPath, + cmGeneratorTarget &, + bool relink); // Expand rule variables in CMake of the type found in language rules void ExpandRuleVariables(std::string& string, @@ -354,12 +366,12 @@ protected: /** Convert a target to a utility target for unsupported * languages of a generator */ - void AddBuildTargetRule(const char* llang, cmTarget& target); + void AddBuildTargetRule(const char* llang, cmGeneratorTarget& target); ///! add a custom command to build a .o file that is part of a target void AddCustomCommandToCreateObject(const char* ofname, const char* lang, cmSourceFile& source, - cmTarget& target); + 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 diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 9f2a863..f15322b 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -853,7 +853,8 @@ inline std::string removeQuotes(const std::string& s) std::string -cmLocalVisualStudio6Generator::GetTargetIncludeOptions(cmTarget &target) +cmLocalVisualStudio6Generator::GetTargetIncludeOptions(cmTarget &target, + const char *config) { std::string includeOptions; @@ -862,10 +863,13 @@ cmLocalVisualStudio6Generator::GetTargetIncludeOptions(cmTarget &target) // the length threatens this problem. unsigned int maxIncludeLength = 3000; bool useShortPath = false; + + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); for(int j=0; j < 2; ++j) { std::vector<std::string> includes; - this->GetIncludeDirectories(includes, &target); + this->GetIncludeDirectories(includes, gt, "C", config); std::vector<std::string>::iterator i; for(i = includes.begin(); i != includes.end(); ++i) @@ -1144,7 +1148,15 @@ void cmLocalVisualStudio6Generator #endif // Get include options for this target. - std::string includeOptions = this->GetTargetIncludeOptions(target); + std::string includeOptionsDebug = this->GetTargetIncludeOptions(target, + "DEBUG"); + std::string includeOptionsRelease = this->GetTargetIncludeOptions(target, + "RELEASE"); + std::string includeOptionsRelWithDebInfo = this->GetTargetIncludeOptions( + target, + "RELWITHDEBINFO"); + std::string includeOptionsMinSizeRel = this->GetTargetIncludeOptions(target, + "MINSIZEREL"); // Get extra linker options for this target type. std::string extraLinkOptions; @@ -1557,8 +1569,15 @@ void cmLocalVisualStudio6Generator cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO", optionsRelWithDebInfo.c_str()); - cmSystemTools::ReplaceString(line, "BUILD_INCLUDES", - includeOptions.c_str()); + cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_DEBUG", + includeOptionsDebug.c_str()); + cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_RELEASE", + includeOptionsRelease.c_str()); + cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_MINSIZEREL", + includeOptionsMinSizeRel.c_str()); + cmSystemTools::ReplaceString(line, "BUILD_INCLUDES_RELWITHDEBINFO", + includeOptionsRelWithDebInfo.c_str()); + cmSystemTools::ReplaceString(line, "TARGET_VERSION_FLAG", targetVersionFlag.c_str()); cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_DEBUG", @@ -1676,37 +1695,25 @@ void cmLocalVisualStudio6Generator std::set<std::string> minsizeDefinesSet; std::set<std::string> debugrelDefinesSet; - this->AppendDefines( - definesSet, - this->Makefile->GetProperty("COMPILE_DEFINITIONS")); - this->AppendDefines( - debugDefinesSet, - this->Makefile->GetProperty("COMPILE_DEFINITIONS_DEBUG")); - this->AppendDefines( - releaseDefinesSet, - this->Makefile->GetProperty("COMPILE_DEFINITIONS_RELEASE")); - this->AppendDefines( - minsizeDefinesSet, - this->Makefile->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL")); - this->AppendDefines( - debugrelDefinesSet, - this->Makefile->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO")); + + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); this->AppendDefines( definesSet, - target.GetProperty("COMPILE_DEFINITIONS")); + gt->GetCompileDefinitions()); this->AppendDefines( debugDefinesSet, - target.GetProperty("COMPILE_DEFINITIONS_DEBUG")); + gt->GetCompileDefinitions("DEBUG")); this->AppendDefines( releaseDefinesSet, - target.GetProperty("COMPILE_DEFINITIONS_RELEASE")); + gt->GetCompileDefinitions("RELEASE")); this->AppendDefines( minsizeDefinesSet, - target.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL")); + gt->GetCompileDefinitions("MINSIZEREL")); this->AppendDefines( debugrelDefinesSet, - target.GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO")); + gt->GetCompileDefinitions("RELWITHDEBINFO")); std::string defines = " "; std::string debugDefines = " "; @@ -1776,8 +1783,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; diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index 9315d97..f45bc17 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -90,7 +90,7 @@ private: std::string& options); void OutputObjects(cmTarget& target, const char* tool, std::string& options); - std::string GetTargetIncludeOptions(cmTarget &target); + std::string GetTargetIncludeOptions(cmTarget &target, const char *config); std::vector<std::string> Configurations; std::string GetConfigName(std::string const& configuration) const; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 2dfca02..f9a2d32 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -724,10 +724,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, flags += targetFlags; } - std::string configUpper = cmSystemTools::UpperCase(configName); - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += configUpper; - // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); Options::Tool t = Options::Compiler; @@ -744,11 +740,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.Parse(flags.c_str()); targetOptions.Parse(defineFlags.c_str()); targetOptions.ParseFinish(); - targetOptions.AddDefines - (this->Makefile->GetProperty("COMPILE_DEFINITIONS")); - targetOptions.AddDefines(target.GetProperty("COMPILE_DEFINITIONS")); - targetOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str())); - targetOptions.AddDefines(target.GetProperty(defPropName.c_str())); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + targetOptions.AddDefines(gt->GetCompileDefinitions().c_str()); + targetOptions.AddDefines(gt->GetCompileDefinitions(configName).c_str()); targetOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); @@ -819,7 +814,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); fout << "\t\t\t\tAdditionalIncludeDirectories=\""; std::vector<std::string> includes; - this->GetIncludeDirectories(includes, &target); + this->GetIncludeDirectories(includes, gt, "C", configName); std::vector<std::string>::iterator i = includes.begin(); for(;i != includes.end(); ++i) { @@ -847,7 +842,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, // non-debug configurations because VS still creates .idb files. fout << "\t\t\t\tProgramDataBaseFileName=\"" << this->ConvertToXMLOutputPathSingle( - target.GetDirectory(configName).c_str()) + target.GetPDBDirectory(configName).c_str()) << "/" << target.GetPDBName(configName) << "\"\n"; } @@ -1079,7 +1074,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1125,7 +1122,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, fout << "\t\t\t\tAdditionalLibraryDirectories=\""; this->OutputLibraryDirectories(fout, cli.GetDirectories()); fout << "\"\n"; - temp = target.GetDirectory(configName); + temp = target.GetPDBDirectory(configName); temp += "/"; temp += targetNamePDB; fout << "\t\t\t\tProgramDatabaseFile=\"" << @@ -1164,7 +1161,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1211,7 +1210,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, this->OutputLibraryDirectories(fout, cli.GetDirectories()); fout << "\"\n"; std::string path = this->ConvertToXMLOutputPathSingle( - target.GetDirectory(configName).c_str()); + target.GetPDBDirectory(configName).c_str()); fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/" << targetNamePDB << "\"\n"; diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx index a68b57c..2ae35ef 100644 --- a/Source/cmMakeDepend.cxx +++ b/Source/cmMakeDepend.cxx @@ -11,6 +11,7 @@ ============================================================================*/ #include "cmMakeDepend.h" #include "cmSystemTools.h" +#include "cmGeneratorExpression.h" #include <cmsys/RegularExpression.hxx> @@ -58,11 +59,22 @@ void cmMakeDepend::SetMakefile(cmMakefile* makefile) // Now extract any include paths from the targets std::set<std::string> uniqueIncludes; std::vector<std::string> orderedAndUniqueIncludes; - cmTargets & targets = this->Makefile->GetTargets(); - for (cmTargets::iterator l = targets.begin(); l != targets.end(); ++l) + cmTargets &targets = this->Makefile->GetTargets(); + for (cmTargets::iterator l = targets.begin(); + l != targets.end(); ++l) { - const std::vector<std::string>& includes = - l->second.GetIncludeDirectories(); + const char *incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES"); + if (!incDirProp) + { + continue; + } + + std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp, + cmGeneratorExpression::StripAllGeneratorExpressions); + + std::vector<std::string> includes; + cmSystemTools::ExpandListArgument(incDirs.c_str(), includes); + for(std::vector<std::string>::const_iterator j = includes.begin(); j != includes.end(); ++j) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 9a9c1c8..f067da4 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3984,6 +3984,12 @@ cmTarget* cmMakefile::FindTargetToUse(const char* name) return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name); } +cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name) +{ + cmTarget *t = this->FindTargetToUse(name); + return this->LocalGenerator->GetGlobalGenerator()->GetGeneratorTarget(t); +} + //---------------------------------------------------------------------------- bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, bool isCustom) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 74c8039..70cfe54 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -20,6 +20,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmNewLineStyle.h" +#include "cmGeneratorTarget.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -518,12 +519,27 @@ public: * Get the list of targets, const version */ const cmTargets &GetTargets() const { return this->Targets; } + const std::vector<cmTarget*> &GetOwnedImportedTargets() const + { + return this->ImportedTargetsOwned; + } + + const cmGeneratorTargetsType &GetGeneratorTargets() const + { + return this->GeneratorTargets; + } + + void SetGeneratorTargets(const cmGeneratorTargetsType &targets) + { + this->GeneratorTargets = targets; + } cmTarget* FindTarget(const char* name); /** Find a target to use in place of the given name. The target returned may be imported or built within the project. */ cmTarget* FindTargetToUse(const char* name); + cmGeneratorTarget* FindGeneratorTargetToUse(const char* name); /** * Mark include directories as system directories. @@ -865,6 +881,7 @@ protected: // libraries, classes, and executables cmTargets Targets; + cmGeneratorTargetsType GeneratorTargets; std::vector<cmSourceFile*> SourceFiles; // Tests diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index ab5150a..b7a454b 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -131,9 +131,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) outpathImp += "/"; } } + + std::string pdbOutputPath = this->Target->GetPDBDirectory(); + cmSystemTools::MakeDirectory(pdbOutputPath.c_str()); + pdbOutputPath += "/"; + std::string targetFullPath = outpath + targetName; std::string targetFullPathReal = outpath + targetNameReal; - std::string targetFullPathPDB = outpath + targetNamePDB; + std::string targetFullPathPDB = pdbOutputPath + targetNamePDB; std::string targetFullPathImport = outpathImp + targetNameImport; std::string targetOutPathPDB = this->Convert(targetFullPathPDB.c_str(), @@ -210,7 +215,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add language feature flags. this->AddFeatureFlags(flags, linkLanguage); - this->LocalGenerator->AddArchitectureFlags(flags, this->Target, + this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, linkLanguage, this->ConfigName); // Add target-specific linker flags. @@ -318,9 +323,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->SetLinkScriptShell(useLinkScript); // Collect up flags to link in needed libraries. - cmOStringStream linklibs; - this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink); - + std::string linkLibs; + std::string frameworkPath; + std::string linkPath; + this->LocalGenerator->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, + *this->GeneratorTarget, + relink); + linkLibs = frameworkPath + linkPath + linkLibs; // Construct object file lists that may be needed to expand the // rule. std::string buildObjs; @@ -359,8 +368,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.TargetVersionMajor = targetVersionMajor.c_str(); vars.TargetVersionMinor = targetVersionMinor.c_str(); - std::string linkString = linklibs.str(); - vars.LinkLibraries = linkString.c_str(); + vars.LinkLibraries = linkLibs.c_str(); vars.Flags = flags.c_str(); vars.LinkFlags = linkFlags.c_str(); // Expand placeholders in the commands. diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 577e5fd..e7004d6 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -328,8 +328,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } } + std::string pdbOutputPath = this->Target->GetPDBDirectory(); + cmSystemTools::MakeDirectory(pdbOutputPath.c_str()); + pdbOutputPath += "/"; + std::string targetFullPath = outpath + targetName; - std::string targetFullPathPDB = outpath + targetNamePDB; + std::string targetFullPathPDB = pdbOutputPath + targetNamePDB; std::string targetFullPathSO = outpath + targetNameSO; std::string targetFullPathReal = outpath + targetNameReal; std::string targetFullPathImport = outpathImp + targetNameImport; @@ -542,11 +546,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules this->LocalGenerator->SetLinkScriptShell(useLinkScript); // Collect up flags to link in needed libraries. - cmOStringStream linklibs; + std::string linkLibs; if(this->Target->GetType() != cmTarget::STATIC_LIBRARY) { + std::string frameworkPath; + std::string linkPath; this->LocalGenerator - ->OutputLinkLibraries(linklibs, *this->Target, relink); + ->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, + *this->GeneratorTarget, relink); + linkLibs = frameworkPath + linkPath + linkLibs; } // Construct object file lists that may be needed to expand the @@ -587,8 +595,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules cmLocalGenerator::SHELL); vars.ObjectDir = objdir.c_str(); vars.Target = targetOutPathReal.c_str(); - std::string linkString = linklibs.str(); - vars.LinkLibraries = linkString.c_str(); + vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); if (this->Target->HasSOName(this->ConfigName)) { @@ -625,7 +632,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules std::string langFlags; this->AddFeatureFlags(langFlags, linkLanguage); - this->LocalGenerator->AddArchitectureFlags(langFlags, this->Target, + this->LocalGenerator->AddArchitectureFlags(langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); // remove any language flags that might not work with the diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 95738c4..3d02d6a 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -259,7 +259,7 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) // Add language feature flags. this->AddFeatureFlags(flags, lang); - this->LocalGenerator->AddArchitectureFlags(flags, this->Target, + this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, lang, this->ConfigName); // Fortran-specific flags computed for this target. @@ -302,16 +302,11 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l) // Add preprocessor definitions for this target and configuration. this->LocalGenerator->AppendDefines - (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS")); - this->LocalGenerator->AppendDefines - (defines, this->Target->GetProperty("COMPILE_DEFINITIONS")); - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += - cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); - this->LocalGenerator->AppendDefines - (defines, this->Makefile->GetProperty(defPropName.c_str())); + (defines, this->GeneratorTarget->GetCompileDefinitions()); + this->LocalGenerator->AppendDefines - (defines, this->Target->GetProperty(defPropName.c_str())); + (defines, this->GeneratorTarget->GetCompileDefinitions( + this->LocalGenerator->ConfigurationName.c_str())); std::string definesString; this->LocalGenerator->JoinDefines(defines, definesString, lang); @@ -652,7 +647,7 @@ cmMakefileTargetGenerator this->Target->GetType() == cmTarget::SHARED_LIBRARY || this->Target->GetType() == cmTarget::MODULE_LIBRARY) { - targetFullPathPDB = this->Target->GetDirectory(this->ConfigName); + targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName); targetFullPathPDB += "/"; targetFullPathPDB += this->Target->GetPDBName(this->ConfigName); } @@ -1022,7 +1017,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "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)) + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(cfg)) { cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); for(cmComputeLinkInformation::ItemVector::const_iterator @@ -1061,7 +1057,11 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() *this->InfoFileStream << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n"; std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, this->Target); + + const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + "C", config); for(std::vector<std::string>::iterator i = includes.begin(); i != includes.end(); ++i) { @@ -1546,7 +1546,11 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags() emitted.insert("/System/Library/Frameworks"); #endif std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, this->Target); + + const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + "C", config); std::vector<std::string>::iterator i; // check all include directories for frameworks as this // will already have added a -F for the framework @@ -1590,7 +1594,8 @@ void cmMakefileTargetGenerator // Loop over all library dependencies. const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(cfg)) { std::vector<std::string> const& libDeps = cli->GetDepends(); for(std::vector<std::string>::const_iterator j = libDeps.begin(); @@ -1850,7 +1855,10 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, this->Target, lang); + const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + lang, config); std::string includeFlags = this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile); @@ -1953,7 +1961,10 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) { std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, this->Target); + const char *config = this->Makefile->GetDefinition("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) { diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 9dc860e..6c54ced 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -153,7 +153,7 @@ cmNinjaNormalTargetGenerator cmTarget::TargetType targetType = this->GetTarget()->GetType(); std::string ruleName = this->LanguageLinkerRule(); if (useResponseFile) - ruleName += "_RSPFILE"; + ruleName += "_RSP_FILE"; // Select whether to use a response file for objects. std::string rspfile; @@ -168,20 +168,29 @@ cmNinjaNormalTargetGenerator std::string responseFlag; if (!useResponseFile) { vars.Objects = "$in"; - vars.LinkLibraries = "$LINK_LIBRARIES"; + vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES"; } else { - // handle response file - std::string cmakeLinkVar = std::string("CMAKE_") + - this->TargetLinkLanguage + "_RESPONSE_FILE_LINK_FLAG"; + std::string cmakeVarLang = "CMAKE_"; + cmakeVarLang += this->TargetLinkLanguage; + + // build response file name + std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; const char * flag = GetMakefile()->GetDefinition(cmakeLinkVar.c_str()); if(flag) { responseFlag = flag; } else { responseFlag = "@"; } - rspfile = "$out.rsp"; + rspfile = "$RSP_FILE"; responseFlag += rspfile; - rspcontent = "$in $LINK_LIBRARIES"; + + // build response file content + std::string linkOptionVar = cmakeVarLang; + linkOptionVar += "_COMPILER_LINKER_OPTION_FLAG_"; + linkOptionVar += cmTarget::GetTargetTypeName(targetType); + const std::string linkOption = + GetMakefile()->GetSafeDefinition(linkOptionVar.c_str()); + rspcontent = "$in " + linkOption + " $LINK_PATH $LINK_LIBRARIES"; vars.Objects = responseFlag.c_str(); vars.LinkLibraries = ""; } @@ -420,12 +429,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmNinjaDeps explicitDeps = this->GetObjects(); cmNinjaDeps implicitDeps = this->ComputeLinkDeps(); + std::string frameworkPath; + std::string linkPath; this->GetLocalGenerator()->GetTargetFlags(vars["LINK_LIBRARIES"], vars["FLAGS"], vars["LINK_FLAGS"], - *this->GetTarget()); + frameworkPath, + linkPath, + this->GetGeneratorTarget()); this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]); + vars["LINK_PATH"] = frameworkPath + linkPath; // Compute architecture specific link flags. Yes, these go into a different // variable for executables, probably due to a mistake made when duplicating @@ -434,7 +448,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() ? vars["FLAGS"] : vars["ARCH_FLAGS"]); this->GetLocalGenerator()->AddArchitectureFlags(flags, - this->GetTarget(), + this->GetGeneratorTarget(), this->TargetLinkLanguage, this->GetConfigName()); if (targetType == cmTarget::EXECUTABLE) { @@ -539,15 +553,24 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() int linkRuleLength = this->GetGlobalGenerator()-> GetRuleCmdLength(this->LanguageLinkerRule()); + + int commandLineLengthLimit = 1; + const char* forceRspFile = "CMAKE_NINJA_FORCE_RESPONSE_FILE"; + if (!this->GetMakefile()->IsDefinitionSet(forceRspFile) && + cmSystemTools::GetEnv(forceRspFile) == 0) { #ifdef _WIN32 - int commandLineLengthLimit = 8000 - linkRuleLength; + commandLineLengthLimit = 8000 - linkRuleLength; #elif defined(__linux) || defined(__APPLE__) - // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac - int commandLineLengthLimit = ((int)sysconf(_SC_ARG_MAX)) - - linkRuleLength - 1000; + // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac + commandLineLengthLimit = ((int)sysconf(_SC_ARG_MAX))-linkRuleLength-1000; #else - int commandLineLengthLimit = -1; + commandLineLengthLimit = -1; #endif + } + + const std::string rspfile = std::string + (cmake::GetCMakeFilesDirectoryPostSlash()) + + this->GetTarget()->GetName() + ".rsp"; // Write the build statement for this target. cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(), @@ -558,6 +581,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() implicitDeps, emptyDeps, vars, + rspfile, commandLineLengthLimit); if (targetOutput != targetOutputReal) { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 385b4a0..0f10152 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -134,7 +134,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, this->AddFeatureFlags(flags, language.c_str()); this->GetLocalGenerator()->AddArchitectureFlags(flags, - this->GetTarget(), + this->GeneratorTarget, language.c_str(), this->GetConfigName()); @@ -152,8 +152,10 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, // Add include directory flags. { std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, this->Target, - language.c_str()); + const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + language.c_str(), config); std::string includeFlags = this->LocalGenerator->GetIncludeFlags(includes, language.c_str(), language == "RC" ? true : false); // full include paths for RC @@ -225,10 +227,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language) // Add preprocessor definitions for this target and configuration. this->LocalGenerator->AppendDefines (defines, - this->Makefile->GetProperty("COMPILE_DEFINITIONS")); - this->LocalGenerator->AppendDefines - (defines, - this->Target->GetProperty("COMPILE_DEFINITIONS")); + this->GeneratorTarget->GetCompileDefinitions()); this->LocalGenerator->AppendDefines (defines, source->GetProperty("COMPILE_DEFINITIONS")); @@ -237,10 +236,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language) defPropName += cmSystemTools::UpperCase(this->GetConfigName()); this->LocalGenerator->AppendDefines (defines, - this->Makefile->GetProperty(defPropName.c_str())); - this->LocalGenerator->AppendDefines - (defines, - this->Target->GetProperty(defPropName.c_str())); + this->GeneratorTarget->GetCompileDefinitions(this->GetConfigName())); this->LocalGenerator->AppendDefines (defines, source->GetProperty(defPropName.c_str())); @@ -261,7 +257,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const return cmNinjaDeps(); cmComputeLinkInformation* cli = - this->Target->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); if(!cli) return cmNinjaDeps(); @@ -335,10 +331,10 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const this->Target->GetType() == cmTarget::SHARED_LIBRARY || this->Target->GetType() == cmTarget::MODULE_LIBRARY) { - pdbPath = this->Target->GetDirectory(this->GetConfigName()); + pdbPath = this->Target->GetPDBDirectory(this->GetConfigName()); pdbPath += "/"; pdbPath += this->Target->GetPDBName(this->GetConfigName()); - } + } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( ConvertToNinjaPath(pdbPath.c_str()).c_str(), @@ -374,7 +370,7 @@ cmNinjaTargetGenerator std::string flags = "$FLAGS"; vars.Defines = "$DEFINES"; vars.TargetPDB = "$TARGET_PDB"; - + vars.ObjectDir = "$OBJECT_DIR"; cmMakefile* mf = this->GetMakefile(); @@ -514,8 +510,6 @@ void cmNinjaTargetGenerator ::WriteObjectBuildStatement(cmSourceFile* source) { - cmNinjaDeps emptyDeps; - std::string comment; const std::string language = source->GetLanguage(); std::string rule = this->LanguageCompilerRule(language); @@ -539,11 +533,12 @@ cmNinjaTargetGenerator cmNinjaDeps orderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps); + cmNinjaDeps implicitDeps; if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> depList; cmSystemTools::ExpandListArgument(objectDeps, depList); std::transform(depList.begin(), depList.end(), - std::back_inserter(orderOnlyDeps), MapToNinjaPath()); + std::back_inserter(implicitDeps), MapToNinjaPath()); } // Add order-only dependencies on custom command outputs. @@ -554,7 +549,7 @@ cmNinjaTargetGenerator cmCustomCommand const* cc = (*si)->GetCustomCommand(); const std::vector<std::string>& ccoutputs = cc->GetOutputs(); std::transform(ccoutputs.begin(), ccoutputs.end(), - std::back_inserter(orderOnlyDeps), MapToNinjaPath()); + std::back_inserter(implicitDeps), MapToNinjaPath()); } // If the source file is GENERATED and does not have a custom command @@ -573,6 +568,13 @@ cmNinjaTargetGenerator vars["DEP_FILE"] = objectFileName + ".d";; EnsureParentDirectoryExists(objectFileName); + std::string objectDir = cmSystemTools::GetFilenamePath(objectFileName); + objectDir = this->GetLocalGenerator()->Convert(objectDir.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + vars["OBJECT_DIR"] = objectDir; + + this->SetMsvcTargetPdbVariable(vars); if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) @@ -597,6 +599,7 @@ cmNinjaTargetGenerator compileObjectVars.Source = escapedSourceFileName.c_str(); compileObjectVars.Object = objectFileName.c_str(); + compileObjectVars.ObjectDir = objectDir.c_str(); compileObjectVars.Flags = vars["FLAGS"].c_str(); compileObjectVars.Defines = vars["DEFINES"].c_str(); @@ -625,7 +628,7 @@ cmNinjaTargetGenerator rule, outputs, explicitDeps, - emptyDeps, + implicitDeps, orderOnlyDeps, vars); @@ -669,9 +672,19 @@ cmNinjaTargetGenerator void cmNinjaTargetGenerator -::EnsureDirectoryExists(const std::string& dir) const +::EnsureDirectoryExists(const std::string& path) const { - cmSystemTools::MakeDirectory(dir.c_str()); + if (cmSystemTools::FileIsFullPath(path.c_str())) + { + cmSystemTools::MakeDirectory(path.c_str()); + } + else + { + const std::string fullPath = std::string(this->GetGlobalGenerator()-> + GetCMakeInstance()->GetHomeOutputDirectory()) + + "/" + path; + cmSystemTools::MakeDirectory(fullPath.c_str()); + } } void diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index cd20694..cf06bfd 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -52,6 +52,9 @@ protected: cmTarget* GetTarget() const { return this->Target; } + cmGeneratorTarget* GetGeneratorTarget() const + { return this->GeneratorTarget; } + cmLocalNinjaGenerator* GetLocalGenerator() const { return this->LocalGenerator; } diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index 71feffd..942c7ab 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -111,6 +111,7 @@ cmQtAutomoc::cmQtAutomoc() void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) { cmMakefile* makefile = target->GetMakefile(); + cmLocalGenerator* localGen = makefile->GetLocalGenerator(); const char* targetName = target->GetName(); // don't do anything if there is no Qt4 or Qt5Core (which contains moc): std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); @@ -169,7 +170,8 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) ++fileIt) { cmSourceFile* sf = *fileIt; - std::string absFile = sf->GetFullPath(); + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath().c_str()); bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")); @@ -193,12 +195,28 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) } } - const char* tmp = makefile->GetProperty("INCLUDE_DIRECTORIES"); - std::string _moc_incs = (tmp!=0 ? tmp : ""); - tmp = makefile->GetProperty("DEFINITIONS"); - std::string _moc_defs = (tmp!=0 ? tmp : ""); - tmp = makefile->GetProperty("COMPILE_DEFINITIONS"); + std::vector<std::string> includeDirs; + cmGeneratorTarget gtgt(target); + localGen->GetIncludeDirectories(includeDirs, >gt, "CXX"); + std::string _moc_incs = ""; + const char* sep = ""; + for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin(); + incDirIt != includeDirs.end(); + ++incDirIt) + { + _moc_incs += sep; + sep = ";"; + _moc_incs += *incDirIt; + } + + const char* tmp = target->GetProperty("COMPILE_DEFINITIONS"); std::string _moc_compile_defs = (tmp!=0 ? tmp : ""); + tmp = makefile->GetProperty("COMPILE_DEFINITIONS"); + if (tmp) + { + _moc_compile_defs += ";"; + _moc_compile_defs += tmp; + } tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); std::string _moc_options = (tmp!=0 ? tmp : ""); @@ -210,8 +228,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) cmLocalGenerator::EscapeForCMake(automocTargetName.c_str()).c_str()); makefile->AddDefinition("_moc_incs", cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str()); - makefile->AddDefinition("_moc_defs", - cmLocalGenerator::EscapeForCMake(_moc_defs.c_str()).c_str()); makefile->AddDefinition("_moc_compile_defs", cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str()); makefile->AddDefinition("_moc_options", @@ -314,7 +330,6 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile, this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE"); this->MocCompileDefinitionsStr = makefile->GetSafeDefinition( "AM_MOC_COMPILE_DEFINITIONS"); - this->MocDefinitionsStr = makefile->GetSafeDefinition("AM_MOC_DEFINITIONS"); this->MocIncludesStr = makefile->GetSafeDefinition("AM_MOC_INCLUDES"); this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR"); @@ -332,7 +347,7 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile, std::string cmQtAutomoc::MakeCompileSettingsString(cmMakefile* makefile) { std::string s; - s += makefile->GetSafeDefinition("AM_MOC_DEFINITIONS"); + s += makefile->GetSafeDefinition("AM_MOC_COMPILE_DEFINITIONS"); s += " ~~~ "; s += makefile->GetSafeDefinition("AM_MOC_INCLUDES"); s += " ~~~ "; @@ -387,32 +402,11 @@ void cmQtAutomoc::Init() std::vector<std::string> cdefList; cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList); - if (!cdefList.empty()) - { - for(std::vector<std::string>::const_iterator it = cdefList.begin(); - it != cdefList.end(); - ++it) - { - this->MocDefinitions.push_back("-D" + (*it)); - } - } - else + for(std::vector<std::string>::const_iterator it = cdefList.begin(); + it != cdefList.end(); + ++it) { - std::string tmpMocDefs = this->MocDefinitionsStr; - cmSystemTools::ReplaceString(tmpMocDefs, " ", ";"); - - std::vector<std::string> defList; - cmSystemTools::ExpandListArgument(tmpMocDefs, defList); - - for(std::vector<std::string>::const_iterator it = defList.begin(); - it != defList.end(); - ++it) - { - if (this->StartsWith(*it, "-D")) - { - this->MocDefinitions.push_back(*it); - } - } + this->MocDefinitions.push_back("-D" + (*it)); } cmSystemTools::ExpandListArgument(this->MocOptionsStr, this->MocOptions); diff --git a/Source/cmQtAutomoc.h b/Source/cmQtAutomoc.h index f6d72e2..a737477 100644 --- a/Source/cmQtAutomoc.h +++ b/Source/cmQtAutomoc.h @@ -69,7 +69,6 @@ private: std::string Builddir; std::string MocExecutable; std::string MocCompileDefinitionsStr; - std::string MocDefinitionsStr; std::string MocIncludesStr; std::string MocOptionsStr; std::string ProjectBinaryDir; diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 43a0dbe..728b1bc 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -133,7 +133,8 @@ public: " . Matches any single character\n" " [ ] Matches any character(s) inside the brackets\n" " [^ ] Matches any character(s) not inside the brackets\n" - " - Matches any character in range on either side of a dash\n" + " - Inside brackets, specifies an inclusive range between\n" + " characters on either side e.g. [a-f] is [abcdef]\n" " * Matches preceding pattern zero or more times\n" " + Matches preceding pattern one or more times\n" " ? Matches preceding pattern zero or once only\n" diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9a3812c..f3eb52b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -15,8 +15,8 @@ #include "cmSourceFile.h" #include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" -#include "cmComputeLinkInformation.h" #include "cmDocumentCompileDefinitions.h" +#include "cmDocumentGeneratorExpressions.h" #include "cmDocumentLocationUndefined.h" #include "cmListFileCache.h" #include "cmGeneratorExpression.h" @@ -57,6 +57,7 @@ struct cmTarget::OutputInfo { std::string OutDir; std::string ImpDir; + std::string PdbDir; }; //---------------------------------------------------------------------------- @@ -205,6 +206,9 @@ void cmTarget::DefineProperties(cmake *cm) "are not supported by the native build tool. " "The VS6 IDE does not support definition values with spaces " "(but NMake does).\n" + "Contents of COMPILE_DEFINITIONS may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER); cm->DefineProperty @@ -498,8 +502,11 @@ void cmTarget::DefineProperties(cmake *cm) "to the include_directories command." "\n" "The target property values are used by the generators to set " - "the include paths for the compiler. " - "See also the include_directories command."); + "the include paths for the compiler. " + "See also the include_directories command.\n" + "Contents of INCLUDE_DIRECTORIES may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); cm->DefineProperty ("INSTALL_NAME_DIR", cmProperty::TARGET, @@ -741,6 +748,22 @@ void cmTarget::DefineProperties(cmake *cm) "Use OUTPUT_NAME_<CONFIG> instead."); cm->DefineProperty + ("PDB_NAME", cmProperty::TARGET, + "Output name for MS debug symbols .pdb file.", + "Set the base name for debug symbols file created for an " + "executable or library target. " + "If not set, the logical target name is used by default. " + "\n" + "This property is not implemented by the Visual Studio 6 generator."); + + cm->DefineProperty + ("PDB_NAME_<CONFIG>", cmProperty::TARGET, + "Per-configuration name for MS debug symbols .pdb file. ", + "This is the configuration-specific version of PDB_NAME. " + "\n" + "This property is not implemented by the Visual Studio 6 generator."); + + cm->DefineProperty ("PRE_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the " @@ -1190,6 +1213,27 @@ void cmTarget::DefineProperties(cmake *cm) CM_TARGET_OUTDIR_CONFIG_DOC(RUNTIME)); cm->DefineProperty + ("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET, + "Output directory for MS debug symbols .pdb files.", + "This property specifies the directory into which the MS debug symbols " + "will be placed. " + "This property is initialized by the value of the variable " + "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created." + "\n" + "This property is not implemented by the Visual Studio 6 generator."); + cm->DefineProperty + ("PDB_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET, + "Per-configuration output directory for MS debug symbols .pdb files.", + "This is a per-configuration version of PDB_OUTPUT_DIRECTORY, " + "but multi-configuration generators (VS, Xcode) do NOT append " + "a per-configuration subdirectory to the specified directory. " + "This property is initialized by the value of the variable " + "CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG> " + "if it is set when a target is created." + "\n" + "This property is not implemented by the Visual Studio 6 generator."); + + cm->DefineProperty ("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET, "Output name for ARCHIVE target files.", "This property specifies the base name for archive target files. " @@ -1263,6 +1307,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("Fortran_FORMAT", 0); this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0); this->SetPropertyDefault("GNUtoMS", 0); @@ -1282,6 +1327,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) "ARCHIVE_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_", "RUNTIME_OUTPUT_DIRECTORY_", + "PDB_OUTPUT_DIRECTORY_", 0}; for(std::vector<std::string>::iterator ci = configNames.begin(); ci != configNames.end(); ++ci) @@ -2014,9 +2060,8 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) } //---------------------------------------------------------------------------- -bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType llt) +bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType) { - (void)llt; // TODO: What is this? if(this->NameResolvesToFramework(libname.c_str())) { std::string frameworkDir = libname; @@ -2296,7 +2341,7 @@ void cmTarget::Emit(const LibraryID lib, // be preserved. // This variable will keep track of the libraries that were - // emitted directory from the current node, and not from a + // emitted directly from the current node, and not from a // recursive call. This way, if we come across a library that // has already been emitted, we repeat it iff it has been // emitted here. @@ -2414,7 +2459,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value, //---------------------------------------------------------------------------- void cmTarget::MaybeInvalidatePropertyCache(const char* prop) { - // Wipe wipe out maps caching information affected by this property. + // Wipe out maps caching information affected by this property. if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0) { this->Internal->ImportInfoMap.clear(); @@ -2539,6 +2584,10 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config) OutputInfo info; this->ComputeOutputDir(config, false, info.OutDir); this->ComputeOutputDir(config, true, info.ImpDir); + if(!this->ComputePDBOutputDir(config, info.PdbDir)) + { + info.PdbDir = info.OutDir; + } OutputInfoMapType::value_type entry(config_upper, info); i = this->Internal->OutputInfoMap.insert(entry).first; } @@ -2564,6 +2613,17 @@ std::string cmTarget::GetDirectory(const char* config, bool implib) } //---------------------------------------------------------------------------- +std::string cmTarget::GetPDBDirectory(const char* config) +{ + if(OutputInfo const* info = this->GetOutputInfo(config)) + { + // Return the directory in which the target will be built. + return info->PdbDir; + } + return ""; +} + +//---------------------------------------------------------------------------- const char* cmTarget::GetLocation(const char* config) { if (this->IsImported()) @@ -2954,25 +3014,6 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc) } //---------------------------------------------------------------------------- -const char* cmTarget::GetCreateRuleVariable() -{ - switch(this->GetType()) - { - case cmTarget::STATIC_LIBRARY: - return "_CREATE_STATIC_LIBRARY"; - case cmTarget::SHARED_LIBRARY: - return "_CREATE_SHARED_LIBRARY"; - case cmTarget::MODULE_LIBRARY: - return "_CREATE_SHARED_MODULE"; - case cmTarget::EXECUTABLE: - return "_LINK_EXECUTABLE"; - default: - break; - } - return ""; -} - -//---------------------------------------------------------------------------- const char* cmTarget::GetSuffixVariableInternal(bool implib) { switch(this->GetType()) @@ -3028,6 +3069,28 @@ std::string cmTarget::GetPDBName(const char* config) std::string base; std::string suffix; this->GetFullNameInternal(config, false, prefix, base, suffix); + + std::vector<std::string> props; + std::string configUpper = + cmSystemTools::UpperCase(config? 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->c_str())) + { + base = outName; + break; + } + } return prefix+base+".pdb"; } @@ -3412,7 +3475,7 @@ void cmTarget::GetLibraryNames(std::string& name, } // The program database file name. - pdbName = prefix+base+".pdb"; + pdbName = this->GetPDBName(config); } //---------------------------------------------------------------------------- @@ -3491,7 +3554,7 @@ void cmTarget::GetExecutableNames(std::string& name, impName = this->GetFullNameInternal(config, true); // The program database file name. - pdbName = prefix+base+".pdb"; + pdbName = this->GetPDBName(config); } //---------------------------------------------------------------------------- @@ -3570,7 +3633,7 @@ void cmTarget::GenerateTargetManifest(const char* config) } if(!pdbName.empty()) { - f = dir; + f = this->GetPDBDirectory(config); f += "/"; f += pdbName; gg->AddToManifest(config? config:"", f); @@ -3880,6 +3943,65 @@ bool cmTarget::ComputeOutputDir(const char* config, } //---------------------------------------------------------------------------- +bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out) +{ + // Look for a target property defining the target output directory + // based on the target type. + std::string targetTypeName = "PDB"; + const char* propertyName = 0; + std::string propertyNameStr = targetTypeName; + if(!propertyNameStr.empty()) + { + propertyNameStr += "_OUTPUT_DIRECTORY"; + propertyName = propertyNameStr.c_str(); + } + + // Check for a per-configuration output directory target property. + std::string configUpper = cmSystemTools::UpperCase(config? config : ""); + const char* configProp = 0; + std::string configPropStr = targetTypeName; + if(!configPropStr.empty()) + { + configPropStr += "_OUTPUT_DIRECTORY_"; + configPropStr += configUpper; + configProp = configPropStr.c_str(); + } + + // Select an output directory. + if(const char* config_outdir = this->GetProperty(configProp)) + { + // Use the user-specified per-configuration output directory. + out = config_outdir; + + // Skip per-configuration subdirectory. + config = 0; + } + else if(const char* outdir = this->GetProperty(propertyName)) + { + // Use the user-specified output directory. + out = outdir; + } + if(out.empty()) + { + return false; + } + + // Convert the output path to a full path in case it is + // specified as a relative path. Treat a relative path as + // relative to the current output directory for this makefile. + out = (cmSystemTools::CollapseFullPath + (out.c_str(), this->Makefile->GetStartOutputDirectory())); + + // The generator may add the configuration's subdirectory. + if(config && *config) + { + this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> + AppendDirectoryForConfig("/", config, "", out); + } + return true; +} + +//---------------------------------------------------------------------------- bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib) { std::string dir; @@ -3980,27 +4102,6 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const } //---------------------------------------------------------------------------- -void cmTarget::GetAppleArchs(const char* config, - std::vector<std::string>& archVec) -{ - const char* archs = 0; - if(config && *config) - { - std::string defVarName = "OSX_ARCHITECTURES_"; - defVarName += cmSystemTools::UpperCase(config); - archs = this->GetProperty(defVarName.c_str()); - } - if(!archs) - { - archs = this->GetProperty("OSX_ARCHITECTURES"); - } - if(archs) - { - cmSystemTools::ExpandListArgument(std::string(archs), archVec); - } -} - -//---------------------------------------------------------------------------- bool cmTarget::IsChrpathUsed(const char* config) { #if defined(CMAKE_USE_ELF_PARSER) @@ -4671,56 +4772,6 @@ std::string cmTarget::CheckCMP0004(std::string const& item) } //---------------------------------------------------------------------------- -cmComputeLinkInformation* -cmTarget::GetLinkInformation(const char* config) -{ - // Lookup any existing information for this configuration. - std::map<cmStdString, cmComputeLinkInformation*>::iterator - i = this->LinkInformation.find(config?config:""); - 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. - std::map<cmStdString, cmComputeLinkInformation*>::value_type - entry(config?config:"", info); - i = this->LinkInformation.insert(entry).first; - } - return i->second; -} - -//---------------------------------------------------------------------------- -std::vector<std::string> cmTarget::GetIncludeDirectories() -{ - std::vector<std::string> includes; - const char *prop = this->GetProperty("INCLUDE_DIRECTORIES"); - if(prop) - { - cmSystemTools::ExpandListArgument(prop, includes); - } - - std::set<std::string> uniqueIncludes; - std::vector<std::string> orderedAndUniqueIncludes; - for(std::vector<std::string>::const_iterator - li = includes.begin(); li != includes.end(); ++li) - { - if(uniqueIncludes.insert(*li).second) - { - orderedAndUniqueIncludes.push_back(*li); - } - } - - return orderedAndUniqueIncludes; -} - -//---------------------------------------------------------------------------- std::string cmTarget::GetFrameworkDirectory(const char* config) { std::string fpath; @@ -4778,29 +4829,6 @@ std::string cmTarget::GetMacContentDirectory(const char* config, } //---------------------------------------------------------------------------- -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() -{ - for(derived::iterator i = this->begin(); i != this->end(); ++i) - { - delete i->second; - } -} - -//---------------------------------------------------------------------------- cmTargetInternalPointer::cmTargetInternalPointer() { this->Pointer = new cmTargetInternals; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 98eaeec..e442d25 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -22,18 +22,8 @@ class cmake; class cmMakefile; class cmSourceFile; class cmGlobalGenerator; -class cmComputeLinkInformation; class cmListFileBacktrace; -struct cmTargetLinkInformationMap: - public std::map<cmStdString, cmComputeLinkInformation*> -{ - typedef std::map<cmStdString, cmComputeLinkInformation*> derived; - cmTargetLinkInformationMap() {} - cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); - ~cmTargetLinkInformationMap(); -}; - class cmTargetInternals; class cmTargetInternalPointer { @@ -301,6 +291,12 @@ public: output directory is given. */ std::string GetDirectory(const char* config = 0, bool implib = false); + /** Get the directory in which this targets .pdb files will be placed. + If the configuration name is given then the generator will add its + subdirectory for that configuration. Otherwise just the canonical + pdb output directory is given. */ + std::string GetPDBDirectory(const char* config = 0); + /** Get the location of the target in the build tree for the given configuration. This location is suitable for use as the LOCATION target property. */ @@ -330,10 +326,6 @@ public: ///! Return the preferred linker language for this target const char* GetLinkerLanguage(const char* config = 0); - ///! Return the rule variable used to create this type of target, - // need to add CMAKE_(LANG) for full name. - const char* GetCreateRuleVariable(); - /** Get the full name of the target according to the settings in its makefile. */ std::string GetFullName(const char* config=0, bool implib = false); @@ -400,8 +392,6 @@ public: std::string GetInstallNameDirForInstallTree(const char* config, bool for_xcode = false); - cmComputeLinkInformation* GetLinkInformation(const char* config); - // Get the properties cmPropertyMap &GetProperties() { return this->Properties; }; @@ -419,9 +409,6 @@ public: // until we have per-target object file properties. void GetLanguages(std::set<cmStdString>& languages) const; - /** Get the list of OS X target architectures to be built. */ - void GetAppleArchs(const char* config, std::vector<std::string>& archVec); - /** Return whether this target is an executable with symbol exports enabled. */ bool IsExecutableWithExports(); @@ -459,9 +446,6 @@ public: directory. */ bool UsesDefaultOutputDir(const char* config, bool implib); - /** Get the include directories for this target. */ - std::vector<std::string> GetIncludeDirectories(); - /** Append to @a base the mac content directory and return it. */ std::string BuildMacContentDirectory(const std::string& base, const char* config = 0, @@ -593,14 +577,13 @@ private: struct OutputInfo; OutputInfo const* GetOutputInfo(const char* config); bool ComputeOutputDir(const char* config, bool implib, std::string& out); + bool ComputePDBOutputDir(const char* config, std::string& out); // Cache import information from properties for each configuration. struct ImportInfo; ImportInfo const* GetImportInfo(const char* config); void ComputeImportInfo(std::string const& desired_config, ImportInfo& info); - cmTargetLinkInformationMap LinkInformation; - bool ComputeLinkInterface(const char* config, LinkInterface& iface); void ComputeLinkImplementation(const char* config, diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h new file mode 100644 index 0000000..c9d87fb --- /dev/null +++ b/Source/cmTargetExport.h @@ -0,0 +1,39 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 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 cmTargetExport_h +#define cmTargetExport_h + +class cmTarget; +class cmInstallTargetGenerator; +class cmInstallFilesGenerator; + +/** \brief A member of an ExportSet + * + * This struct holds pointers to target and all relevant generators. + */ +class cmTargetExport +{ +public: + cmTarget* Target; ///< The target + + ///@name Generators + ///@{ + cmInstallTargetGenerator* ArchiveGenerator; + cmInstallTargetGenerator* RuntimeGenerator; + cmInstallTargetGenerator* LibraryGenerator; + cmInstallTargetGenerator* FrameworkGenerator; + cmInstallTargetGenerator* BundleGenerator; + cmInstallFilesGenerator* HeaderGenerator; + ///@} +}; + +#endif diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index dbea1c3..f42b0f6 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -108,8 +108,8 @@ bool cmTargetLinkLibrariesCommand // specification if the keyword is encountered as the first argument. this->CurrentProcessingState = ProcessingLinkLibraries; - // add libraries, nothe that there is an optional prefix - // of debug and optimized than can be used + // add libraries, note that there is an optional prefix + // of debug and optimized that can be used for(unsigned int i=1; i < args.size(); ++i) { if(args[i] == "LINK_INTERFACE_LIBRARIES") diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 3d2828d..1e37ca5 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1225,21 +1225,16 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( flags += " "; flags += targetFlags; } - std::string configUpper = cmSystemTools::UpperCase(configName); - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += configUpper; - // Get preprocessor definitions for this directory. std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags(); clOptions.FixExceptionHandlingDefault(); clOptions.AddFlag("PrecompiledHeader", "NotUsing"); clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); - clOptions.AddDefines - (this->Makefile->GetProperty("COMPILE_DEFINITIONS")); - clOptions.AddDefines(this->Target->GetProperty("COMPILE_DEFINITIONS")); - clOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str())); - clOptions.AddDefines(this->Target->GetProperty(defPropName.c_str())); + clOptions.AddDefines( + this->GeneratorTarget->GetCompileDefinitions().c_str()); + clOptions.AddDefines(this->GeneratorTarget->GetCompileDefinitions( + configName.c_str()).c_str()); clOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); @@ -1284,9 +1279,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY) { - // TODO: PDB for object library? this->WriteString("<ProgramDataBaseFileName>", 3); - *this->BuildFileStream << this->Target->GetDirectory(configName.c_str()) + *this->BuildFileStream << this->Target->GetPDBDirectory(configName.c_str()) << "/" << this->Target->GetPDBName(configName.c_str()) << "</ProgramDataBaseFileName>\n"; @@ -1452,7 +1446,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& // Replace spaces in libs with ; cmSystemTools::ReplaceString(libs, " ", ";"); cmComputeLinkInformation* pcli = - this->Target->GetLinkInformation(config.c_str()); + this->GeneratorTarget->GetLinkInformation(config.c_str()); if(!pcli) { cmSystemTools::Error @@ -1511,9 +1505,8 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config.c_str()); } - std::string dir = this->Target->GetDirectory(config.c_str()); - dir += "/"; - std::string pdb = dir; + std::string pdb = this->Target->GetPDBDirectory(config.c_str()); + pdb += "/"; pdb += targetNamePDB; std::string imLib = this->Target->GetDirectory(config.c_str(), true); imLib += "/"; @@ -1593,11 +1586,13 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() std::vector<std::string> *configs = static_cast<cmGlobalVisualStudio7Generator *> (this->GlobalGenerator)->GetConfigurations(); - std::vector<std::string> includes; - this->LocalGenerator->GetIncludeDirectories(includes, this->Target); for(std::vector<std::string>::iterator i = configs->begin(); i != configs->end(); ++i) { + std::vector<std::string> includes; + this->LocalGenerator->GetIncludeDirectories(includes, + this->GeneratorTarget, + "C", i->c_str()); this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1); *this->BuildFileStream << "\n"; // output cl compile flags <ClCompile></ClCompile> diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1750daa..0123427 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -628,9 +628,14 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string linkLibs; + std::string frameworkPath; + std::string linkPath; std::string flags; std::string linkFlags; - lg->GetTargetFlags(linkLibs, flags, linkFlags, *tgt); + cmGeneratorTarget gtgt(tgt); + lg->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags, + >gt); + linkLibs = frameworkPath + linkPath + linkLibs; printf("%s\n", linkLibs.c_str() ); @@ -1682,19 +1687,11 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args) } else if (args[1] == "vs_link_exe") { - return cmake::VisualStudioLink(args, 1, false); + return cmake::VisualStudioLink(args, 1); } else if (args[1] == "vs_link_dll") { - return cmake::VisualStudioLink(args, 2, false); - } - else if (args[1] == "vs_link_exe_no_rsp_expand") - { - return cmake::VisualStudioLink(args, 1, true); - } - else if (args[1] == "vs_link_dll_no_rsp_expand") - { - return cmake::VisualStudioLink(args, 2, true); + return cmake::VisualStudioLink(args, 2); } #ifdef CMAKE_BUILD_WITH_CMAKE // Internal CMake color makefile support. @@ -4020,8 +4017,7 @@ static bool cmakeCheckStampList(const char* stampList) // For visual studio 2005 and newer manifest files need to be embeded into // exe and dll's. This code does that in such a way that incremental linking // still works. -int cmake::VisualStudioLink(std::vector<std::string>& args, int type, - bool no_rsp_expand) +int cmake::VisualStudioLink(std::vector<std::string>& args, int type) { if(args.size() < 2) { @@ -4036,12 +4032,13 @@ int cmake::VisualStudioLink(std::vector<std::string>& args, int type, for(std::vector<std::string>::iterator i = args.begin(); i != args.end(); ++i) { - // check for nmake temporary files (there are two rsp files) - if(!no_rsp_expand && (*i)[0] == '@' && i->find("@CMakeFiles") != 0 ) + // check for nmake temporary files + if((*i)[0] == '@' && i->find("@CMakeFiles") != 0 ) { std::ifstream fin(i->substr(1).c_str()); std::string line; - while(cmSystemTools::GetLineFromStream(fin, line)) + while(cmSystemTools::GetLineFromStream(fin, + line)) { cmSystemTools::ParseWindowsCommandLine(line.c_str(), expandedArgs); } diff --git a/Source/cmake.h b/Source/cmake.h index 12e5edf..94c6f12 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -447,8 +447,7 @@ protected: std::string const& link); static int ExecuteEchoColor(std::vector<std::string>& args); static int ExecuteLinkScript(std::vector<std::string>& args); - static int VisualStudioLink(std::vector<std::string>& args, int type, - bool no_rsp_expand); + static int VisualStudioLink(std::vector<std::string>& args, int type); static int VisualStudioLinkIncremental(std::vector<std::string>& args, int type, bool verbose); |