From 711e2b3b5c674d4f754b5b214d511be6ce7e8f4d Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Fri, 5 Oct 2012 21:55:07 +0200 Subject: [PATCH 001/131] CMake: Add TIMESTAMP subcommand to string and file commands --- Source/cmBootstrapCommands.cxx | 1 + Source/cmFileCommand.cxx | 57 ++++++++ Source/cmFileCommand.h | 10 ++ Source/cmStringCommand.cxx | 54 +++++++ Source/cmStringCommand.h | 30 +++- Source/cmTimestamp.cxx | 134 ++++++++++++++++++ Source/cmTimestamp.h | 40 ++++++ Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake | 1 + Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake | 2 + .../CMakeTests/File-TIMESTAMP-NotBogus.cmake | 24 ++++ Tests/CMakeTests/File-TIMESTAMP-Works.cmake | 2 + Tests/CMakeTests/FileTest.cmake.in | 12 ++ .../String-TIMESTAMP-AllSpecifiers.cmake | 11 ++ .../CMakeTests/String-TIMESTAMP-BadArg1.cmake | 1 + .../CMakeTests/String-TIMESTAMP-BadArg2.cmake | 1 + .../CMakeTests/String-TIMESTAMP-BadArg3.cmake | 1 + .../String-TIMESTAMP-CustomFormatLocal.cmake | 2 + .../String-TIMESTAMP-CustomFormatUTC.cmake | 2 + .../String-TIMESTAMP-DefaulFormatUTC.cmake | 2 + .../String-TIMESTAMP-DefaultFormatLocal.cmake | 2 + .../String-TIMESTAMP-DefaultFormatUTC.cmake | 2 + ...String-TIMESTAMP-IncompleteSpecifier.cmake | 2 + .../String-TIMESTAMP-UnknownSpecifier.cmake | 2 + Tests/CMakeTests/StringTest.cmake.in | 30 ++++ 24 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 Source/cmTimestamp.cxx create mode 100644 Source/cmTimestamp.h create mode 100644 Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake create mode 100644 Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake create mode 100644 Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake create mode 100644 Tests/CMakeTests/File-TIMESTAMP-Works.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake create mode 100644 Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx index 9097a7482..e3a2ad4e5 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands.cxx @@ -89,6 +89,7 @@ #include "cmStringCommand.cxx" #include "cmSubdirCommand.cxx" #include "cmTargetLinkLibrariesCommand.cxx" +#include "cmTimestamp.cxx" #include "cmTryCompileCommand.cxx" #include "cmTryRunCommand.cxx" #include "cmUnsetCommand.cxx" diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index b877f3c3a..42df3a17f 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -17,6 +17,8 @@ #include "cmFileTimeComparison.h" #include "cmCryptoHash.h" +#include "cmTimestamp.h" + #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_curl.h" #endif @@ -161,6 +163,10 @@ bool cmFileCommand { return this->HandleCMakePathCommand(args, true); } + else if ( subCommand == "TIMESTAMP" ) + { + return this->HandleTimestampCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -3241,3 +3247,54 @@ cmFileCommand::HandleUploadCommand(std::vector const& args) return false; #endif } + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleTimestampCommand( + std::vector const& args) +{ + if(args.size() < 3) + { + this->SetError("sub-command TIMESTAMP requires at least two arguments."); + return false; + } + else if(args.size() > 5) + { + this->SetError("sub-command TIMESTAMP takes at most four arguments."); + return false; + } + + int argsIndex = 1; + + const std::string& filename = args[argsIndex++]; + + const std::string& outputVariable = args[argsIndex++]; + + std::string formatString; + if(args.size() > argsIndex && args[argsIndex] != "UTC") + { + formatString = args[argsIndex++]; + } + + bool utcFlag = false; + if(args.size() > argsIndex) + { + if(args[argsIndex] == "UTC") + { + utcFlag = true; + } + else + { + std::string e = " TIMESTAMP sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e.c_str()); + return false; + } + } + + cmTimestamp timestamp; + std::string result = timestamp.FileModificationTime( + filename.c_str(), formatString, utcFlag); + this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str()); + + return true; +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index a0862ec9b..5550dbe64 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -87,6 +87,8 @@ public: " [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" + " file(TIMESTAMP " + " [] [UTC])\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist. (If the file is a build input, use " @@ -200,6 +202,12 @@ public: "If SHOW_PROGRESS is specified, progress information will be printed " "as status messages until the operation is complete." "\n" + "TIMESTAMP will write a string representation of " + "the modification time of to .\n" + "Should the command be unable to obtain a timestamp " + " will be set to the empty string \"\".\n" + "See documentation of the string TIMESTAMP sub-command for more details." + "\n" "The file() command also provides COPY and INSTALL signatures:\n" " file( files... DESTINATION \n" " [FILE_PERMISSIONS permissions...]\n" @@ -260,6 +268,8 @@ protected: bool HandleInstallCommand(std::vector const& args); bool HandleDownloadCommand(std::vector const& args); bool HandleUploadCommand(std::vector const& args); + + bool HandleTimestampCommand(std::vector const& args); }; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 0193dc9e7..c402738fe 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -19,6 +19,8 @@ #include #include +#include + //---------------------------------------------------------------------------- bool cmStringCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) @@ -87,6 +89,10 @@ bool cmStringCommand { return this->HandleFindCommand(args); } + else if(subCommand == "TIMESTAMP") + { + return this->HandleTimestampCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -879,3 +885,51 @@ bool cmStringCommand this->Makefile->AddDefinition(variableName.c_str(), &*result.begin()); return true; } + +//---------------------------------------------------------------------------- +bool cmStringCommand +::HandleTimestampCommand(std::vector const& args) +{ + if(args.size() < 2) + { + this->SetError("sub-command TIMESTAMP requires at least one argument."); + return false; + } + else if(args.size() > 4) + { + this->SetError("sub-command TIMESTAMP takes at most three arguments."); + return false; + } + + int argsIndex = 1; + + const std::string &outputVariable = args[argsIndex++]; + + std::string formatString; + if(args.size() > argsIndex && args[argsIndex] != "UTC") + { + formatString = args[argsIndex++]; + } + + bool utcFlag = false; + if(args.size() > argsIndex) + { + if(args[argsIndex] == "UTC") + { + utcFlag = true; + } + else + { + std::string e = " TIMESTAMP sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e.c_str()); + return false; + } + } + + cmTimestamp timestamp; + std::string result = timestamp.CurrentTime(formatString, utcFlag); + this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str()); + + return true; +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 728b1bc5f..7e0694ed6 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -93,6 +93,7 @@ public: " string(RANDOM [LENGTH ] [ALPHABET ]\n" " [RANDOM_SEED ] )\n" " string(FIND [REVERSE])\n" + " string(TIMESTAMP [] [UTC])\n" "REGEX MATCH will match the regular expression once and store the " "match in the output variable.\n" "REGEX MATCHALL will match the regular expression as many times as " @@ -142,7 +143,33 @@ public: " () Saves a matched subexpression, which can be referenced \n" " in the REGEX REPLACE operation. Additionally it is saved\n" " by all regular expression-related commands, including \n" - " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9)."; + " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n" + "TIMESTAMP will write a string representation of " + "the current date and/or time to .\n" + "Should the command be unable to obtain a timestamp " + " will be set to the empty string \"\".\n" + "The optional UTC flag requests the current date/time " + "representation to be in Coordinated Universal Time (UTC) " + "rather than local time.\n" + "The optional may contain the following " + "format specifiers: \n" + " %d The day of the current month (01-31).\n" + " %H The hour on a 24-hour clock (00-23).\n" + " %I The hour on a 12-hour clock (01-12).\n" + " %j The day of the current year (001-366).\n" + " %m The month of the current year (01-12).\n" + " %M The minute of the current hour (00-59).\n" + " %S The second of the current minute.\n" + " 60 represents a leap second. (00-60)\n" + " %U The week number of the current year (00-53).\n" + " %w The day of the current week. 0 is Sunday. (0-6)\n" + " %y The last two digits of the current year (00-99)\n" + " %Y The current year. \n" + "Unknown format specifiers will be ignored " + "and copied to the output as-is.\n" + "If no explicit is given it will default to:\n" + " %Y-%m-%dT%H:%M:%S for local time.\n" + " %Y-%m-%dT%H:%M:%SZ for UTC."; } cmTypeMacro(cmStringCommand, cmCommand); @@ -165,6 +192,7 @@ protected: bool HandleStripCommand(std::vector const& args); bool HandleRandomCommand(std::vector const& args); bool HandleFindCommand(std::vector const& args); + bool HandleTimestampCommand(std::vector const& args); class RegexReplacement { diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx new file mode 100644 index 000000000..f1115e672 --- /dev/null +++ b/Source/cmTimestamp.cxx @@ -0,0 +1,134 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 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 "cmTimestamp.h" + +#include + +#include +#include + +//---------------------------------------------------------------------------- +std::string cmTimestamp::CurrentTime( + const std::string& formatString, bool utcFlag) +{ + time_t currentTimeT = time(0); + if(currentTimeT == time_t(-1)) return std::string(); + + return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); +} + +std::string cmTimestamp::FileModificationTime(const char* path, + const std::string& formatString, bool utcFlag) +{ +#ifdef _WIN32 + struct _stat info; + std::memset(&info, 0, sizeof(info)); + + if(_stat(path, &info) != 0) + return std::string(); + + time_t currentTimeT = info.st_mtime; +#else + struct stat info; + std::memset(&info, 0, sizeof(info)); + + if(stat(path, &info) != 0) + return std::string(); + + time_t currentTimeT = info.st_mtime; +#endif + + return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); +} + +std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, + std::string formatString, bool utcFlag) +{ + if(formatString.empty()) + { + formatString = "%Y-%m-%dT%H:%M:%S"; + if(utcFlag) formatString += "Z"; + } + + struct tm timeStruct; + std::memset(&timeStruct, 0, sizeof(timeStruct)); + + if(utcFlag) + { + tm* ptr = gmtime(&timeT); + if(ptr == 0) return std::string(); + + timeStruct = *ptr; + } + else + { + struct tm* ptr = localtime(&timeT); + if(ptr == 0) return std::string(); + + timeStruct = *ptr; + } + + std::string result; + for(std::string::size_type i = 0; i < formatString.size(); ++i) + { + char c1 = formatString[i]; + char c2 = (i+1 < formatString.size()) ? + formatString[i+1] : 0; + + if(c1 == '%' && c2 != 0) + { + result += AddTimestampComponent(c2, timeStruct); + ++i; + } + else + { + result += c1; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +std::string cmTimestamp::AddTimestampComponent( + char flag, struct tm& timeStruct) +{ + std::string formatString = "%"; + formatString += flag; + + switch(flag) + { + case 'd': + case 'H': + case 'I': + case 'j': + case 'm': + case 'M': + case 'S': + case 'U': + case 'w': + case 'y': + case 'Y': + break; + default: + { + return formatString; + } + } + + char buffer[16]; + + size_t size = strftime(buffer, sizeof(buffer), + formatString.c_str(), &timeStruct); + + return std::string(buffer, size); +} diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h new file mode 100644 index 000000000..24c186983 --- /dev/null +++ b/Source/cmTimestamp.h @@ -0,0 +1,40 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 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 cmTimestamp_h +#define cmTimestamp_h + +#include +#include + +/** \class cmTimestamp + * \brief Utility class to generate sting representation of a timestamp + * + */ +class cmTimestamp +{ +public: + cmTimestamp() {} + + std::string CurrentTime(const std::string& formatString, bool utcFlag); + + std::string FileModificationTime(const char* path, + const std::string& formatString, bool utcFlag); + +private: + std::string CreateTimestampFromTimeT(time_t timeT, + std::string formatString, bool utcFlag); + + std::string AddTimestampComponent(char flag, struct tm& timeStruct); +}; + + +#endif diff --git a/Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake b/Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake new file mode 100644 index 000000000..cc15c77a8 --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-BadArg1.cmake @@ -0,0 +1 @@ +file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") diff --git a/Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake b/Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake new file mode 100644 index 000000000..62390e792 --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-NoFile.cmake @@ -0,0 +1,2 @@ +file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/DoesNotExist.cmake" output) +message("~${output}~") diff --git a/Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake b/Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake new file mode 100644 index 000000000..d0e5fe35f --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake @@ -0,0 +1,24 @@ +set(STAMP_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/FileTimestamp-Stamp") +set(STAMP_FORMAT "%Y-%m-%d") + +string(TIMESTAMP timestamp1 "${STAMP_FORMAT}") + +file(WRITE "${STAMP_FILENAME}" "foo") +file(TIMESTAMP "${STAMP_FILENAME}" timestamp2 "${STAMP_FORMAT}") + +string(TIMESTAMP timestamp3 "${STAMP_FORMAT}") + +message(STATUS "timestamp1 [${timestamp1}]") +message(STATUS "timestamp2 [${timestamp2}]") +message(STATUS "timestamp3 [${timestamp3}]") + +if(timestamp1 STREQUAL timestamp3) + if(NOT timestamp1 STREQUAL timestamp2) + message(FATAL_ERROR + "timestamp mismatch [${timestamp1}] != [${timestamp2}]") + else() + message("all timestamps match") + endif() +else() + message(WARNING "this test may race when run at midnight") +endif() diff --git a/Tests/CMakeTests/File-TIMESTAMP-Works.cmake b/Tests/CMakeTests/File-TIMESTAMP-Works.cmake new file mode 100644 index 000000000..4351b19dd --- /dev/null +++ b/Tests/CMakeTests/File-TIMESTAMP-Works.cmake @@ -0,0 +1,2 @@ +file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt" output UTC) +message("~${output}~") diff --git a/Tests/CMakeTests/FileTest.cmake.in b/Tests/CMakeTests/FileTest.cmake.in index 960d3c172..61523e6f6 100644 --- a/Tests/CMakeTests/FileTest.cmake.in +++ b/Tests/CMakeTests/FileTest.cmake.in @@ -36,6 +36,14 @@ set(SHA384-Works-RESULT 0) set(SHA384-Works-STDERR "1de9560b4e030e02051ea408200ffc55d70c97ac64ebf822461a5c786f495c36df43259b14483bc8d364f0106f4971ee") set(SHA512-Works-RESULT 0) set(SHA512-Works-STDERR "3982a1b4e651768bec70ab1fb97045cb7a659f4ba7203d501c52ab2e803071f9d5fd272022df15f27727fc67f8cd022e710e29010b2a9c0b467c111e2f6abf51") +set(TIMESTAMP-NoFile-RESULT 0) +set(TIMESTAMP-NoFile-STDERR "~~") +set(TIMESTAMP-BadArg1-RESULT 1) +set(TIMESTAMP-BadArg1-STDERR "file sub-command TIMESTAMP requires at least two arguments") +set(TIMESTAMP-NotBogus-RESULT 0) +set(TIMESTAMP-NotBogus-STDERR "all timestamps match") +set(TIMESTAMP-Works-RESULT 0) +set(TIMESTAMP-Works-STDERR "~[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z~") include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") check_cmake_test(File @@ -58,6 +66,10 @@ check_cmake_test(File SHA256-Works SHA384-Works SHA512-Works + TIMESTAMP-NoFile + TIMESTAMP-BadArg1 + TIMESTAMP-NotBogus + TIMESTAMP-Works ) file(GLOB hum) diff --git a/Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake b/Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake new file mode 100644 index 000000000..2d0fcc89c --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-AllSpecifiers.cmake @@ -0,0 +1,11 @@ +string(TIMESTAMP output "%d;%H;%I;%j;%m;%M;%S;%U;%w;%y;%Y") +message("~${output}~") + +list(LENGTH output output_length) + +set(expected_output_length 11) + +if(NOT output_length EQUAL ${expected_output_length}) + message(FATAL_ERROR "expected ${expected_output_length} entries in output " + "with all specifiers; found ${output_length}") +endif() diff --git a/Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake b/Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake new file mode 100644 index 000000000..8f2d9f8b4 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-BadArg1.cmake @@ -0,0 +1 @@ +string(TIMESTAMP) diff --git a/Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake b/Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake new file mode 100644 index 000000000..c1e512684 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-BadArg2.cmake @@ -0,0 +1 @@ +string(TIMESTAMP output_variable "%Y" UTF) diff --git a/Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake b/Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake new file mode 100644 index 000000000..3d577df3f --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-BadArg3.cmake @@ -0,0 +1 @@ +string(TIMESTAMP output_variable "%Y" UTC UTC) diff --git a/Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake new file mode 100644 index 000000000..eab2a45de --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatLocal.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "%S") +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake new file mode 100644 index 000000000..eab2a45de --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-CustomFormatUTC.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "%S") +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake b/Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake new file mode 100644 index 000000000..dad6a8d97 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output UTC) +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake new file mode 100644 index 000000000..d7c7dde1c --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatLocal.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output) +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake new file mode 100644 index 000000000..dad6a8d97 --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-DefaultFormatUTC.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output UTC) +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake b/Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake new file mode 100644 index 000000000..ffc5656fa --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-IncompleteSpecifier.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "foobar%") +message("~${output}~") diff --git a/Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake b/Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake new file mode 100644 index 000000000..0e145e5ec --- /dev/null +++ b/Tests/CMakeTests/String-TIMESTAMP-UnknownSpecifier.cmake @@ -0,0 +1,2 @@ +string(TIMESTAMP output "%g") +message("~${output}~") diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in index 49e7dc90c..a9fe428e3 100644 --- a/Tests/CMakeTests/StringTest.cmake.in +++ b/Tests/CMakeTests/StringTest.cmake.in @@ -16,6 +16,26 @@ set(SHA384-Works-RESULT 0) set(SHA384-Works-STDERR "1de9560b4e030e02051ea408200ffc55d70c97ac64ebf822461a5c786f495c36df43259b14483bc8d364f0106f4971ee") set(SHA512-Works-RESULT 0) set(SHA512-Works-STDERR "3982a1b4e651768bec70ab1fb97045cb7a659f4ba7203d501c52ab2e803071f9d5fd272022df15f27727fc67f8cd022e710e29010b2a9c0b467c111e2f6abf51") +set(TIMESTAMP-BadArg1-RESULT 1) +set(TIMESTAMP-BadArg1-STDERR "string sub-command TIMESTAMP requires at least one argument") +set(TIMESTAMP-BadArg2-RESULT 1) +set(TIMESTAMP-BadArg2-STDERR "string TIMESTAMP sub-command does not recognize option UTF") +set(TIMESTAMP-BadArg3-RESULT 1) +set(TIMESTAMP-BadArg3-STDERR "string sub-command TIMESTAMP takes at most three arguments") +set(TIMESTAMP-DefaultFormatLocal-RESULT 0) +set(TIMESTAMP-DefaultFormatLocal-STDERR "~[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]~") +set(TIMESTAMP-DefaultFormatUTC-RESULT 0) +set(TIMESTAMP-DefaultFormatUTC-STDERR "~[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z~") +set(TIMESTAMP-CustomFormatLocal-RESULT 0) +set(TIMESTAMP-CustomFormatLocal-STDERR "~([0-5][0-9])|60~") +set(TIMESTAMP-CustomFormatUTC-RESULT 0) +set(TIMESTAMP-CustomFormatUTC-STDERR "~([0-5][0-9])|60~") +set(TIMESTAMP-UnknownSpecifier-RESULT 0) +set(TIMESTAMP-UnknownSpecifier-STDERR "~%g~") +set(TIMESTAMP-IncompleteSpecifier-RESULT 0) +set(TIMESTAMP-IncompleteSpecifier-STDERR "~foobar%~") +set(TIMESTAMP-AllSpecifiers-RESULT 0) +set(TIMESTAMP-AllSpecifiers-STDERR "~[0-9]+(;[0-9]+)*~") include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") check_cmake_test(String @@ -28,6 +48,16 @@ check_cmake_test(String SHA256-Works SHA384-Works SHA512-Works + TIMESTAMP-BadArg1 + TIMESTAMP-BadArg2 + TIMESTAMP-BadArg3 + TIMESTAMP-DefaultFormatLocal + TIMESTAMP-DefaultFormatUTC + TIMESTAMP-CustomFormatLocal + TIMESTAMP-CustomFormatUTC + TIMESTAMP-UnknownSpecifier + TIMESTAMP-IncompleteSpecifier + TIMESTAMP-AllSpecifiers ) # Execute each test listed in StringTestScript.cmake: From d842d9062297435747117bd74b6e184cedd345cc Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 5 Dec 2012 09:55:27 -0500 Subject: [PATCH 002/131] CMake: Stylistic changes and documentation tweaks ...for the contributed file and string TIMESTAMP sub-commands. --- Source/cmFileCommand.h | 7 +-- Source/cmStringCommand.h | 4 +- Source/cmTimestamp.cxx | 56 ++++++++++--------- .../String-TIMESTAMP-DefaulFormatUTC.cmake | 2 - 4 files changed, 36 insertions(+), 33 deletions(-) delete mode 100644 Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 5550dbe64..5973fa732 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -87,8 +87,7 @@ public: " [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" - " file(TIMESTAMP " - " [] [UTC])\n" + " file(TIMESTAMP filename variable [] [UTC])\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist. (If the file is a build input, use " @@ -203,9 +202,9 @@ public: "as status messages until the operation is complete." "\n" "TIMESTAMP will write a string representation of " - "the modification time of to .\n" + "the modification time of filename to variable.\n" "Should the command be unable to obtain a timestamp " - " will be set to the empty string \"\".\n" + "variable will be set to the empty string \"\".\n" "See documentation of the string TIMESTAMP sub-command for more details." "\n" "The file() command also provides COPY and INSTALL signatures:\n" diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 7e0694ed6..4423a90e9 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -145,9 +145,9 @@ public: " by all regular expression-related commands, including \n" " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n" "TIMESTAMP will write a string representation of " - "the current date and/or time to .\n" + "the current date and/or time to the output variable.\n" "Should the command be unable to obtain a timestamp " - " will be set to the empty string \"\".\n" + "the output variable will be set to the empty string \"\".\n" "The optional UTC flag requests the current date/time " "representation to be in Coordinated Universal Time (UTC) " "rather than local time.\n" diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index f1115e672..c3df495b7 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -21,62 +21,68 @@ std::string cmTimestamp::CurrentTime( const std::string& formatString, bool utcFlag) { time_t currentTimeT = time(0); - if(currentTimeT == time_t(-1)) return std::string(); + if(currentTimeT == time_t(-1)) + { + return std::string(); + } return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); } +//---------------------------------------------------------------------------- std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) { #ifdef _WIN32 - struct _stat info; - std::memset(&info, 0, sizeof(info)); - - if(_stat(path, &info) != 0) - return std::string(); - - time_t currentTimeT = info.st_mtime; + #define STAT _stat #else - struct stat info; - std::memset(&info, 0, sizeof(info)); - - if(stat(path, &info) != 0) - return std::string(); - - time_t currentTimeT = info.st_mtime; + #define STAT stat #endif - return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag); + struct STAT info; + std::memset(&info, 0, sizeof(info)); + + if(STAT(path, &info) != 0) + { + return std::string(); + } + + return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag); } +//---------------------------------------------------------------------------- std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, std::string formatString, bool utcFlag) { if(formatString.empty()) { formatString = "%Y-%m-%dT%H:%M:%S"; - if(utcFlag) formatString += "Z"; + if(utcFlag) + { + formatString += "Z"; + } } struct tm timeStruct; std::memset(&timeStruct, 0, sizeof(timeStruct)); + struct tm* ptr = (struct tm*) 0; if(utcFlag) { - tm* ptr = gmtime(&timeT); - if(ptr == 0) return std::string(); - - timeStruct = *ptr; + ptr = gmtime(&timeT); } else { - struct tm* ptr = localtime(&timeT); - if(ptr == 0) return std::string(); - - timeStruct = *ptr; + ptr = localtime(&timeT); } + if(ptr == 0) + { + return std::string(); + } + + timeStruct = *ptr; + std::string result; for(std::string::size_type i = 0; i < formatString.size(); ++i) { diff --git a/Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake b/Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake deleted file mode 100644 index dad6a8d97..000000000 --- a/Tests/CMakeTests/String-TIMESTAMP-DefaulFormatUTC.cmake +++ /dev/null @@ -1,2 +0,0 @@ -string(TIMESTAMP output UTC) -message("~${output}~") From f80ccac158c11b21319e6f4a82137bcc88f0dfaf Mon Sep 17 00:00:00 2001 From: Amit Kulkarni Date: Wed, 5 Dec 2012 11:36:14 -0600 Subject: [PATCH 003/131] OpenBSD: Add paths for Qt3/Qt4 Handle OpenBSD specific paths in Qt3/Qt4, allowing concurrent building and installation. Some common programs are renamed with suffixes of either 3 or 4. Also, allow qt3/qt4 installed under /usr/local to be searched and recognized appropriately. --- Modules/FindQt.cmake | 14 ++++++++++++++ Modules/FindQt3.cmake | 6 ++++-- Modules/FindQt4.cmake | 12 ++++++------ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Modules/FindQt.cmake b/Modules/FindQt.cmake index 541cc0565..54b7c6f97 100644 --- a/Modules/FindQt.cmake +++ b/Modules/FindQt.cmake @@ -43,6 +43,12 @@ if(GLOB_TEMP_VAR) endif() set(GLOB_TEMP_VAR) +file(GLOB GLOB_TEMP_VAR /usr/local/lib/qt3/bin/qmake) +if(GLOB_TEMP_VAR) + set(QT3_INSTALLED TRUE) +endif() +set(GLOB_TEMP_VAR) + # look for qt4 installations file(GLOB GLOB_TEMP_VAR /usr/local/qt-x11-commercial-4*/bin/qmake) if(GLOB_TEMP_VAR) @@ -56,6 +62,12 @@ if(GLOB_TEMP_VAR) endif() set(GLOB_TEMP_VAR) +file(GLOB GLOB_TEMP_VAR /usr/local/lib/qt4/bin/qmake) +if(GLOB_TEMP_VAR) + set(QT4_INSTALLED TRUE) +endif() +set(GLOB_TEMP_VAR) + if (Qt_FIND_VERSION) set(DESIRED_QT_VERSION "${Qt_FIND_VERSION}") endif () @@ -91,6 +103,7 @@ find_file( QT4_QGLOBAL_H_FILE qglobal.h /usr/lib/qt/include/Qt /usr/include/Qt /usr/share/qt4/include/Qt + /usr/local/include/X11/qt4/Qt C:/Progra~1/qt/include/Qt ) if(QT4_QGLOBAL_H_FILE) @@ -110,6 +123,7 @@ find_file( QT3_QGLOBAL_H_FILE qglobal.h /usr/lib/qt/include /usr/include /usr/share/qt3/include + /usr/local/include/X11/qt3 C:/Progra~1/qt/include /usr/include/qt3 ) diff --git a/Modules/FindQt3.cmake b/Modules/FindQt3.cmake index 07b6fef34..4fc8e406c 100644 --- a/Modules/FindQt3.cmake +++ b/Modules/FindQt3.cmake @@ -64,6 +64,7 @@ find_path(QT_INCLUDE_DIR qt.h /usr/share/qt3/include C:/Progra~1/qt/include /usr/include/qt3 + /usr/local/include/X11/qt3 ) # if qglobal.h is not in the qt_include_dir then set @@ -146,7 +147,7 @@ find_library(QT_QASSISTANTCLIENT_LIBRARY # Qt 3 should prefer QTDIR over the PATH find_program(QT_MOC_EXECUTABLE - NAMES moc-qt3 moc + NAMES moc-qt3 moc moc3 moc3-mt HINTS ENV QTDIR PATHS @@ -154,6 +155,7 @@ find_program(QT_MOC_EXECUTABLE "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.0;InstallDir]/include/Qt" "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.1.0;InstallDir]/include/Qt" ${GLOB_PATHS_BIN} + /usr/local/lib/qt3 /usr/local/qt /usr/lib/qt /usr/lib/qt3 @@ -170,7 +172,7 @@ endif() # Qt 3 should prefer QTDIR over the PATH find_program(QT_UIC_EXECUTABLE - NAMES uic-qt3 uic + NAMES uic-qt3 uic uic3 uic3-mt HINTS ENV QTDIR PATHS diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index b42247a1c..013461b85 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -982,13 +982,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) endif() find_program(QT_MOC_EXECUTABLE - NAMES moc-qt4 moc + NAMES moc-qt4 moc moc4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) find_program(QT_UIC_EXECUTABLE - NAMES uic-qt4 uic + NAMES uic-qt4 uic uic4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) @@ -1018,13 +1018,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ) find_program(QT_LUPDATE_EXECUTABLE - NAMES lupdate-qt4 lupdate + NAMES lupdate-qt4 lupdate lupdate4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) find_program(QT_LRELEASE_EXECUTABLE - NAMES lrelease-qt4 lrelease + NAMES lrelease-qt4 lrelease lrelease4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) @@ -1036,13 +1036,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ) find_program(QT_DESIGNER_EXECUTABLE - NAMES designer-qt4 designer + NAMES designer-qt4 designer designer4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) find_program(QT_LINGUIST_EXECUTABLE - NAMES linguist-qt4 linguist + NAMES linguist-qt4 linguist linguist4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) From 354ecc1e1f28b9f2412fa015064353c6e20cfe92 Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 5 Dec 2012 13:14:56 -0500 Subject: [PATCH 004/131] CMake: Fix dashboard warnings ...in the new file and string TIMESTAMP sub-commands --- Source/cmFileCommand.cxx | 2 +- Source/cmStringCommand.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 42df3a17f..0cdbb82d7 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3263,7 +3263,7 @@ bool cmFileCommand::HandleTimestampCommand( return false; } - int argsIndex = 1; + unsigned int argsIndex = 1; const std::string& filename = args[argsIndex++]; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index c402738fe..e49edd878 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -901,7 +901,7 @@ bool cmStringCommand return false; } - int argsIndex = 1; + unsigned int argsIndex = 1; const std::string &outputVariable = args[argsIndex++]; From e28ce2483dbdc620aa92e2ba0d86e8923dcdb296 Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 5 Dec 2012 15:16:22 -0500 Subject: [PATCH 005/131] CMake: Fix dashboard test failure Eliminate the platform difference in calling stat. We call stat normally in other places in the CMake code base just fine. Works everywhere we work. Will hopefully also fix the Borland Continuous dashboard failure that is occurring with respect to correctly measuring the modification time of a freshly generated file. --- Source/cmTimestamp.cxx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index c3df495b7..22bb4b789 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -33,16 +33,10 @@ std::string cmTimestamp::CurrentTime( std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) { -#ifdef _WIN32 - #define STAT _stat -#else - #define STAT stat -#endif - - struct STAT info; + struct stat info; std::memset(&info, 0, sizeof(info)); - if(STAT(path, &info) != 0) + if(stat(path, &info) != 0) { return std::string(); } From 12d87c04253bd203a9b8a510b1772291527d441c Mon Sep 17 00:00:00 2001 From: David Cole Date: Thu, 6 Dec 2012 07:20:12 -0500 Subject: [PATCH 006/131] CMake: Fix dashboard build errors and warnings memset is not in std:: for VS6, and though quite silly, 0 is not a char --- Source/cmTimestamp.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 22bb4b789..ac26503c6 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -34,7 +34,7 @@ std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) { struct stat info; - std::memset(&info, 0, sizeof(info)); + memset(&info, 0, sizeof(info)); if(stat(path, &info) != 0) { @@ -58,7 +58,7 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, } struct tm timeStruct; - std::memset(&timeStruct, 0, sizeof(timeStruct)); + memset(&timeStruct, 0, sizeof(timeStruct)); struct tm* ptr = (struct tm*) 0; if(utcFlag) @@ -82,7 +82,7 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT, { char c1 = formatString[i]; char c2 = (i+1 < formatString.size()) ? - formatString[i+1] : 0; + formatString[i+1] : static_cast(0); if(c1 == '%' && c2 != 0) { From 8039bd0864aae15fd0d95db728159a85d72bf0f4 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Thu, 6 Dec 2012 22:24:43 +0100 Subject: [PATCH 007/131] CONFIGURE_PACKAGE_CONFIG_FILE(): improve generated comments CONFIGURE_PACKAGE_CONFIG_FILE() now additionally generates "Any changes to this file will be overwritten by the next CMake run The input file was FooConfig.cmake.in" into the configured file. Alex --- Modules/CMakePackageConfigHelpers.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index 96ecb4270..a92ce7cc9 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -188,8 +188,13 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile) endif() endforeach() + get_filename_component(inputFileName "${_inputFile}" NAME) + set(PACKAGE_INIT " ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was ${inputFileName} ######## + get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE) ") From 711b63f7e095992d6ab84063af076d23a916b1f3 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Dec 2012 09:59:18 -0500 Subject: [PATCH 008/131] Add policy CMP0019 to skip include/link variable re-expansion Historically CMake has always expanded ${} variable references in the values given to include_directories(), link_directories(), and link_libraries(). This has been unnecessary since general ${} evaluation syntax was added to the language a LONG time ago, but has remained for compatibility with VERY early CMake versions. For a long time the re-expansion was a lightweight operation because it was only processed once at the directory level and the fast-path of cmMakefile::ExpandVariablesInString was usually taken because values did not have any '$' in them. Then commit d899eb71 (Call ExpandVariablesInString for each target's INCLUDE_DIRECTORIES, 2012-02-22) made the operation a bit heavier because the expansion is now needed on a per-target basis. In the future we will support generator expressions in INCLUDE_DIRECTORIES with $<> syntax, so the fast-path in cmMakefile::ExpandVariablesInString will no longer be taken and re-expansion will be very expensive. Add policy CMP0019 to skip the re-expansion altogether in NEW behavior. In OLD behavior perform the expansion but improve the fast-path heuristic to match ${} but not $<>. If the policy is not set then warn if expansion actually does anything. We expect this to be encountered very rarely in practice. --- Source/cmMakefile.cxx | 77 +++++++++++++++---- Source/cmMakefile.h | 2 +- Source/cmPolicies.cxx | 17 ++++ Source/cmPolicies.h | 1 + Tests/RunCMake/CMP0019/CMP0019-NEW.cmake | 2 + Tests/RunCMake/CMP0019/CMP0019-OLD.cmake | 2 + .../RunCMake/CMP0019/CMP0019-WARN-stderr.txt | 40 ++++++++++ Tests/RunCMake/CMP0019/CMP0019-WARN.cmake | 1 + Tests/RunCMake/CMP0019/CMP0019-code.cmake | 9 +++ Tests/RunCMake/CMP0019/CMakeLists.txt | 3 + Tests/RunCMake/CMP0019/RunCMakeTest.cmake | 5 ++ Tests/RunCMake/CMakeLists.txt | 1 + 12 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 Tests/RunCMake/CMP0019/CMP0019-NEW.cmake create mode 100644 Tests/RunCMake/CMP0019/CMP0019-OLD.cmake create mode 100644 Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0019/CMP0019-WARN.cmake create mode 100644 Tests/RunCMake/CMP0019/CMP0019-code.cmake create mode 100644 Tests/RunCMake/CMP0019/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0019/RunCMakeTest.cmake diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8498d72fd..d943c450f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -814,7 +814,7 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major, void cmMakefile::FinalPass() { // do all the variable expansions here - this->ExpandVariables(); + this->ExpandVariablesCMP0019(); // give all the commands a chance to do something // after the file has been parsed before generation @@ -2122,21 +2122,33 @@ void cmMakefile::AddExtraDirectory(const char* dir) this->AuxSourceDirectories.push_back(dir); } - -// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the -// include and library directories. - -void cmMakefile::ExpandVariables() +static bool mightExpandVariablesCMP0019(const char* s) { - // Now expand variables in the include and link strings + return s && *s && strstr(s,"${") && strchr(s,'}'); +} + +void cmMakefile::ExpandVariablesCMP0019() +{ + // Drop this ancient compatibility behavior with a policy. + cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019); + if(pol != cmPolicies::OLD && pol != cmPolicies::WARN) + { + return; + } + cmOStringStream w; - // May not be necessary anymore... But may need a policy for strict - // backwards compatibility const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); - if (includeDirs) + if(mightExpandVariablesCMP0019(includeDirs)) { std::string dirs = includeDirs; this->ExpandVariablesInString(dirs, true, true); + if(pol == cmPolicies::WARN && dirs != includeDirs) + { + w << "Evaluated directory INCLUDE_DIRECTORIES\n" + << " " << includeDirs << "\n" + << "as\n" + << " " << dirs << "\n"; + } this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); } @@ -2146,10 +2158,17 @@ void cmMakefile::ExpandVariables() { cmTarget &t = l->second; includeDirs = t.GetProperty("INCLUDE_DIRECTORIES"); - if (includeDirs) + if(mightExpandVariablesCMP0019(includeDirs)) { std::string dirs = includeDirs; this->ExpandVariablesInString(dirs, true, true); + if(pol == cmPolicies::WARN && dirs != includeDirs) + { + w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n" + << " " << includeDirs << "\n" + << "as\n" + << " " << dirs << "\n"; + } t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); } } @@ -2157,13 +2176,45 @@ void cmMakefile::ExpandVariables() for(std::vector::iterator d = this->LinkDirectories.begin(); d != this->LinkDirectories.end(); ++d) { - this->ExpandVariablesInString(*d, true, true); + if(mightExpandVariablesCMP0019(d->c_str())) + { + std::string orig = *d; + this->ExpandVariablesInString(*d, true, true); + if(pol == cmPolicies::WARN && *d != orig) + { + w << "Evaluated link directory\n" + << " " << orig << "\n" + << "as\n" + << " " << *d << "\n"; + } + } } for(cmTarget::LinkLibraryVectorType::iterator l = this->LinkLibraries.begin(); l != this->LinkLibraries.end(); ++l) { - this->ExpandVariablesInString(l->first, true, true); + if(mightExpandVariablesCMP0019(l->first.c_str())) + { + std::string orig = l->first; + this->ExpandVariablesInString(l->first, true, true); + if(pol == cmPolicies::WARN && l->first != orig) + { + w << "Evaluated link library\n" + << " " << orig << "\n" + << "as\n" + << " " << l->first << "\n"; + } + } + } + + if(!w.str().empty()) + { + cmOStringStream m; + m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019) + << "\n" + << "The following variable evaluations were encountered:\n" + << w.str(); + this->IssueMessage(cmake::AUTHOR_WARNING, m.str()); } } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 70cfe5421..eff05d091 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -693,7 +693,7 @@ public: /** * Expand variables in the makefiles ivars such as link directories etc */ - void ExpandVariables(); + void ExpandVariablesCMP0019(); /** * Replace variables and #cmakedefine lines in the given string. diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 6aef50243..eb7d6668e 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -491,6 +491,23 @@ cmPolicies::cmPolicies() "CMAKE_SHARED_LIBRARY__FLAGS whether it is modified or not and " "honor the POSITION_INDEPENDENT_CODE target property.", 2,8,9,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0019, "CMP0019", + "Do not re-expand variables in include and link information.", + "CMake 2.8.10 and lower re-evaluated values given to the " + "include_directories, link_directories, and link_libraries " + "commands to expand any leftover variable references at the " + "end of the configuration step. " + "This was for strict compatibility with VERY early CMake versions " + "because all variable references are now normally evaluated during " + "CMake language processing. " + "CMake 2.8.11 and higher prefer to skip the extra evaluation." + "\n" + "The OLD behavior for this policy is to re-evaluate the values " + "for strict compatibility. " + "The NEW behavior for this policy is to leave the values untouched.", + 2,8,11,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 6932565ab..d7d945c42 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -68,6 +68,7 @@ public: CMP0018, ///< Ignore language flags for shared libs, and adhere to /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C} /// instead. + CMP0019, ///< No variable re-expansion in include and link info /** \brief Always the last entry. * diff --git a/Tests/RunCMake/CMP0019/CMP0019-NEW.cmake b/Tests/RunCMake/CMP0019/CMP0019-NEW.cmake new file mode 100644 index 000000000..3091e66ac --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0019 NEW) +include(CMP0019-code.cmake) diff --git a/Tests/RunCMake/CMP0019/CMP0019-OLD.cmake b/Tests/RunCMake/CMP0019/CMP0019-OLD.cmake new file mode 100644 index 000000000..0f02f9ce5 --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0019 OLD) +include(CMP0019-code.cmake) diff --git a/Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt b/Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt new file mode 100644 index 000000000..03faef90e --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-WARN-stderr.txt @@ -0,0 +1,40 @@ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0019 is not set: Do not re-expand variables in include and link + information. Run "cmake --help-policy CMP0019" for policy details. Use + the cmake_policy command to set the policy and suppress this warning. + + The following variable evaluations were encountered: + + Evaluated directory INCLUDE_DIRECTORIES + + /usr/include/\${VAR_INCLUDE};/usr/include/normal + + as + + /usr/include/VAL_INCLUDE;/usr/include/normal + + Evaluated target some_target INCLUDE_DIRECTORIES + + /usr/include/\${VAR_INCLUDE};/usr/include/normal + + as + + /usr/include/VAL_INCLUDE;/usr/include/normal + + Evaluated link directory + + /usr/lib/\${VAR_LINK_DIRS} + + as + + /usr/lib/VAL_LINK_DIRS + + Evaluated link library + + \${VAR_LINK_LIBS} + + as + + VAL_LINK_LIBS + +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMP0019/CMP0019-WARN.cmake b/Tests/RunCMake/CMP0019/CMP0019-WARN.cmake new file mode 100644 index 000000000..a419f309e --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-WARN.cmake @@ -0,0 +1 @@ +include(CMP0019-code.cmake) diff --git a/Tests/RunCMake/CMP0019/CMP0019-code.cmake b/Tests/RunCMake/CMP0019/CMP0019-code.cmake new file mode 100644 index 000000000..26c0e5b27 --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-code.cmake @@ -0,0 +1,9 @@ +set(VAR_INCLUDE "VAL_INCLUDE") +set(VAR_LINK_DIRS "VAL_LINK_DIRS") +set(VAR_LINK_LIBS "VAL_LINK_LIBS") +add_custom_target(some_target) +include_directories("/usr/include/\${VAR_INCLUDE}" /usr/include/normal) +link_directories("/usr/lib/\${VAR_LINK_DIRS}" /usr/lib/normal) +link_libraries("\${VAR_LINK_LIBS}" normal) +add_custom_target(other_target) +set_property(TARGET other_target PROPERTY INCLUDE_DIRECTORIES "") diff --git a/Tests/RunCMake/CMP0019/CMakeLists.txt b/Tests/RunCMake/CMP0019/CMakeLists.txt new file mode 100644 index 000000000..e8db6b05b --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0019/RunCMakeTest.cmake b/Tests/RunCMake/CMP0019/RunCMakeTest.cmake new file mode 100644 index 000000000..119fc2b30 --- /dev/null +++ b/Tests/RunCMake/CMP0019/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0019-WARN) +run_cmake(CMP0019-OLD) +run_cmake(CMP0019-NEW) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 722d9c388..cc544a373 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -45,6 +45,7 @@ macro(add_RunCMake_test test) ) endmacro() +add_RunCMake_test(CMP0019) add_RunCMake_test(GeneratorExpression) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) From 2bc22bdaacfc0f0f91c229685dc5dbadd0267601 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 7 Dec 2012 13:06:20 -0500 Subject: [PATCH 009/131] Xcode: Add frameworks search paths from link dependeny closure (#13397) The Xcode generator produces FRAMEWORK_SEARCH_PATHS from: (1) Include directories of the form /path/to/Foo.framework become -F/path/to so '#include ' can find H in the framework. (2) Linked frameworks of the form /path/to/Foo.framework become -F/path/to -framework Foo so the linker can find the framework. Originally commit 82bb6fae (add framework support to FIND_FILE, 2005-12-27) added these and used the (then current) old-style link dependency analysis results to get the frameworks. Later a second setting was added by commit 2ed6191f (add initial xcode framework stuff, 2007-05-08) to transform -F/path/to linker options produced by the old link line generation into entries appended to FRAMEWORK_SEARCH_PATHS. Then commit 96fd5909 (Implement linking with paths to library files, 2008-01-22) updated the second setting to directly use the results of full modern link dependency analysis, but forgot to remove the use of old-style link results from the original setting location. The two settings worked together for a while, with the second one appending to the first. Then commit f33a27ab (Generate native Xcode 3.0 and 3.1 projects, 2009-06-29) changed the internal representation format produced by the first setting but did not update the second setting to append to the new representation. As a result, if the first setting added any paths (usually via the old-style link analysis) then the second setting containing the modern link analysis results would not be applied at all. Fix this by removing use of the old-style link analysis results. Replace it using the modern link dependencies and remove the second setting altogether. Now all values for FRAMEWORK_SEARCH_PATHS are collected in one place so no special append logic is needed. --- Source/cmGlobalXCodeGenerator.cxx | 36 ++++++++++--------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 9bbeeaf6f..b2d325c8a 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1997,15 +1997,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, dirs.Add(incpath.c_str()); } } - std::vector& frameworks = target.GetFrameworks(); - if(frameworks.size()) + if(target.GetType() != cmTarget::OBJECT_LIBRARY && + target.GetType() != cmTarget::STATIC_LIBRARY) { - for(std::vector::iterator fmIt = frameworks.begin(); - fmIt != frameworks.end(); ++fmIt) + // Add framework search paths needed for linking. + if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName)) { - if(emitted.insert(*fmIt).second) + std::vector const& fwDirs = cli->GetFrameworkPaths(); + for(std::vector::const_iterator fdi = fwDirs.begin(); + fdi != fwDirs.end(); ++fdi) { - fdirs.Add(this->XCodeEscapePath(fmIt->c_str()).c_str()); + if(emitted.insert(*fdi).second) + { + fdirs.Add(this->XCodeEscapePath(fdi->c_str()).c_str()); + } } } } @@ -2691,25 +2696,6 @@ void cmGlobalXCodeGenerator linkDirs.c_str(), configName); } - // add the framework search paths - { - const char* sep = ""; - std::string fdirs; - std::vector const& fwDirs = cli.GetFrameworkPaths(); - for(std::vector::const_iterator fdi = fwDirs.begin(); - fdi != fwDirs.end(); ++fdi) - { - fdirs += sep; - sep = " "; - fdirs += this->XCodeEscapePath(fdi->c_str()); - } - if(!fdirs.empty()) - { - this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", - fdirs.c_str(), configName); - } - } - // now add the link libraries { std::string linkLibs; From acc224005e99076da3561ada8c06985487b0ce11 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Fri, 7 Dec 2012 21:24:28 +0100 Subject: [PATCH 010/131] Automoc: get include dirs without stripping implicit include dirs off This should finally fix #13667 and #13762. Instead of adding special handling to guess whether implicit include dirs may have been removed, simply make it possible to query the include dirs without removing the implicit ones. Alex --- Source/cmLocalGenerator.cxx | 27 +++++++++------- Source/cmLocalGenerator.h | 3 +- Source/cmQtAutomoc.cxx | 62 ++----------------------------------- 3 files changed, 21 insertions(+), 71 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 6d396b340..b41f06010 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1329,7 +1329,9 @@ std::string cmLocalGenerator::GetIncludeFlags( void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, cmGeneratorTarget* target, const char* lang, - const char *config) + const char *config, + bool stripImplicitInclDirs + ) { // Need to decide whether to automatically include the source and // binary directories at the beginning of the include path. @@ -1404,18 +1406,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, return; } - // Load implicit include directories for this language. - std::string impDirVar = "CMAKE_"; - impDirVar += lang; - impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES"; - if(const char* value = this->Makefile->GetDefinition(impDirVar.c_str())) + if (stripImplicitInclDirs) { - std::vector impDirVec; - cmSystemTools::ExpandListArgument(value, impDirVec); - for(std::vector::const_iterator i = impDirVec.begin(); - i != impDirVec.end(); ++i) + // Load implicit include directories for this language. + std::string impDirVar = "CMAKE_"; + impDirVar += lang; + impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES"; + if(const char* value = this->Makefile->GetDefinition(impDirVar.c_str())) { - emitted.insert(*i); + std::vector impDirVec; + cmSystemTools::ExpandListArgument(value, impDirVec); + for(std::vector::const_iterator i = impDirVec.begin(); + i != impDirVec.end(); ++i) + { + emitted.insert(*i); + } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index bd582181c..63559d750 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -212,7 +212,8 @@ public: /** Get the include flags for the current makefile and language. */ void GetIncludeDirectories(std::vector& dirs, cmGeneratorTarget* target, - const char* lang = "C", const char *config = 0); + const char* lang = "C", const char *config = 0, + bool stripImplicitInclDirs = true); /** Compute the language used to compile the given source file. */ const char* GetSourceFileLanguage(const cmSourceFile& source); diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index 83688dd75..bf034cf44 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -212,36 +212,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) } - const char* qtIncDir = 0; - const char* qtCoreIncDir = 0; - - // check whether ${QT_INCLUDE_DIR} is part of the implicit include dirs, - // see http://public.kitware.com/Bug/view.php?id=13667 - bool qtIncludeDirMayHaveBeenRemoved = false; - if (makefile->IsSet("QT_INCLUDE_DIR")) - { - qtIncDir = makefile->GetDefinition("QT_INCLUDE_DIR"); - std::string s = - makefile->GetSafeDefinition("CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES"); - std::vector implIncDirs; - cmSystemTools::ExpandListArgument(s, implIncDirs); - if (std::find(implIncDirs.begin(), implIncDirs.end(),std::string(qtIncDir)) - != implIncDirs.end()) - { - qtIncludeDirMayHaveBeenRemoved = true; - if (makefile->IsSet("QT_QTCORE_INCLUDE_DIR")) - { - qtCoreIncDir = makefile->GetDefinition("QT_QTCORE_INCLUDE_DIR"); - } - } - } - - bool haveQtCoreIncDir = false; - bool haveQtIncDir = false; - std::vector includeDirs; cmGeneratorTarget gtgt(target); - localGen->GetIncludeDirectories(includeDirs, >gt, "CXX"); + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 + localGen->GetIncludeDirectories(includeDirs, >gt, "CXX", 0, false); std::string _moc_incs = ""; const char* sep = ""; for(std::vector::const_iterator incDirIt = includeDirs.begin(); @@ -251,37 +226,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) _moc_incs += sep; sep = ";"; _moc_incs += *incDirIt; - - if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir) // #13667 - { - if (*incDirIt == qtIncDir) - { - haveQtIncDir = true; - qtIncludeDirMayHaveBeenRemoved = false; // it's here, i.e. not removed - } - if (*incDirIt == qtCoreIncDir) - { - haveQtCoreIncDir = true; - } - } - } - - // Some projects (kdelibs, phonon) query the compiler for its default - // include search dirs, and add those to - // CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES. - // These may include e.g./usr/lib/qt/include . This is typically also part - // of ${QT_INCLUDES}. If this directory is then contained in the implicit - // include dirs, it is removed from the include dirs returned from the - // target above. So we add ${QT_INCLUDE_DIR} manually for moc if we detected - // that ${QT_QTCORE_INCLUDE_DIR} is among the include dirs (there shouldn't - // be a way to use Qt4 without using ${QT_QTCORE_INCLUDE_DIR} I think. - // See #13646 and #13667. - if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir - && (haveQtCoreIncDir == true) && (haveQtIncDir == false)) - { - _moc_incs += sep; - sep = ";"; - _moc_incs += qtIncDir; } const char* tmp = target->GetProperty("COMPILE_DEFINITIONS"); From f0d938549eead63fb86bec28c299a1bceacbdd6b Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 7 Dec 2012 13:27:52 -0500 Subject: [PATCH 011/131] Makefile: Use modern link information for framework search paths Use cmComputeLinkInformation::GetFrameworkPaths to get the list of framework paths needed by the linker. Drop the now unused framework information from the old-style cmTarget link dependency analysis. --- Source/cmMakefileTargetGenerator.cxx | 26 +++++++++++++++----------- Source/cmTarget.cxx | 21 --------------------- Source/cmTarget.h | 5 ----- 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 2b89c794b..9bf6b7d9e 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1550,10 +1550,10 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags() this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, "C", config); - std::vector::iterator i; // check all include directories for frameworks as this // will already have added a -F for the framework - for(i = includes.begin(); i != includes.end(); ++i) + for(std::vector::iterator i = includes.begin(); + i != includes.end(); ++i) { if(this->Target->NameResolvesToFramework(i->c_str())) { @@ -1565,17 +1565,21 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags() } std::string flags; - std::vector& frameworks = this->Target->GetFrameworks(); - for(i = frameworks.begin(); - i != frameworks.end(); ++i) + const char* cfg = this->LocalGenerator->ConfigurationName.c_str(); + if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) { - if(emitted.insert(*i).second) + std::vector const& frameworks = cli->GetFrameworkPaths(); + for(std::vector::const_iterator i = frameworks.begin(); + i != frameworks.end(); ++i) { - flags += "-F"; - flags += this->Convert(i->c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL, true); - flags += " "; + if(emitted.insert(*i).second) + { + flags += "-F"; + flags += this->Convert(i->c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL, true); + flags += " "; + } } } return flags; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index be20464da..de3b23c78 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2092,26 +2092,6 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) NameResolvesToFramework(libname); } -//---------------------------------------------------------------------------- -bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType) -{ - if(this->NameResolvesToFramework(libname.c_str())) - { - std::string frameworkDir = libname; - frameworkDir += "/../"; - frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str()); - std::vector::iterator i = - std::find(this->Frameworks.begin(), - this->Frameworks.end(), frameworkDir); - if(i == this->Frameworks.end()) - { - this->Frameworks.push_back(frameworkDir); - } - return true; - } - return false; -} - //---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, @@ -2122,7 +2102,6 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, { return; } - this->AddFramework(lib, llt); cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 9efd638f8..0dfbc68a1 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -109,9 +109,6 @@ public: std::vector &GetPostBuildCommands() {return this->PostBuildCommands;} - ///! Return the list of frameworks being linked to this target - std::vector &GetFrameworks() {return this->Frameworks;} - /** * Get the list of the source files used by this target */ @@ -179,7 +176,6 @@ public: // Check to see if a library is a framework and treat it different on Mac bool NameResolvesToFramework(const std::string& libname); - bool AddFramework(const std::string& lib, LinkLibraryType llt); void AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt); @@ -569,7 +565,6 @@ private: LinkLibraryVectorType LinkLibraries; LinkLibraryVectorType PrevLinkedLibraries; bool LinkLibrariesAnalyzed; - std::vector Frameworks; std::vector LinkDirectories; std::set LinkDirectoriesEmmitted; bool HaveInstallRule; From 61ace1df2616e472d056b302e4269cbf112fb020 Mon Sep 17 00:00:00 2001 From: David Cole Date: Mon, 10 Dec 2012 17:03:57 -0500 Subject: [PATCH 012/131] CTest: Coverage handler: expect certain output lines from gcov 4.7 (#13657) And do not report them as errors. --- Source/CTest/cmCTestCoverageHandler.cxx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 4d1e249e6..20aded2b5 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -1097,10 +1097,17 @@ int cmCTestCoverageHandler::HandleGCovCoverage( } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Unknown gcov output line: [" << line->c_str() << "]" << std::endl); - cont->Error ++; - //abort(); + // gcov 4.7 can have output lines saying "No executable lines" and + // "Removing 'filename.gcov'"... Don't log those as "errors." + if(*line != "No executable lines" && + !cmSystemTools::StringStartsWith(line->c_str(), "Removing ")) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Unknown gcov output line: [" << line->c_str() << "]" + << std::endl); + cont->Error ++; + //abort(); + } } From ab2b1f44f88dd82129bcfe7f96007c30e1e07d08 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 11 Dec 2012 00:01:14 -0500 Subject: [PATCH 013/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 18c483557..20e68e91e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121210) +set(CMake_VERSION_TWEAK 20121211) #set(CMake_VERSION_RC 1) From 017d90c50099540b2bc71b63d646271aa0968d36 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 Dec 2012 14:00:23 -0500 Subject: [PATCH 014/131] Documentation: Clarify handling of implicit link directories Extend documentation for CMAKE__IMPLICIT_LINK_DIRECTORIES to explain how it is used by CMake and how it can be influenced by environment variables. Inspired-by: Alex Neundorf --- Source/cmDocumentVariables.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 55d70f862..32c543dce 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1621,7 +1621,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "These paths are implicit linker search directories for the compiler's " "language. " "CMake automatically detects these directories for each language and " - "reports the results in this variable.", false, + "reports the results in this variable." + "\n" + "When a library in one of these directories is given by full path to " + "target_link_libraries() CMake will generate the -l form on " + "link lines to ensure the linker searches its implicit directories " + "for the library. " + "Note that some toolchains read implicit directories from an " + "environment variable such as LIBRARY_PATH so keep its value " + "consistent when operating in a given build tree.",false, "Variables for Languages"); cm->DefineProperty From ba58d0c06fd8576844a5722930531a95d00c2003 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 Dec 2012 15:11:40 -0500 Subject: [PATCH 015/131] OS X: Link with all framework search paths, not just the last Refactoring in commit 8d674e78 (Ninja: move -LIBPATH behind -link option, 2012-09-26) accidentally added code that overwrites the framework search path flags on each iteration instead of appending. Change '=' to '+=' to fix it. This affects Makefile and Ninja generators. --- Source/cmLocalGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index b41f06010..b557ca19b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1708,7 +1708,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, for(std::vector::const_iterator fdi = fwDirs.begin(); fdi != fwDirs.end(); ++fdi) { - frameworkPath = " -F"; + frameworkPath += "-F"; frameworkPath += this->Convert(fdi->c_str(), NONE, SHELL, false); frameworkPath += " "; } From 2dd67c7ea095957d557d2934a67baacdf8a82d7b Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 5 Dec 2012 11:49:13 -0500 Subject: [PATCH 016/131] OS X: Detect implicit link directories on modern toolchains We detect the implicit link directories for the toolchain by adding a flag to get verbose output from the compiler front-end while linking the ABI detection binary. Newer OS X toolchains based on Clang do not add the implicit link directories with -L options to their internal invocation of "ld". Instead they use a linker that comes with the toolchain and is already configured with the proper directories. Add the "-Wl,-v" option to ask "ld" to print its implicit directories. It displays them in a block such as: Library search paths: /... Parse this block to extract the implicit link directories. While at it, remove the checks introduced by commit efaf335b (Skip implicit link information on Xcode, 2009-07-23) and commit 5195a664 (Skip implicit link info for multiple OS X archs, 2009-09-22). Discard the non-system link directories added by Xcode. Discard all detected implicit libraries in the multi-architecture case but keep the directories. The directories are still useful without the libraries just to suppress addition of explicit -L options for them. --- Modules/CMakeDetermineCompilerABI.cmake | 21 ++-- Modules/CMakeParseImplicitLinkInfo.cmake | 29 +++++- Modules/Platform/Darwin-Clang.cmake | 1 + Modules/Platform/Darwin-GNU.cmake | 1 + .../CMakeTests/ImplicitLinkInfoTest.cmake.in | 97 +++++++++++++++++++ 5 files changed, 134 insertions(+), 15 deletions(-) diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 75247d955..cb94aa655 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -72,18 +72,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # Parse implicit linker information for this language, if available. set(implicit_dirs "") set(implicit_libs "") - set(MULTI_ARCH FALSE) - if(DEFINED CMAKE_OSX_ARCHITECTURES) - if( "${CMAKE_OSX_ARCHITECTURES}" MATCHES ";" ) - set(MULTI_ARCH TRUE) - endif() - endif() - if(CMAKE_${lang}_VERBOSE_FLAG - # Implicit link information cannot be used explicitly for - # multiple OS X architectures, so we skip it. - AND NOT MULTI_ARCH - # Skip this with Xcode for now. - AND NOT "${CMAKE_GENERATOR}" MATCHES Xcode) + if(CMAKE_${lang}_VERBOSE_FLAG) CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -112,6 +101,14 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) message(STATUS "${_desc}") endif() + # Implicit link libraries cannot be used explicitly for multiple + # OS X architectures, so we skip it. + if(DEFINED CMAKE_OSX_ARCHITECTURES) + if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";") + set(implicit_libs "") + endif() + endif() + set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE) set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE) diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index ecb20dc6b..54e812748 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -36,6 +36,16 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) set(cmd) if("${line}" MATCHES "${linker_regex}" AND NOT "${line}" MATCHES "${linker_exclude_regex}") + if(XCODE) + # Xcode unconditionally adds a path under the project build tree and + # on older versions it is not reported with proper quotes. Remove it. + string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" _dir_regex "${CMAKE_BINARY_DIR}") + string(REGEX REPLACE " -[FL]${_dir_regex}/([^ ]| [^-])+( |$)" " " xline "${line}") + if(NOT "x${xline}" STREQUAL "x${line}") + set(log "${log} reduced line: [${line}]\n to: [${xline}]\n") + set(line "${xline}") + endif() + endif() if(UNIX) separate_arguments(args UNIX_COMMAND "${line}") else() @@ -97,6 +107,13 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) endif() endforeach() + # Look for library search paths reported by linker. + if("${output_lines}" MATCHES ";Library search paths:((;\t[^;]+)+)") + string(REPLACE ";\t" ";" implicit_dirs_match "${CMAKE_MATCH_1}") + set(log "${log} Library search paths: [${implicit_dirs_match}]\n") + list(APPEND implicit_dirs_tmp ${implicit_dirs_match}) + endif() + # Cleanup list of libraries and flags. # We remove items that are not language-specific. set(implicit_libs "") @@ -108,12 +125,18 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) endif() endforeach() - # Cleanup list of directories. + # Cleanup list of library directories. set(implicit_dirs "") foreach(d IN LISTS implicit_dirs_tmp) get_filename_component(dir "${d}" ABSOLUTE) - list(APPEND implicit_dirs "${dir}") - set(log "${log} collapse dir [${d}] ==> [${dir}]\n") + string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos) + if(NOT pos LESS 0) + set(msg ", skipping non-system directory") + else() + set(msg "") + list(APPEND implicit_dirs "${dir}") + endif() + set(log "${log} collapse library dir [${d}] ==> [${dir}]${msg}\n") endforeach() list(REMOVE_DUPLICATES implicit_dirs) diff --git a/Modules/Platform/Darwin-Clang.cmake b/Modules/Platform/Darwin-Clang.cmake index de7a85636..528873cfd 100644 --- a/Modules/Platform/Darwin-Clang.cmake +++ b/Modules/Platform/Darwin-Clang.cmake @@ -19,6 +19,7 @@ endif() set(__DARWIN_COMPILER_CLANG 1) macro(__darwin_compiler_clang lang) + set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names") set(CMAKE_${lang}_SYSROOT_FLAG "-isysroot") diff --git a/Modules/Platform/Darwin-GNU.cmake b/Modules/Platform/Darwin-GNU.cmake index d9535039f..5fee7e3ae 100644 --- a/Modules/Platform/Darwin-GNU.cmake +++ b/Modules/Platform/Darwin-GNU.cmake @@ -19,6 +19,7 @@ endif() set(__DARWIN_COMPILER_GNU 1) macro(__darwin_compiler_gnu lang) + set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output # GNU does not have -shared on OS X set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names") diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index dbe95005e..02963042c 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -102,30 +102,127 @@ list(APPEND platforms linux64_test1) #----------------------------------------------------------------------------- # Mac +# gcc -arch i686 dummy.c -v -Wl,-v +set(mac_i686_gcc_Wlv_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (i686 Darwin) +/usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccSiuUhD.o -v -lSystem -lgcc -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_i686_gcc_Wlv_libs "") +set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +list(APPEND platforms mac_i686_gcc_Wlv) + # gcc -arch i686 dummy.c -v set(mac_i686_gcc_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem") set(mac_i686_gcc_libs "") set(mac_i686_gcc_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_gcc) +# g++ -arch i686 dummy.cxx -v -Wl,-v +set(mac_i686_g++_Wlv_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (i686 Darwin) +/usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccWrBoVl.o -v -lstdc++ -lSystem -lgcc -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/gcc/i686-apple-darwin10/4.2.1 + /usr/lib/i686-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_i686_g++_Wlv_libs "stdc++") +set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +list(APPEND platforms mac_i686_g++_Wlv) + # g++ -arch i686 dummy.cxx -v set(mac_i686_g++_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem") set(mac_i686_g++_libs "stdc++") set(mac_i686_g++_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_g++) +# gfortran dummy.f -v -Wl,-v +set(mac_i686_gfortran_Wlv_text " /usr/local/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//cc9zXNax.o -v -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem +collect2 version 4.4.1 20090623 (prerelease) (i686 Darwin) +/usr/bin/ld -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//cc9zXNax.o -v -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 + /usr/local/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran") +set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib") +list(APPEND platforms mac_i686_gfortran_Wlv) + # gfortran dummy.f -v set(mac_i686_gfortran_text " /usr/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/lib/gcc -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//ccgqbX5P.o -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem") set(mac_i686_gfortran_libs "gfortranbegin;gfortran") set(mac_i686_gfortran_dirs "/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/lib/gcc;/usr/lib") list(APPEND platforms mac_i686_gfortran) +# gcc -arch ppc dummy.c -v -Wl,-v +set(mac_ppc_gcc_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//cclziQY4.o -v -lgcc -lSystemStubs -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (Darwin/PowerPC) +/usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/ld -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//cclziQY4.o -v -lgcc -lSystemStubs -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_ppc_gcc_Wlv_libs "") +set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +list(APPEND platforms mac_ppc_gcc_Wlv) + # gcc -arch ppc dummy.c -v set(mac_ppc_gcc_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccdcolsP.o -lgcc -lSystemStubs -lSystem") set(mac_ppc_gcc_libs "") set(mac_ppc_gcc_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_ppc_gcc) +# g++ -arch ppc dummy.cxx -v -Wl,-v +set(mac_ppc_g++_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccaFTkwq.o -v -lstdc++ -lgcc -lSystemStubs -lSystem +collect2 version 4.2.1 (Apple Inc. build 5646) (Darwin/PowerPC) +/usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/ld -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccaFTkwq.o -v -lstdc++ -lgcc -lSystemStubs -lSystem +@(#)PROGRAM:ld PROJECT:ld64-95.2.12 +Library search paths: + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/gcc/powerpc-apple-darwin10/4.2.1 + /usr/lib/powerpc-apple-darwin10/4.2.1 + /usr/lib + /usr/lib + /usr/local/lib +Framework search paths: + /Library/Frameworks/ + /System/Library/Frameworks/") +set(mac_ppc_g++_Wlv_libs "stdc++") +set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +list(APPEND platforms mac_ppc_g++_Wlv) + # g++ -arch ppc dummy.cxx -v set(mac_ppc_g++_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccbjB6Lj.o -lstdc++ -lgcc -lSystemStubs -lSystem") set(mac_ppc_g++_libs "stdc++") From cc676c3a08019b17433931a9287d9cd8b0ccf2f2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 5 Dec 2012 13:46:04 -0500 Subject: [PATCH 017/131] OS X: Detect implicit linker framework search paths Previously we hard-coded a list of implicit framework directories but did not account for CMAKE_OSX_SYSROOT or for changes to the list across OS X versions. Instead we should automatically detect the framework directories for the active toolchain. The parent commit added the "-Wl,-v" option to ask "ld" to print its implicit directories. It displays a block such as: Framework search paths: /... Parse this block to extract the list of framework directories. Detection may fail on toolchains that do not list their framework directories, such as older OS X linkers. Always treat the paths /Library/Frameworks /System/Library/Frameworks /Network/Library/Frameworks # Older OS X only /System/Library/Frameworks as implicit. Note that /System/Library/Frameworks should always be considered implicit so that frameworks CMake finds there will not override the SDK copies. --- Modules/CMakeCCompiler.cmake.in | 1 + Modules/CMakeCXXCompiler.cmake.in | 1 + Modules/CMakeDetermineCompilerABI.cmake | 4 +- Modules/CMakeFortranCompiler.cmake.in | 1 + Modules/CMakeParseImplicitLinkInfo.cmake | 40 ++++++++++++------- Modules/Platform/Darwin.cmake | 18 +++++++++ Source/cmComputeLinkInformation.cxx | 29 ++++++++++++-- Source/cmDocumentVariables.cxx | 9 +++++ .../CMakeTests/ImplicitLinkInfoTest.cmake.in | 11 +++-- Tests/SystemInformation/SystemInformation.in | 2 + 10 files changed, 94 insertions(+), 22 deletions(-) diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index d74dcdcee..c41adc956 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -50,6 +50,7 @@ endif() set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "@CMAKE_C_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") @SET_CMAKE_CMCLDEPS_EXECUTABLE@ @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 8c5d84e6c..9287b8194 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -51,6 +51,7 @@ endif() set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") @SET_CMAKE_CMCLDEPS_EXECUTABLE@ @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@ diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index cb94aa655..25d6bbea7 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -72,8 +72,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # Parse implicit linker information for this language, if available. set(implicit_dirs "") set(implicit_libs "") + set(implicit_fwks "") if(CMAKE_${lang}_VERBOSE_FLAG) - CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs log + CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Parsed ${lang} implicit link information from above output:\n${log}\n\n") @@ -111,6 +112,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE) set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE) + set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE) # Detect library architecture directory name. if(CMAKE_LIBRARY_ARCHITECTURE_REGEX) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 55f827773..d193881d9 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -52,3 +52,4 @@ endif() set(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "@CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index 54e812748..234fb7fa1 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -16,9 +16,10 @@ # This is used internally by CMake and should not be included by user # code. -function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) +function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj_regex) set(implicit_libs_tmp "") set(implicit_dirs_tmp) + set(implicit_fwks_tmp) set(log "") # Parse implicit linker arguments. @@ -113,6 +114,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) set(log "${log} Library search paths: [${implicit_dirs_match}]\n") list(APPEND implicit_dirs_tmp ${implicit_dirs_match}) endif() + if("${output_lines}" MATCHES ";Framework search paths:((;\t[^;]+)+)") + string(REPLACE ";\t" ";" implicit_fwks_match "${CMAKE_MATCH_1}") + set(log "${log} Framework search paths: [${implicit_fwks_match}]\n") + list(APPEND implicit_fwks_tmp ${implicit_fwks_match}) + endif() # Cleanup list of libraries and flags. # We remove items that are not language-specific. @@ -125,27 +131,33 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex) endif() endforeach() - # Cleanup list of library directories. - set(implicit_dirs "") - foreach(d IN LISTS implicit_dirs_tmp) - get_filename_component(dir "${d}" ABSOLUTE) - string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos) - if(NOT pos LESS 0) - set(msg ", skipping non-system directory") - else() - set(msg "") - list(APPEND implicit_dirs "${dir}") - endif() - set(log "${log} collapse library dir [${d}] ==> [${dir}]${msg}\n") + # Cleanup list of library and framework directories. + set(desc_dirs "library") + set(desc_fwks "framework") + foreach(t dirs fwks) + set(implicit_${t} "") + foreach(d IN LISTS implicit_${t}_tmp) + get_filename_component(dir "${d}" ABSOLUTE) + string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos) + if(NOT pos LESS 0) + set(msg ", skipping non-system directory") + else() + set(msg "") + list(APPEND implicit_${t} "${dir}") + endif() + set(log "${log} collapse ${desc_${t}} dir [${d}] ==> [${dir}]${msg}\n") + endforeach() + list(REMOVE_DUPLICATES implicit_${t}) endforeach() - list(REMOVE_DUPLICATES implicit_dirs) # Log results. set(log "${log} implicit libs: [${implicit_libs}]\n") set(log "${log} implicit dirs: [${implicit_dirs}]\n") + set(log "${log} implicit fwks: [${implicit_fwks}]\n") # Return results. set(${lib_var} "${implicit_libs}" PARENT_SCOPE) set(${dir_var} "${implicit_dirs}" PARENT_SCOPE) + set(${fwk_var} "${implicit_fwks}" PARENT_SCOPE) set(${log_var} "${log}" PARENT_SCOPE) endfunction() diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index ed0b8af3f..2e6b71e36 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -256,6 +256,24 @@ set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK if(NOT DEFINED CMAKE_FIND_FRAMEWORK) set(CMAKE_FIND_FRAMEWORK FIRST) endif() + +# Older OS X linkers do not report their framework search path +# with -v but "man ld" documents the following locations. +set(CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + ${_CMAKE_OSX_SYSROOT_PATH}/Library/Frameworks + ${_CMAKE_OSX_SYSROOT_PATH}/System/Library/Frameworks + ) +if(_CMAKE_OSX_SYSROOT_PATH) + # Treat some paths as implicit so we do not override the SDK versions. + list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + /System/Library/Frameworks) +endif() +if("${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5") + # Older OS X tools had more implicit paths. + list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + ${_CMAKE_OSX_SYSROOT_PATH}/Network/Library/Frameworks) +endif() + # set up the default search directories for frameworks set(CMAKE_SYSTEM_FRAMEWORK_PATH ~/Library/Frameworks diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d8ffb5e83..19de90347 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1376,10 +1376,31 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item) //---------------------------------------------------------------------------- void cmComputeLinkInformation::ComputeFrameworkInfo() { - // Avoid adding system framework paths. See "man ld" on OS X. - this->FrameworkPathsEmmitted.insert("/Library/Frameworks"); - this->FrameworkPathsEmmitted.insert("/Network/Library/Frameworks"); - this->FrameworkPathsEmmitted.insert("/System/Library/Frameworks"); + // Avoid adding implicit framework paths. + std::vector implicitDirVec; + + // Get platform-wide implicit directories. + if(const char* implicitLinks = this->Makefile->GetDefinition + ("CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")) + { + cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec); + } + + // Get language-specific implicit directories. + std::string implicitDirVar = "CMAKE_"; + implicitDirVar += this->LinkLanguage; + implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"; + if(const char* implicitDirs = + this->Makefile->GetDefinition(implicitDirVar.c_str())) + { + cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec); + } + + for(std::vector::const_iterator i = implicitDirVec.begin(); + i != implicitDirVec.end(); ++i) + { + this->FrameworkPathsEmmitted.insert(*i); + } // Regular expression to extract a framework path and name. this->SplitFramework.compile("(.*)/(.*)\\.framework$"); diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 55d70f862..0a4170b71 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1624,6 +1624,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "reports the results in this variable.", false, "Variables for Languages"); + cm->DefineProperty + ("CMAKE__IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", cmProperty::VARIABLE, + "Implicit linker framework search path detected for language .", + "These paths are implicit linker framework search directories for " + "the compiler's language. " + "CMake automatically detects these directories for each language and " + "reports the results in this variable.", false, + "Variables for Languages"); + cm->DefineProperty ("CMAKE__IMPLICIT_LINK_LIBRARIES", cmProperty::VARIABLE, "Implicit link libraries and flags detected for language .", diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 02963042c..31488c0ff 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -120,6 +120,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_i686_gcc_Wlv_libs "") set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gcc_Wlv) # gcc -arch i686 dummy.c -v @@ -146,6 +147,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_i686_g++_Wlv_libs "stdc++") set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_g++_Wlv) # g++ -arch i686 dummy.cxx -v @@ -169,6 +171,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran") set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib") +set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gfortran_Wlv) # gfortran dummy.f -v @@ -195,6 +198,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_ppc_gcc_Wlv_libs "") set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_gcc_Wlv) # gcc -arch ppc dummy.c -v @@ -221,6 +225,7 @@ Framework search paths: /System/Library/Frameworks/") set(mac_ppc_g++_Wlv_libs "stdc++") set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") +set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_g++_Wlv) # g++ -arch ppc dummy.cxx -v @@ -499,10 +504,10 @@ list(APPEND platforms msys_g77) # Test parsing for all above examples. foreach(p IN LISTS platforms) - cmake_parse_implicit_link_info("${${p}_text}" libs dirs log "${${p}_obj_regex}") + cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}") - foreach(v libs dirs) - if(NOT "${${v}}" STREQUAL "${${p}_${v}}") + foreach(v libs dirs fwks) + if(DEFINED "${p}_${v}" AND NOT "${${v}}" STREQUAL "${${p}_${v}}") message(FATAL_ERROR "cmake_parse_implicit_link_info failed\n" "Expected '${p}' implicit ${v}\n" diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in index ecbc05408..df3bf49d5 100644 --- a/Tests/SystemInformation/SystemInformation.in +++ b/Tests/SystemInformation/SystemInformation.in @@ -96,7 +96,9 @@ CMAKE_CXX_LINK_EXECUTABLE == "${CMAKE_CXX_LINK_EXECUTABLE}" // implicit link info CMAKE_C_IMPLICIT_LINK_LIBRARIES == "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}" CMAKE_C_IMPLICIT_LINK_DIRECTORIES == "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}" +CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES == "${CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}" CMAKE_CXX_IMPLICIT_LINK_LIBRARIES == "${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES}" CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES == "${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}" +CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES == "${CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}" XCODE_VERSION == "${XCODE_VERSION}" From daf17b13d5c8694c43c3c127dedbc93a1b2a894b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 12 Dec 2012 00:01:06 -0500 Subject: [PATCH 018/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 20e68e91e..41fc6a20c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121211) +set(CMake_VERSION_TWEAK 20121212) #set(CMake_VERSION_RC 1) From f6a9a64f16a6f79095dd3eb9563999253fa18f9f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 13 Dec 2012 00:01:03 -0500 Subject: [PATCH 019/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 41fc6a20c..59bac2dbb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121212) +set(CMake_VERSION_TWEAK 20121213) #set(CMake_VERSION_RC 1) From 34ecf7088b8d08bdc5cbf2462c8f9ad72425ecf9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 14 Dec 2012 00:01:02 -0500 Subject: [PATCH 020/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 59bac2dbb..e4117d550 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121213) +set(CMake_VERSION_TWEAK 20121214) #set(CMake_VERSION_RC 1) From a076b256c4786a3d86c7d3655fa26cd72761e16b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 15 Dec 2012 00:01:04 -0500 Subject: [PATCH 021/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e4117d550..6071fc27c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121214) +set(CMake_VERSION_TWEAK 20121215) #set(CMake_VERSION_RC 1) From d8dcd639101de6eeccf21860c0048a6c8bb188dc Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 16 Dec 2012 00:01:04 -0500 Subject: [PATCH 022/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6071fc27c..4cf6b99e1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121215) +set(CMake_VERSION_TWEAK 20121216) #set(CMake_VERSION_RC 1) From a3f63661e67c928c465562f988e4ab103b0ec865 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 17 Dec 2012 00:01:05 -0500 Subject: [PATCH 023/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4cf6b99e1..aced2e752 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121216) +set(CMake_VERSION_TWEAK 20121217) #set(CMake_VERSION_RC 1) From 8931dd6e74bce78737baaf78c9867c992829c60b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 18 Dec 2012 00:01:03 -0500 Subject: [PATCH 024/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index aced2e752..81d74c889 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121217) +set(CMake_VERSION_TWEAK 20121218) #set(CMake_VERSION_RC 1) From 324780697c5020a027efdc24bd9cc2fc926a3546 Mon Sep 17 00:00:00 2001 From: Casey Goodlett Date: Tue, 18 Dec 2012 13:09:53 -0500 Subject: [PATCH 025/131] CTest: Prevent creation of unbounded number of tests in ctest (#12904) Note it is still possible for CTest to start more than the number of processes specified by PARALLEL_LEVEL, but this prevents the number of tests to start from being unbounded because of overflow. --- Source/CTest/cmCTestMultiProcessHandler.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index ebef1ed9c..76ddeea01 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -248,7 +248,12 @@ bool cmCTestMultiProcessHandler::StartTest(int test) //--------------------------------------------------------- void cmCTestMultiProcessHandler::StartNextTests() { - size_t numToStart = this->ParallelLevel - this->RunningCount; + size_t numToStart = 0; + if(this->RunningCount < this->ParallelLevel) + { + numToStart = this->ParallelLevel - this->RunningCount; + } + if(numToStart == 0) { return; From 5ac16ea6e4ddb086d48c97fa4f58543284ec3305 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 19 Dec 2012 00:01:09 -0500 Subject: [PATCH 026/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 81d74c889..84ed3680b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121218) +set(CMake_VERSION_TWEAK 20121219) #set(CMake_VERSION_RC 1) From a0f91f1daa7765066a784e4479da7e231374a065 Mon Sep 17 00:00:00 2001 From: KWSys Robot Date: Wed, 19 Dec 2012 08:02:08 -0500 Subject: [PATCH 027/131] KWSys 2012-12-19 (933eb822) Extract upstream KWSys using the following shell commands. $ git archive --prefix=upstream-kwsys/ 933eb822 | tar x $ git shortlog --no-merges --abbrev=8 --format='%h %s' 3b17de34..933eb822 Brad King (2): fea37696 Process: Remove support for Windows 98 01e15c22 Remove KWSys Registry Rolf Eike Beer (7): f376ec32 SystemInformation: fix typos bfee5174 SystemInformation: sum up all caches found in /proc/cpuinfo 5690d711 SystemInformation: fix value extraction from /proc/cpuinfo 36295981 SystemInformation: PA-RISC chips are from HP 72e9d02e SystemInformation: try harder to find a useful processor name b39de34c SystemInformation: try harder to find the CPU family 933eb822 SystemInformation: extract CPU stepping information from /proc/cpuinfo, too Sean McBride (2): 5e17bfde Process: Dereference NULL++ instead of NULL to force crash 86a78cb7 SystemTools: Add check for empty strings to prevent integer underflow Change-Id: Id7194f434fe67be81e6ee9e96d705010a1171a06 --- CMakeLists.txt | 51 +-- EncodeExecutable.c | 114 ------ ProcessFwd9x.c | 211 ---------- ProcessWin32.c | 287 +------------ Registry.cxx | 818 -------------------------------------- Registry.hxx.in | 107 ----- SystemInformation.cxx | 99 ++++- SystemTools.cxx | 8 +- testProcess.c | 15 +- testRegistry.cxx | 109 ----- testSystemInformation.cxx | 1 + 11 files changed, 119 insertions(+), 1701 deletions(-) delete mode 100644 EncodeExecutable.c delete mode 100644 ProcessFwd9x.c delete mode 100644 Registry.cxx delete mode 100644 Registry.hxx.in delete mode 100644 testRegistry.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index 777d76f4b..ccdff1255 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_USE_MD5 1) SET(KWSYS_USE_Process 1) SET(KWSYS_USE_RegularExpression 1) - SET(KWSYS_USE_Registry 1) SET(KWSYS_USE_System 1) SET(KWSYS_USE_SystemTools 1) SET(KWSYS_USE_CommandLineArguments 1) @@ -762,7 +761,7 @@ SET(KWSYS_HXX_FILES Configure String # Add selected C++ classes. SET(cppclasses Directory DynamicLoader Glob RegularExpression SystemTools - CommandLineArguments Registry IOStream SystemInformation + CommandLineArguments IOStream SystemInformation ) FOREACH(cpp ${cppclasses}) IF(KWSYS_USE_${cpp}) @@ -800,12 +799,8 @@ SET(KWSYS_CXX_SRCS) # Add the proper sources for this platform's Process implementation. IF(KWSYS_USE_Process) IF(NOT UNIX) - # Use the Windows implementation. We need the encoded forwarding executable. - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c - ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c) - SET_SOURCE_FILES_PROPERTIES( - ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c - PROPERTIES GENERATED 1) + # Use the Windows implementation. + SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c) ELSE(NOT UNIX) # Use the UNIX implementation. SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) @@ -937,43 +932,6 @@ IF(KWSYS_USE_String) COMPILE_FLAGS "-DKWSYS_STRING_C") ENDIF(KWSYS_USE_String) -#----------------------------------------------------------------------------- -# Process execution on windows needs to build a forwarding executable -# that works around a Win9x bug. We encode the executable into a C -# file and build it into the library. Win9x platforms reproduce the -# executable into a temporary directory when it is needed. -IF(KWSYS_USE_Process) - IF(NOT UNIX) - # Build the forwarding executable itself and a program that will - # encode it into a C file. - ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY LABELS ${KWSYS_LABELS_EXE}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY LABELS ${KWSYS_LABELS_EXE}) - - SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}") - IF(CMAKE_BUILD_TOOL MATCHES "make") - SET(CFG_INTDIR "") - ENDIF(CMAKE_BUILD_TOOL MATCHES "make") - - # Take advantage of a better custom command syntax if possible. - SET(CMD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe) - SET(FWD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe) - ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c - COMMAND ${CMD} - ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c - ${KWSYS_NAMESPACE} ProcessFwd9x - DEPENDS ${CMD} ${FWD}) - - # Make sure build occurs in proper order. - ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x - ${KWSYS_NAMESPACE}EncodeExecutable) - ENDIF(NOT UNIX) -ENDIF(KWSYS_USE_Process) - #----------------------------------------------------------------------------- # Setup testing if not being built as part of another project. IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) @@ -1012,7 +970,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) ) ENDIF(NOT WATCOM) SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} - testRegistry testIOS testSystemTools testCommandLineArguments @@ -1116,8 +1073,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) # We expect test to fail SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON) GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv) - SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR_NOT_VALGRIND;FAIL;Test failed") - SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES PASS_REGULAR_EXPRESSION "Test passed") SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value") MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}") ENDIF() diff --git a/EncodeExecutable.c b/EncodeExecutable.c deleted file mode 100644 index bc30568ff..000000000 --- a/EncodeExecutable.c +++ /dev/null @@ -1,114 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include -#ifdef __WATCOMC__ -#define _unlink unlink -#endif -int main(int argc, char* argv[]) -{ - FILE* ifp; - FILE* ofp; - int i; - int n; - int count = 0; - unsigned char buffer[1024]; - - /* Check arguments. */ - if(argc != 5) - { - fprintf(stderr, "Usage: %s \n", - argv[0]); - return 1; - } - - /* Open the input file. */ - ifp = fopen(argv[1], "rb"); - if(!ifp) - { - fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]); - return 2; - } - ofp = fopen(argv[2], "w"); - if(!ofp) - { - fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]); - fclose(ifp); - return 2; - } - - /* Prepend header comment. */ - fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n"); - fprintf(ofp, " * %s\n */\n\n", argv[0]); - fprintf(ofp, "#include \"kwsysPrivate.h\"\n"); - fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n"); - fprintf(ofp, "#include \n\n"); - fprintf(ofp, "#if defined(_WIN32)\n"); - fprintf(ofp, "# include \n"); - fprintf(ofp, "#else\n"); - fprintf(ofp, "# include \n"); - fprintf(ofp, "#endif\n"); - fprintf(ofp, "\n"); - fprintf(ofp, "static void kwsys_unlink(const char* fname)\n"); - fprintf(ofp, "{\n"); - fprintf(ofp, "#if defined(__WATCOMC__)\n"); - fprintf(ofp, " unlink(fname);\n"); - fprintf(ofp, "#else\n"); - fprintf(ofp, " _unlink(fname);\n"); - fprintf(ofp, "#endif\n"); - fprintf(ofp, "}\n"); - fprintf(ofp, "\n"); - - /* Split file up in 1024-byte chunks. */ - while((n = (int)fread(buffer, 1, 1024, ifp)) > 0) - { - fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n", - argv[4], count++, n); - for(i=0; i < n-1; ++i) - { - fprintf(ofp, "0x%02X", buffer[i]); - if(i%10 == 9) - { - fprintf(ofp, ",\n"); - } - else - { - fprintf(ofp, ", "); - } - } - fprintf(ofp, "0x%02X};\n\n", buffer[n-1]); - } - fclose(ifp); - - /* Provide a function to write the data to a file. */ - fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n", - argv[3], argv[3], argv[4]); - fprintf(ofp, "{\n"); - fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n"); - fprintf(ofp, " if(!ofp) { return 0; }\n"); - for(i=0; i < count; ++i) - { - fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n" - " sizeof(kwsysEncodedArray%s_%d), ofp) !=\n" - " sizeof(kwsysEncodedArray%s_%d))\n", - argv[4], i, argv[4], i, argv[4], i); - fprintf(ofp, " {\n"); - fprintf(ofp, " fclose(ofp);\n"); - fprintf(ofp, " kwsys_unlink(fname);\n"); - fprintf(ofp, " return 0;\n"); - fprintf(ofp, " }\n"); - } - fprintf(ofp, " fclose(ofp);\n"); - fprintf(ofp, " return 1;\n"); - fprintf(ofp, "}\n"); - fclose(ofp); - return 0; -} diff --git a/ProcessFwd9x.c b/ProcessFwd9x.c deleted file mode 100644 index 536c54b67..000000000 --- a/ProcessFwd9x.c +++ /dev/null @@ -1,211 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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. -============================================================================*/ - -/* - On Windows9x platforms, this executable is spawned between a parent - process and the child it is invoking to work around a bug. See the - Win32 implementation file for details. - - Future Work: This executable must be linked statically against the C - runtime library before being encoded into the library. Building it - in this way may be hard because CMake has limited abilities to build - different targets with different configurations in the same - directory. We may just have to create and encode the executable - once instead of generating it during the build. This would be an - acceptable solution because the forwarding executable should not - change very often and is pretty simple. -*/ - -#ifdef _MSC_VER -#pragma warning (push, 1) -#endif -#include -#include - -void ReportLastError(HANDLE errorPipe); - -int main() -{ - /* Process startup information for the real child. */ - STARTUPINFO si; - PROCESS_INFORMATION pi; - - /* The result of waiting for the child to exit. */ - DWORD waitResult; - - /* The child's process return code. */ - DWORD retVal; - - /* The command line used to invoke this process. */ - LPSTR commandLine = GetCommandLine(); - - /* Pointer that will be advanced to the beginning of the command - line of the real child process. */ - LPSTR cmdLine = commandLine; - - /* Handle to the error reporting pipe provided by the parent. This - is parsed off the command line. */ - HANDLE errorPipe = 0; - HANDLE errorPipeOrig = 0; - - /* Handle to the event the parent uses to tell us to resume the child. - This is parsed off the command line. */ - HANDLE resumeEvent = 0; - - /* Handle to the event the parent uses to tell us to kill the child. - This is parsed off the command line. */ - HANDLE killEvent = 0; - - /* Flag for whether to hide window of child process. */ - int hideWindow = 0; - - /* An array of the handles on which we wait when the child is - running. */ - HANDLE waitHandles[2] = {0, 0}; - - /* Move the pointer past the name of this executable. */ - if(*cmdLine == '"') - { - ++cmdLine; - while(*cmdLine && *cmdLine != '"') { ++cmdLine; } - if(*cmdLine) { ++cmdLine; } - } - else - { - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - } - - /* Parse the error pipe handle. */ - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%p", &errorPipeOrig); - - /* Parse the resume event handle. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%p", &resumeEvent); - - /* Parse the kill event handle. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%p", &killEvent); - - /* Parse the hide window flag. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - sscanf(cmdLine, "%d", &hideWindow); - - /* Skip to the beginning of the command line of the real child. */ - while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } - while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } - - /* Create a non-inherited copy of the error pipe. We do not want - the child to get it. */ - if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig, - GetCurrentProcess(), &errorPipe, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - /* Have a non-inherited duplicate. Close the inherited one. */ - CloseHandle(errorPipeOrig); - } - else - { - /* Could not duplicate handle. Report the error. */ - ReportLastError(errorPipeOrig); - return 1; - } - - /* Create the subprocess. */ - ZeroMemory(&si, sizeof(si)); - ZeroMemory(&pi, sizeof(pi)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; - si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT; - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi)) - { - /* Process created successfully. Close the error reporting pipe - to notify the parent of success. */ - CloseHandle(errorPipe); - } - else - { - /* Error creating the process. Report the error to the parent - process through the special error reporting pipe. */ - ReportLastError(errorPipe); - return 1; - } - - /* Wait for resume or kill event from parent. */ - waitHandles[0] = killEvent; - waitHandles[1] = resumeEvent; - waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); - - /* Check what happened. */ - if(waitResult == WAIT_OBJECT_0) - { - /* We were asked to kill the child. */ - TerminateProcess(pi.hProcess, 255); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return 1; - } - else - { - /* We were asked to resume the child. */ - ResumeThread(pi.hThread); - CloseHandle(pi.hThread); - } - - /* Wait for subprocess to exit or for kill event from parent. */ - waitHandles[0] = killEvent; - waitHandles[1] = pi.hProcess; - waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); - - /* Check what happened. */ - if(waitResult == WAIT_OBJECT_0) - { - /* We were asked to kill the child. */ - TerminateProcess(pi.hProcess, 255); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - return 1; - } - else - { - /* The child exited. Get the return code. */ - GetExitCodeProcess(pi.hProcess, &retVal); - CloseHandle(pi.hProcess); - return retVal; - } -} - -void ReportLastError(HANDLE errorPipe) -{ - LPVOID lpMsgBuf; - DWORD n; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0); - LocalFree( lpMsgBuf ); -} diff --git a/ProcessWin32.c b/ProcessWin32.c index 5aa4d8bf6..c836f9b08 100644 --- a/ProcessWin32.c +++ b/ProcessWin32.c @@ -28,14 +28,6 @@ On windows, a thread is created to wait for data on each pipe. The threads are synchronized with the main thread to simulate the use of a UNIX-style select system call. -On Windows9x platforms, a small WIN32 console application is spawned -in-between the calling process and the actual child to be executed. -This is to work-around a problem with connecting pipes from WIN16 -console applications to WIN32 applications. - -For more information, please check Microsoft Knowledge Base Articles -Q190351 and Q150956. - */ #ifdef _MSC_VER @@ -91,18 +83,12 @@ Q190351 and Q150956. # define KWSYSPE_DEBUG(x) (void)1 #endif -#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x) - typedef LARGE_INTEGER kwsysProcessTime; typedef struct kwsysProcessCreateInformation_s { /* Windows child startup control data. */ STARTUPINFO StartupInfo; - - /* Special error reporting pipe for Win9x forwarding executable. */ - HANDLE ErrorPipeRead; - HANDLE ErrorPipeWrite; } kwsysProcessCreateInformation; /*--------------------------------------------------------------------------*/ @@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc static void kwsysProcessSetExitException(kwsysProcess* cp, int code); static void kwsysProcessKillTree(int pid); static void kwsysProcessDisablePipeThreads(kwsysProcess* cp); -extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname); /*--------------------------------------------------------------------------*/ /* A structure containing synchronization data for each thread. */ @@ -233,15 +218,6 @@ struct kwsysProcess_s /* Whether to treat command lines as verbatim. */ int Verbatim; - /* On Win9x platforms, the path to the forwarding executable. */ - char* Win9x; - - /* On Win9x platforms, the resume event for the forwarding executable. */ - HANDLE Win9xResumeEvent; - - /* On Win9x platforms, the kill event for the forwarding executable. */ - HANDLE Win9xKillEvent; - /* Mutex to protect the shared index used by threads to report data. */ HANDLE SharedIndexMutex; @@ -269,9 +245,6 @@ struct kwsysProcess_s HANDLE PipeNativeSTDOUT[2]; HANDLE PipeNativeSTDERR[2]; - /* Handle to automatically delete the Win9x forwarding executable. */ - HANDLE Win9xHandle; - /* ------------- Data managed per call to Execute ------------- */ /* The exceptional behavior that terminated the process, if any. */ @@ -311,7 +284,7 @@ struct kwsysProcess_s for pipes to close after process termination. */ int PipesLeft; - /* Buffer for error messages (possibly from Win9x child). */ + /* Buffer for error messages. */ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; /* Description for the ExitException. */ @@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void) /* Process control structure. */ kwsysProcess* cp; - /* Path to Win9x forwarding executable. */ - char* win9x = 0; - /* Windows version number data. */ OSVERSIONINFO osv; @@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void) GetVersionEx(&osv); if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { - /* This is Win9x. We need the console forwarding executable to - work-around a Windows 9x bug. */ - char fwdName[_MAX_FNAME+1] = ""; - char tempDir[_MAX_PATH+1] = ""; - - /* We will try putting the executable in the system temp - directory. Note that the returned path already has a trailing - slash. */ - DWORD length = GetTempPath(_MAX_PATH+1, tempDir); - - /* Construct the executable name from the process id and kwsysProcess - instance. This should be unique. */ - sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%ld_%p.exe", - GetCurrentProcessId(), cp); - - /* If we have a temp directory, use it. */ - if(length > 0 && length <= _MAX_PATH) - { - /* Allocate a buffer to hold the forwarding executable path. */ - size_t tdlen = strlen(tempDir); - win9x = (char*)malloc(tdlen + strlen(fwdName) + 2); - if(!win9x) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Construct the full path to the forwarding executable. */ - sprintf(win9x, "%s%s", tempDir, fwdName); - } - - /* If we found a place to put the forwarding executable, try to - write it. */ - if(win9x) - { - if(!kwsysEncodedWriteArrayProcessFwd9x(win9x)) - { - /* Failed to create forwarding executable. Give up. */ - free(win9x); - kwsysProcess_Delete(cp); - return 0; - } - - /* Get a handle to the file that will delete it when closed. */ - cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0, - OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); - if(cp->Win9xHandle == INVALID_HANDLE_VALUE) - { - /* We were not able to get a read handle for the forwarding - executable. It will not be deleted properly. Give up. */ - _unlink(win9x); - free(win9x); - kwsysProcess_Delete(cp); - return 0; - } - } - else - { - /* Failed to find a place to put forwarding executable. */ - kwsysProcess_Delete(cp); - return 0; - } + /* Win9x no longer supported. */ + kwsysProcess_Delete(cp); + return 0; } - /* Save the path to the forwarding executable. */ - cp->Win9x = win9x; - /* Initially no thread owns the mutex. Initialize semaphore to 1. */ if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0))) { @@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void) return 0; } - if(cp->Win9x) - { - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - - /* Create an event to tell the forwarding executable to resume the - child. */ - if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Create an event to tell the forwarding executable to kill the - child. */ - if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - } - /* Create the thread to read each pipe. */ for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) { @@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp) kwsysProcessCleanupHandle(&cp->SharedIndexMutex); kwsysProcessCleanupHandle(&cp->Full); - /* Close the Win9x resume and kill event handles. */ - if(cp->Win9x) - { - kwsysProcessCleanupHandle(&cp->Win9xResumeEvent); - kwsysProcessCleanupHandle(&cp->Win9xKillEvent); - } - /* Free memory. */ kwsysProcess_SetCommand(cp, 0); kwsysProcess_SetWorkingDirectory(cp, 0); @@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp) { free(cp->CommandExitCodes); } - if(cp->Win9x) - { - /* Close our handle to the forwarding executable file. This will - cause it to be deleted. */ - kwsysProcessCleanupHandle(&cp->Win9xHandle); - } free(cp); } @@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) SetCurrentDirectory(cp->WorkingDirectory); } - /* Reset the Win9x resume and kill events. */ - if(cp->Win9x) - { - if(!ResetEvent(cp->Win9xResumeEvent)) - { - kwsysProcessCleanup(cp, 1); - return; - } - if(!ResetEvent(cp->Win9xKillEvent)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - /* Initialize startup info data. */ ZeroMemory(&si, sizeof(si)); si.StartupInfo.cb = sizeof(si.StartupInfo); @@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) STD_OUTPUT_HANDLE); kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE); - kwsysProcessCleanupHandle(&si.ErrorPipeRead); - kwsysProcessCleanupHandle(&si.ErrorPipeWrite); return; } } @@ -1160,16 +1014,9 @@ void kwsysProcess_Execute(kwsysProcess* cp) /* All processes in the pipeline have been started in suspended mode. Resume them all now. */ - if(cp->Win9x) + for(i=0; i < cp->NumberOfCommands; ++i) { - SetEvent(cp->Win9xResumeEvent); - } - else - { - for(i=0; i < cp->NumberOfCommands; ++i) - { - ResumeThread(cp->ProcessInformation[i].hThread); - } + ResumeThread(cp->ProcessInformation[i].hThread); } /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */ @@ -1480,21 +1327,12 @@ void kwsysProcess_Kill(kwsysProcess* cp) /* Kill the children. */ cp->Killed = 1; - if(cp->Win9x) + for(i=0; i < cp->NumberOfCommands; ++i) { - /* Windows 9x. Tell the forwarding executable to kill the child. */ - SetEvent(cp->Win9xKillEvent); - } - else - { - /* Not Windows 9x. Just terminate the children. */ - for(i=0; i < cp->NumberOfCommands; ++i) - { - kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); - // close the handle if we kill it - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); - } + kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); + // close the handle if we kill it + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); } /* We are killing the children and ignoring all data. Do not wait @@ -1815,97 +1653,13 @@ int kwsysProcessCreate(kwsysProcess* cp, int index, } } - /* Create the child process. */ - { - BOOL r; - char* realCommand; - if(cp->Win9x) - { - /* Create an error reporting pipe for the forwarding executable. - Neither end is directly inherited. */ - if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0)) - { - return 0; - } - - /* Create an inherited duplicate of the write end. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite, - GetCurrentProcess(), &si->ErrorPipeWrite, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - - /* The forwarding executable is given a handle to the error pipe - and resume and kill events. */ - realCommand = (char*)malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100); - if(!realCommand) - { - return 0; - } - sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x, - si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent, - cp->HideWindow, cp->Commands[index]); - } - else - { - realCommand = cp->Commands[index]; - } - /* Create the child in a suspended state so we can wait until all children have been created before running any one. */ - r = CreateProcess(0, realCommand, 0, 0, TRUE, - cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0, - &si->StartupInfo, &cp->ProcessInformation[index]); - if(cp->Win9x) - { - /* Free memory. */ - free(realCommand); - - /* Close the error pipe write end so we can detect when the - forwarding executable closes it. */ - kwsysProcessCleanupHandle(&si->ErrorPipeWrite); - if(r) - { - /* Wait for the forwarding executable to report an error or - close the error pipe to report success. */ - DWORD total = 0; - DWORD n = 1; - while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) - { - if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total, - KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0)) - { - total += n; - } - else - { - n = 0; - } - } - if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE) - { - /* The forwarding executable could not run the process, or - there was an error reading from its error pipe. Preserve - the last error while cleaning up the forwarding executable - so the cleanup our caller does reports the proper error. */ - DWORD error = GetLastError(); - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread); - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); - SetLastError(error); - return 0; - } - } - kwsysProcessCleanupHandle(&si->ErrorPipeRead); - } - - if(!r) + if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, + 0, &si->StartupInfo, &cp->ProcessInformation[index])) { return 0; } - } /* Successfully created this child process. Close the current process's copies of the inherited stdout and stdin handles. The @@ -2152,19 +1906,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) /* Cleanup any processes already started in a suspended state. */ if(cp->ProcessInformation) { - if(cp->Win9x) + for(i=0; i < cp->NumberOfCommands; ++i) { - SetEvent(cp->Win9xKillEvent); - } - else - { - for(i=0; i < cp->NumberOfCommands; ++i) + if(cp->ProcessInformation[i].hProcess) { - if(cp->ProcessInformation[i].hProcess) - { - TerminateProcess(cp->ProcessInformation[i].hProcess, 255); - WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE); - } + TerminateProcess(cp->ProcessInformation[i].hProcess, 255); + WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE); } } for(i=0; i < cp->NumberOfCommands; ++i) diff --git a/Registry.cxx b/Registry.cxx deleted file mode 100644 index cd521c966..000000000 --- a/Registry.cxx +++ /dev/null @@ -1,818 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "kwsysPrivate.h" -#include KWSYS_HEADER(Registry.hxx) - -#include KWSYS_HEADER(Configure.hxx) -#include KWSYS_HEADER(ios/iostream) -#include KWSYS_HEADER(stl/string) -#include KWSYS_HEADER(stl/map) -#include KWSYS_HEADER(ios/iostream) -#include KWSYS_HEADER(ios/fstream) -#include KWSYS_HEADER(ios/sstream) -// Work-around CMake dependency scanning limitation. This must -// duplicate the above list of headers. -#if 0 -# include "Registry.hxx.in" -# include "Configure.hxx.in" -# include "kwsys_stl.hxx.in" -# include "kwsys_stl_string.hxx.in" -# include "kwsys_stl_map.hxx.in" -# include "kwsys_ios_iostream.h.in" -# include "kwsys_ios_fstream.h.in" -# include "kwsys_ios_sstream.h.in" -#endif - -#include // for isspace -#include -#include /* strlen, strncpy */ -#include /* getenv */ - -#ifdef _WIN32 -# include -#endif - - -namespace KWSYS_NAMESPACE -{ -class RegistryHelper { -public: - RegistryHelper(Registry::RegistryType registryType); - virtual ~RegistryHelper(); - - // Read a value from the registry. - virtual bool ReadValue(const char *key, const char **value); - - // Delete a key from the registry. - virtual bool DeleteKey(const char *key); - - // Delete a value from a given key. - virtual bool DeleteValue(const char *key); - - // Set value in a given key. - virtual bool SetValue(const char *key, const char *value); - - // Open the registry at toplevel/subkey. - virtual bool Open(const char *toplevel, const char *subkey, - int readonly); - - // Close the registry. - virtual bool Close(); - - // Set the value of changed - void SetChanged(bool b) { m_Changed = b; } - void SetTopLevel(const char* tl); - const char* GetTopLevel() { return m_TopLevel.c_str(); } - - //! Read from local or global scope. On Windows this mean from local machine - // or local user. On unix this will read from $HOME/.Projectrc or - // /etc/Project - void SetGlobalScope(bool b); - bool GetGlobalScope(); - - kwsys_stl::string EncodeKey(const char* str); - kwsys_stl::string EncodeValue(const char* str); - kwsys_stl::string DecodeValue(const char* str); - -protected: - bool m_Changed; - kwsys_stl::string m_TopLevel; - bool m_GlobalScope; - -#ifdef _WIN32 - HKEY HKey; -#endif - // Strip trailing and ending spaces. - char *Strip(char *str); - void SetSubKey(const char* sk); - kwsys_stl::string CreateKey(const char *key); - - typedef kwsys_stl::map StringToStringMap; - StringToStringMap EntriesMap; - kwsys_stl::string m_SubKey; - bool m_Empty; - bool m_SubKeySpecified; - kwsys_stl::string m_HomeDirectory; - - Registry::RegistryType m_RegistryType; -}; - -//---------------------------------------------------------------------------- -#define Registry_BUFFER_SIZE 8192 - -//---------------------------------------------------------------------------- -Registry::Registry(Registry::RegistryType registryType) -{ - m_Opened = false; - m_Locked = false; - this->Helper = 0; - this->Helper = new RegistryHelper(registryType); -} - -//---------------------------------------------------------------------------- -Registry::~Registry() -{ - if ( m_Opened ) - { - kwsys_ios::cerr << "Registry::Close should be " - "called here. The registry is not closed." - << kwsys_ios::endl; - } - delete this->Helper; -} - -//---------------------------------------------------------------------------- -void Registry::SetGlobalScope(bool b) -{ - this->Helper->SetGlobalScope(b); -} - -//---------------------------------------------------------------------------- -bool Registry::GetGlobalScope() -{ - return this->Helper->GetGlobalScope(); -} - -//---------------------------------------------------------------------------- -bool Registry::Open(const char *toplevel, - const char *subkey, int readonly) -{ - bool res = false; - if ( m_Locked ) - { - return res; - } - if ( m_Opened ) - { - if ( !this->Close() ) - { - return res; - } - } - if ( !toplevel || !*toplevel ) - { - kwsys_ios::cerr << "Registry::Opened() Toplevel not defined" - << kwsys_ios::endl; - return res; - } - - if ( isspace(toplevel[0]) || - isspace(toplevel[strlen(toplevel)-1]) ) - { - kwsys_ios::cerr << "Toplevel has to start with letter or number and end" - " with one" << kwsys_ios::endl; - return res; - } - - res = this->Helper->Open(toplevel, subkey, readonly); - if ( readonly != Registry::READONLY ) - { - m_Locked = true; - } - - if ( res ) - { - m_Opened = true; - this->Helper->SetTopLevel(toplevel); - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::Close() -{ - bool res = false; - if ( m_Opened ) - { - res = this->Helper->Close(); - } - - if ( res ) - { - m_Opened = false; - m_Locked = false; - this->Helper->SetChanged(false); - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::ReadValue(const char *subkey, - const char *key, - const char **value) -{ - bool res = false; - bool open = false; - if ( ! value ) - { - return res; - } - *value = 0; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READONLY) ) - { - return res; - } - open = true; - } - res = this->Helper->ReadValue(key, value); - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::DeleteKey(const char *subkey, const char *key) -{ - bool res = false; - bool open = false; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READWRITE) ) - { - return res; - } - open = true; - } - - res = this->Helper->DeleteKey(key); - if ( res ) - { - this->Helper->SetChanged(true); - } - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::DeleteValue(const char *subkey, const char *key) -{ - bool res = false; - bool open = false; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READWRITE) ) - { - return res; - } - open = true; - } - - res = this->Helper->DeleteValue(key); - if ( res ) - { - this->Helper->SetChanged(true); - } - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -bool Registry::SetValue(const char *subkey, const char *key, - const char *value) -{ - bool res = false; - bool open = false; - if ( !m_Opened ) - { - if ( !this->Open(this->GetTopLevel(), subkey, - Registry::READWRITE) ) - { - return res; - } - open = true; - } - - res = this->Helper->SetValue( key, value ); - if ( res ) - { - this->Helper->SetChanged(true); - } - - if ( open ) - { - if ( !this->Close() ) - { - res = false; - } - } - return res; -} - -//---------------------------------------------------------------------------- -const char* Registry::GetTopLevel() -{ - return this->Helper->GetTopLevel(); -} - -//---------------------------------------------------------------------------- -void Registry::SetTopLevel(const char* tl) -{ - this->Helper->SetTopLevel(tl); -} - -//---------------------------------------------------------------------------- -void RegistryHelper::SetTopLevel(const char* tl) -{ - if ( tl ) - { - m_TopLevel = tl; - } - else - { - m_TopLevel = ""; - } -} - -//---------------------------------------------------------------------------- -RegistryHelper::RegistryHelper(Registry::RegistryType registryType) -{ - m_Changed = false; - m_TopLevel = ""; - m_SubKey = ""; - m_SubKeySpecified = false; - m_Empty = true; - m_GlobalScope = false; - m_RegistryType = registryType; -} - -//---------------------------------------------------------------------------- -RegistryHelper::~RegistryHelper() -{ -} - - -//---------------------------------------------------------------------------- -bool RegistryHelper::Open(const char *toplevel, const char *subkey, - int readonly) -{ - this->EntriesMap.clear(); - m_Empty = 1; - -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - HKEY scope = HKEY_CURRENT_USER; - if ( this->GetGlobalScope() ) - { - scope = HKEY_LOCAL_MACHINE; - } - int res = 0; - kwsys_ios::ostringstream str; - DWORD dwDummy; - str << "Software\\Kitware\\" << toplevel << "\\" << subkey; - if ( readonly == Registry::READONLY ) - { - res = ( RegOpenKeyEx(scope, str.str().c_str(), - 0, KEY_READ, &this->HKey) == ERROR_SUCCESS ); - } - else - { - char lpClass[] = ""; - res = ( RegCreateKeyEx(scope, str.str().c_str(), - 0, lpClass, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, - NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS ); - } - if ( res != 0 ) - { - this->SetSubKey( subkey ); - } - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - bool res = false; - int cc; - kwsys_ios::ostringstream str; - const char* homeDirectory; - if ( (homeDirectory = getenv("HOME")) == 0 ) - { - if ( (homeDirectory = getenv("USERPROFILE")) == 0 ) - { - return false; - } - } - m_HomeDirectory = homeDirectory; - str << m_HomeDirectory.c_str() << "/." << toplevel << "rc"; - if ( readonly == Registry::READWRITE ) - { - kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app ); - if ( ofs.fail() ) - { - return false; - } - ofs.close(); - } - - kwsys_ios::ifstream *ifs = new kwsys_ios::ifstream(str.str().c_str(), kwsys_ios::ios::in -#ifndef KWSYS_IOS_USE_ANSI - | kwsys_ios::ios::nocreate -#endif - ); - if ( !ifs ) - { - return false; - } - if ( ifs->fail()) - { - delete ifs; - return false; - } - - res = true; - char buffer[Registry_BUFFER_SIZE]; - while( !ifs->fail() ) - { - ifs->getline(buffer, Registry_BUFFER_SIZE); - if ( ifs->fail() || ifs->eof() ) - { - break; - } - char *line = this->Strip(buffer); - if ( *line == '#' || *line == 0 ) - { - // Comment - continue; - } - int linelen = static_cast(strlen(line)); - for ( cc = 0; cc < linelen; cc++ ) - { - if ( line[cc] == '=' ) - { - char *key = new char[ cc+1 ]; - strncpy( key, line, cc ); - key[cc] = 0; - char *value = line + cc + 1; - char *nkey = this->Strip(key); - char *nvalue = this->Strip(value); - this->EntriesMap[nkey] = this->DecodeValue(nvalue); - m_Empty = 0; - delete [] key; - break; - } - } - } - ifs->close(); - this->SetSubKey( subkey ); - delete ifs; - return res; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::Close() -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - int res; - res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - if ( !m_Changed ) - { - this->SetSubKey(0); - return true; - } - - kwsys_ios::ostringstream str; - str << m_HomeDirectory.c_str() << "/." << this->GetTopLevel() << "rc"; - kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out); - if ( !ofs ) - { - return false; - } - if ( ofs->fail()) - { - delete ofs; - return false; - } - *ofs << "# This file is automatically generated by the application" << kwsys_ios::endl - << "# If you change any lines or add new lines, note that all" << kwsys_ios::endl - << "# comments and empty lines will be deleted. Every line has" << kwsys_ios::endl - << "# to be in format: " << kwsys_ios::endl - << "# key = value" << kwsys_ios::endl - << "#" << kwsys_ios::endl; - - if ( !this->EntriesMap.empty() ) - { - RegistryHelper::StringToStringMap::iterator it; - for ( it = this->EntriesMap.begin(); - it != this->EntriesMap.end(); - ++ it ) - { - *ofs << it->first.c_str() << " = " << this->EncodeValue(it->second.c_str()).c_str() << kwsys_ios::endl; - } - } - this->EntriesMap.clear(); - ofs->close(); - delete ofs; - this->SetSubKey(0); - m_Empty = 1; - return true; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::ReadValue(const char *skey, const char **value) - -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - DWORD dwType, dwSize; - dwType = REG_SZ; - char buffer[1024]; // Replace with RegQueryInfoKey - dwSize = sizeof(buffer); - int res = ( RegQueryValueEx(this->HKey, skey, NULL, &dwType, - (BYTE *)buffer, &dwSize) == ERROR_SUCCESS ); - if ( !res ) - { - return false; - } - this->EntriesMap[key] = buffer; - RegistryHelper::StringToStringMap::iterator it - = this->EntriesMap.find(key); - *value = it->second.c_str(); - return true; - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - bool res = false; - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - - RegistryHelper::StringToStringMap::iterator it - = this->EntriesMap.find(key); - if ( it != this->EntriesMap.end() ) - { - *value = it->second.c_str(); - res = true; - } - return res; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::DeleteKey(const char* skey) -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - int res = ( RegDeleteKey( this->HKey, skey ) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - this->EntriesMap.erase(key); - return true; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::DeleteValue(const char *skey) -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - int res = ( RegDeleteValue( this->HKey, skey ) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return false; - } - this->EntriesMap.erase(key); - return true; - } - return false; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::SetValue(const char *skey, const char *value) -{ -#ifdef _WIN32 - if ( m_RegistryType == Registry::WIN32_REGISTRY) - { - DWORD len = (DWORD)(value ? strlen(value) : 0); - int res = ( RegSetValueEx(this->HKey, skey, 0, REG_SZ, - (CONST BYTE *)(const char *)value, - len+1) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::FILE_REGISTRY ) - { - kwsys_stl::string key = this->CreateKey( skey ); - if ( key.empty() ) - { - return 0; - } - this->EntriesMap[key] = value; - return 1; - } - return false; -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::CreateKey( const char *key ) -{ - if ( !m_SubKeySpecified || m_SubKey.empty() || !key ) - { - return ""; - } - kwsys_ios::ostringstream ostr; - ostr << this->EncodeKey(this->m_SubKey.c_str()).c_str() - << "\\" << this->EncodeKey(key).c_str(); - return ostr.str(); -} - -//---------------------------------------------------------------------------- -void RegistryHelper::SetSubKey(const char* sk) -{ - if ( !sk ) - { - m_SubKey = ""; - m_SubKeySpecified = false; - } - else - { - m_SubKey = sk; - m_SubKeySpecified = true; - } -} - -//---------------------------------------------------------------------------- -char *RegistryHelper::Strip(char *str) -{ - int cc; - size_t len; - char *nstr; - if ( !str ) - { - return NULL; - } - len = strlen(str); - nstr = str; - for( cc=0; cc < static_cast(len); cc++ ) - { - if ( !isspace( *nstr ) ) - { - break; - } - nstr ++; - } - for( cc= static_cast(strlen(nstr))-1; cc>=0; cc-- ) - { - if ( !isspace( nstr[cc] ) ) - { - nstr[cc+1] = 0; - break; - } - } - return nstr; -} - -//---------------------------------------------------------------------------- -void RegistryHelper::SetGlobalScope(bool b) -{ - m_GlobalScope = b; -} - -//---------------------------------------------------------------------------- -bool RegistryHelper::GetGlobalScope() -{ - return m_GlobalScope; -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::EncodeKey(const char* str) -{ - kwsys_ios::ostringstream ostr; - while ( *str ) - { - switch ( *str ) - { - case '%': case '=': case '\n': case '\r': case '\t': - char buffer[4]; - sprintf(buffer, "%%%02X", *str); - ostr << buffer; - break; - default: - ostr << *str; - } - str ++; - } - return ostr.str(); -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::EncodeValue(const char* str) -{ - kwsys_ios::ostringstream ostr; - while ( *str ) - { - switch ( *str ) - { - case '%': case '=': case '\n': case '\r': case '\t': - char buffer[4]; - sprintf(buffer, "%%%02X", *str); - ostr << buffer; - break; - default: - ostr << *str; - } - str ++; - } - return ostr.str(); -} - -//---------------------------------------------------------------------------- -kwsys_stl::string RegistryHelper::DecodeValue(const char* str) -{ - kwsys_ios::ostringstream ostr; - while ( *str ) - { - unsigned int val; - switch ( *str ) - { - case '%': - if ( *(str+1) && *(str+2) && sscanf(str+1, "%x", &val) == 1 ) - { - ostr << static_cast(val); - str += 2; - } - else - { - ostr << *str; - } - break; - default: - ostr << *str; - } - str ++; - } - return ostr.str(); -} - -} // namespace KWSYS_NAMESPACE diff --git a/Registry.hxx.in b/Registry.hxx.in deleted file mode 100644 index ed9b01072..000000000 --- a/Registry.hxx.in +++ /dev/null @@ -1,107 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - 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 @KWSYS_NAMESPACE@_Registry_hxx -#define @KWSYS_NAMESPACE@_Registry_hxx - -#include <@KWSYS_NAMESPACE@/Configure.h> - -#include <@KWSYS_NAMESPACE@/stl/string> - -namespace @KWSYS_NAMESPACE@ -{ - -class RegistryHelper; - -/** \class Registry - * \brief Portable registry class - * - * This class abstracts the storing of data that can be restored - * when the program executes again. On Win32 platform it is - * implemented using the registry and on unix as a file in - * the user's home directory. - */ -class @KWSYS_NAMESPACE@_EXPORT Registry -{ -public: - enum RegistryType - { -#ifdef _WIN32 - WIN32_REGISTRY, -#endif - FILE_REGISTRY - }; - -#ifdef _WIN32 - Registry(RegistryType registryType = WIN32_REGISTRY); -#else - Registry(RegistryType registryType = FILE_REGISTRY); -#endif - - virtual ~Registry(); - - //! Read a value from the registry. - bool ReadValue(const char *subkey, const char *key, const char **value); - - //! Delete a key from the registry. - bool DeleteKey(const char *subkey, const char *key); - - //! Delete a value from a given key. - bool DeleteValue(const char *subkey, const char *key); - - //! Set value in a given key. - bool SetValue(const char *subkey, const char *key, - const char *value); - - //! Open the registry at toplevel/subkey. - bool Open(const char *toplevel, const char *subkey, - int readonly); - - //! Close the registry. - bool Close(); - - //! Read from local or global scope. On Windows this mean from local machine - // or local user. On unix this will read from $HOME/.Projectrc or - // /etc/Project - void GlobalScopeOn() { this->SetGlobalScope(1); } - void GlobalScopeOff() { this->SetGlobalScope(0); } - void SetGlobalScope(bool b); - bool GetGlobalScope(); - - // Set or get the toplevel registry key. - void SetTopLevel(const char* tl); - const char* GetTopLevel(); - - // Return true if registry opened - bool GetOpened() { return m_Opened; } - - // Should the registry be locked? - bool GetLocked() { return m_Locked; } - - enum { - READONLY, - READWRITE - }; - - // Return true if the character is space. - int IsSpace(char c); - -private: - RegistryHelper* Helper; - - bool m_Opened; - - bool m_Locked; -}; // End Class: Registry - -} // namespace @KWSYS_NAMESPACE@ - -#endif diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 6d990a99d..bfdb0edd6 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -307,7 +307,7 @@ public: enum Manufacturer { AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM, - Motorola, UnknownManufacturer + Motorola, HP, UnknownManufacturer }; protected: @@ -346,7 +346,7 @@ protected: static void Delay (unsigned int); static void DelayOverhead (unsigned int); - void FindManufacturer(); + void FindManufacturer(const kwsys_stl::string &family = ""); // For Mac bool ParseSysCtl(); @@ -1144,6 +1144,7 @@ void SystemInformationImplementation::RunCPUCheck() { // Retrieve the CPU details. RetrieveCPUIdentity(); + this->FindManufacturer(); RetrieveCPUFeatures(); } @@ -1415,6 +1416,8 @@ const char * SystemInformationImplementation::GetVendorID() return "IBM"; case Motorola: return "Motorola"; + case HP: + return "Hewlett-Packard"; default: return "Unknown Manufacturer"; } @@ -1670,7 +1673,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() #endif ; <> ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID + ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID ; edx: CPU feature flags mov eax,1 CPUID_INSTRUCTION @@ -1755,7 +1758,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() /** Find the manufacturer given the vendor id */ -void SystemInformationImplementation::FindManufacturer() +void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& family) { if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp. else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp. @@ -1771,6 +1774,7 @@ void SystemInformationImplementation::FindManufacturer() else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics + else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer } @@ -1809,7 +1813,7 @@ bool SystemInformationImplementation::RetrieveCPUIdentity() ; <> ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID + ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID ; edx: CPU feature flags mov eax,1 CPUID_INSTRUCTION @@ -1836,8 +1840,6 @@ bool SystemInformationImplementation::RetrieveCPUIdentity() vbuf[12] = '\0'; this->ChipID.Vendor = vbuf; - this->FindManufacturer(); - // Retrieve the family of CPU present. this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used @@ -2436,7 +2438,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures() #endif ; <> ; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID + ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID ; edx: CPU feature flags mov eax,0x80000001 CPUID_INSTRUCTION @@ -3002,6 +3004,16 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k size_t pos2 = buffer.find("\n",pos); if(pos!=buffer.npos && pos2!=buffer.npos) { + // It may happen that the beginning matches, but this is still not the requested key. + // An example is looking for "cpu" when "cpu family" comes first. So we check that + // we have only spaces from here to pos, otherwise we search again. + for(size_t i=this->CurrentPositionInFile+strlen(word); i < pos; ++i) + { + if(buffer[i] != ' ' && buffer[i] != '\t') + { + return this->ExtractValueFromCpuInfoFile(buffer, word, pos2); + } + } return buffer.substr(pos+2,pos2-pos-2); } } @@ -3073,7 +3085,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->NumberOfLogicalCPU = atoi(cpucount.c_str()); #endif // gotta have one, and if this is 0 then we get a / by 0n - // beter to have a bad answer than a crash + // better to have a bad answer than a crash if(this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; @@ -3082,32 +3094,83 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical= this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU; - // CPU speed (checking only the first proc + // CPU speed (checking only the first processor) kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz"); this->CPUSpeedInMHz = static_cast(atof(CPUSpeed.c_str())); // Chip family - this->ChipID.Family = atoi(this->ExtractValueFromCpuInfoFile(buffer,"cpu family").c_str()); + kwsys_stl::string familyStr = + this->ExtractValueFromCpuInfoFile(buffer,"cpu family"); + if(familyStr.empty()) + { + familyStr = this->ExtractValueFromCpuInfoFile(buffer,"CPU architecture"); + } + this->ChipID.Family = atoi(familyStr.c_str()); // Chip Vendor this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id"); - this->FindManufacturer(); + this->FindManufacturer(familyStr); + + // second try for setting family + if (this->ChipID.Family == 0 && this->ChipManufacturer == HP) + { + if (familyStr == "PA-RISC 1.1a") + this->ChipID.Family = 0x11a; + else if (familyStr == "PA-RISC 2.0") + this->ChipID.Family = 0x200; + // If you really get CMake to work on a machine not belonging to + // any of those families I owe you a dinner if you get it to + // contribute nightly builds regularly. + } // Chip Model this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str()); - this->RetrieveClassicalCPUIdentity(); + if(!this->RetrieveClassicalCPUIdentity()) + { + // Some platforms (e.g. PA-RISC) tell us their CPU name here. + // Note: x86 does not. + kwsys_stl::string cpuname = this->ExtractValueFromCpuInfoFile(buffer,"cpu"); + if(!cpuname.empty()) + { + this->ChipID.ProcessorName = cpuname; + } + } + + // Chip revision + kwsys_stl::string cpurev = this->ExtractValueFromCpuInfoFile(buffer,"stepping"); + if(cpurev.empty()) + { + cpurev = this->ExtractValueFromCpuInfoFile(buffer,"CPU revision"); + } + this->ChipID.Revision = atoi(cpurev.c_str()); // Chip Model Name this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str(); // L1 Cache size - kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,"cache size"); - pos = cacheSize.find(" KB"); - if(pos!=cacheSize.npos) + // Different architectures may show different names for the caches. + // Sum up everything we find. + kwsys_stl::vector cachename; + cachename.clear(); + + cachename.push_back("cache size"); // e.g. x86 + cachename.push_back("I-cache"); // e.g. PA-RISC + cachename.push_back("D-cache"); // e.g. PA-RISC + + this->Features.L1CacheSize = 0; + for (size_t index = 0; index < cachename.size(); index ++) { - cacheSize = cacheSize.substr(0,pos); + kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]); + if (!cacheSize.empty()) + { + pos = cacheSize.find(" KB"); + if(pos!=cacheSize.npos) + { + cacheSize = cacheSize.substr(0,pos); + } + this->Features.L1CacheSize += atoi(cacheSize.c_str()); + } } - this->Features.L1CacheSize = atoi(cacheSize.c_str()); return 1; } diff --git a/SystemTools.cxx b/SystemTools.cxx index 085d98836..1054d6526 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -2754,9 +2754,15 @@ kwsys_stl::string SystemTools::GetRealPath(const char* path) bool SystemTools::FileIsDirectory(const char* name) { + size_t length = strlen(name); + if (length == 0) + { + return false; + } + // Remove any trailing slash from the name. char buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; - size_t last = strlen(name)-1; + size_t last = length-1; if(last > 0 && (name[last] == '/' || name[last] == '\\') && strcmp(name, "/") !=0) { diff --git a/testProcess.c b/testProcess.c index 877002a14..ec561ead7 100644 --- a/testProcess.c +++ b/testProcess.c @@ -82,6 +82,14 @@ int test3(int argc, const char* argv[]) int test4(int argc, const char* argv[]) { + /* Prepare a pointer to an invalid address. Don't use null, because + dereferencing null is undefined behaviour and compilers are free to + do whatever they want. ex: Clang will warn at compile time, or even + optimize away the write. We hope to 'outsmart' them by using + 'volatile' and a slightly larger address, based on a runtime value. */ + volatile int* invalidAddress = 0; + invalidAddress += argc?1:2; + #if defined(_WIN32) /* Avoid error diagnostic popups since we are crashing on purpose. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); @@ -94,11 +102,8 @@ int test4(int argc, const char* argv[]) fprintf(stderr, "Output before crash on stderr from crash test.\n"); fflush(stdout); fflush(stderr); -#if defined(__clang__) - *(int*)1 = 0; /* Clang warns about 0-ptr; undefined behavior. */ -#else - *(int*)0 = 0; -#endif + /* Provoke deliberate crash by writing to the invalid address. */ + *invalidAddress = 0; fprintf(stdout, "Output after crash on stdout from crash test.\n"); fprintf(stderr, "Output after crash on stderr from crash test.\n"); return 0; diff --git a/testRegistry.cxx b/testRegistry.cxx deleted file mode 100644 index 7e9b0d49b..000000000 --- a/testRegistry.cxx +++ /dev/null @@ -1,109 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "kwsysPrivate.h" - -#include KWSYS_HEADER(Registry.hxx) -#include KWSYS_HEADER(ios/iostream) -#include - -// Work-around CMake dependency scanning limitation. This must -// duplicate the above list of headers. -#if 0 -# include "Registry.hxx.in" -# include "kwsys_ios_iostream.h.in" -#endif - -#define IFT(x,res) if ( !x ) \ - { \ - res = 1; \ - kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \ - } -#define IFNT(x,res) if ( x ) \ - { \ - res = 1; \ - kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \ - } - -#define CHE(x,y,res) if ( x && strcmp(x,y) ) \ - { \ - res = 1; \ - kwsys_ios::cout << "Error, " << x << " != " << y << kwsys_ios::endl; \ - } - -int testRegistry(int, char*[]) -{ - int res = 0; - - kwsys::Registry reg; - reg.SetTopLevel("TestRegistry"); - - IFT(reg.SetValue("TestSubkey", "TestKey1", "Test Value 1"), res); - IFT(reg.SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res); - IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res); - IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res); - - const char *buffer; - IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res); - CHE(buffer, "Test Value 1", res); - IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res); - CHE(buffer, "Test Value 2", res); - IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res); - CHE(buffer, "Test Value 3", res); - IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res); - CHE(buffer, "Test Value 4", res); - - IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res); - IFT(reg.SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res); - IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res); - IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res); - - IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res); - CHE(buffer, "New Test Value 1", res); - IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res); - CHE(buffer, "New Test Value 2", res); - IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res); - CHE(buffer, "New Test Value 3", res); - IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res); - CHE(buffer, "New Test Value 4", res); - - IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res); - IFNT(reg.ReadValue( "TestSubkey", "TestKey1", &buffer), res); - IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res); - IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", &buffer), res); - IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res); - IFNT(reg.ReadValue( "TestSubkey", "TestKey3", &buffer), res); - IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res); - IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", &buffer), res); - - const char* longStringWithNewLines = "Value with embedded CR and LF characters CR='\015' LF='\012' CRLF='\015\012'"; - IFT(reg.SetValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", longStringWithNewLines), res); - IFT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res); - CHE(buffer, longStringWithNewLines, res); - IFT(reg.DeleteValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1"), res); - IFNT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res); - - IFT(reg.SetValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", "Some value"), res); - IFT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res); - CHE(buffer, "Some value", res); - IFT(reg.DeleteValue("TestSubkeyWith = EqualSignChar", "TestKey = 1"), res); - IFNT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res); - - if ( res ) - { - kwsys_ios::cout << "Test failed" << kwsys_ios::endl; - } - else - { - kwsys_ios::cout << "Test passed" << kwsys_ios::endl; - } - return res; -} diff --git a/testSystemInformation.cxx b/testSystemInformation.cxx index 41fcf384b..cfd7ce210 100644 --- a/testSystemInformation.cxx +++ b/testSystemInformation.cxx @@ -66,6 +66,7 @@ int testSystemInformation(int, char*[]) printMethod(info, GetFamilyID); printMethod(info, GetModelID); printMethod(info, GetExtendedProcessorName); + printMethod(info, GetSteppingCode); printMethod(info, GetProcessorSerialNumber); printMethod2(info, GetProcessorCacheSize, "KB"); printMethod(info, GetLogicalProcessorsPerPhysical); From 2c24ca92193f0a03fbf8c0bb13f6a1cca83dd08e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 Dec 2012 09:00:55 -0500 Subject: [PATCH 028/131] Remove references to KWSys Process Win9x support The KWSys "EncodeExecutable" and "ProcessFwd9x" executables were dropped from KWSys along with Win9x Process support. Drop references from the rest of the CMake build rules. --- CMakeLists.txt | 2 -- bootstrap | 27 +++------------------------ 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a67fb6e62..9ad9587e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,8 +234,6 @@ macro (CMAKE_BUILD_UTILITIES) set(kwsys_folder "Utilities/KWSys") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}EncodeExecutable "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}ProcessFwd9x "${kwsys_folder}") if(BUILD_TESTING) CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}") diff --git a/bootstrap b/bootstrap index 0e6d16ca9..643720c86 100755 --- a/bootstrap +++ b/bootstrap @@ -284,18 +284,11 @@ if ${cmake_system_mingw}; then ProcessWin32 \ String \ System" - KWSYS_C_MINGW_SOURCES="\ - ProcessFwd9x \ - EncodeExecutable" - KWSYS_C_GENERATED_SOURCES="\ - cmsysProcessFwd9xEnc" else KWSYS_C_SOURCES="\ ProcessUNIX \ String \ System" - KWSYS_C_MINGW_SOURCES="" - KWSYS_C_GENERATED_SOURCES="" fi KWSYS_CXX_SOURCES="\ @@ -1351,7 +1344,7 @@ cmake_compiler_settings_comment="/* * Sources: * ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} * kwSys Sources: - * ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} ${KWSYS_C_MINGW_SOURCES} + * ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} */ " @@ -1447,7 +1440,7 @@ done # Generate Makefile dep="cmConfigure.h cmsys/*.hxx cmsys/*.h `cmake_escape \"${cmake_source_dir}\"`/Source/*.h" objs="" -for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} ${KWSYS_C_GENERATED_SOURCES}; do +for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}; do objs="${objs} ${a}.o" done @@ -1488,7 +1481,7 @@ for a in ${CMAKE_C_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_c_compiler} ${cmake_c_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done -for a in ${KWSYS_C_SOURCES} ${KWSYS_C_MINGW_SOURCES}; do +for a in ${KWSYS_C_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/kwsys/${a}.c"` src_flags=`eval echo \\${cmake_c_flags_\${a}}` echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" @@ -1500,20 +1493,6 @@ for a in ${KWSYS_CXX_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -DKWSYS_NAMESPACE=cmsys ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done -if ${cmake_system_mingw}; then - src=`cmake_escape "${cmake_bootstrap_dir}/cmsysProcessFwd9xEnc.c"` - in=`cmake_escape "${cmake_bootstrap_dir}/cmsysProcessFwd9x.exe"` - cmd=`cmake_escape "${cmake_bootstrap_dir}/cmsysEncodeExecutable.exe"` - a="cmsysProcessFwd9xEnc" - echo "${cmd} : EncodeExecutable.o" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_c_compiler} ${cmake_ld_flags} ${cmake_c_flags} EncodeExecutable.o -o ${cmd}" >> "${cmake_bootstrap_dir}/Makefile" - echo "${in} : ProcessFwd9x.o" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_c_compiler} ${cmake_ld_flags} ${cmake_c_flags} ProcessFwd9x.o -o ${in}" >> "${cmake_bootstrap_dir}/Makefile" - echo "${src} : ${cmd} ${in}" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmd} ${in} ${src} cmsys ProcessFwd9x" >> "${cmake_bootstrap_dir}/Makefile" - echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_c_compiler} ${cmake_c_flags} -I`cmake_escape \"${cmake_source_dir}/Source/kwsys\"` -DKWSYS_NAMESPACE=cmsys -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" -fi echo ' rebuild_cache: cd "${cmake_binary_dir}" && "${cmake_source_dir}/bootstrap" From e1d211abba91b37907e71b4de1fffb59ebe3c05d Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 20 Dec 2012 00:01:02 -0500 Subject: [PATCH 029/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 84ed3680b..66ae4c689 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121219) +set(CMake_VERSION_TWEAK 20121220) #set(CMake_VERSION_RC 1) From 76ea420fb9a8ceada0e806f1201230e5a7c1202c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 19 Nov 2012 19:30:56 +0100 Subject: [PATCH 030/131] Use cmsys::auto_ptr to manage cmCompiledGeneratorExpressions The compiled generator expressions need to outlive the creating type. For the same reason, store the input string in a std::string. --- Source/cmCustomCommandGenerator.cxx | 4 +-- Source/cmGeneratorExpression.cxx | 46 ++++++++++++----------------- Source/cmGeneratorExpression.h | 24 +++++++++------ Source/cmGeneratorTarget.cxx | 4 +-- Source/cmTarget.cxx | 7 +++-- Source/cmTestGenerator.cxx | 4 +-- 6 files changed, 44 insertions(+), 45 deletions(-) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 07df7d5e0..f2f77eea0 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const { return target->GetLocation(this->Config); } - return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config); + return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config); } //---------------------------------------------------------------------------- @@ -58,7 +58,7 @@ cmCustomCommandGenerator cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; for(unsigned int j=1;j < commandLine.size(); ++j) { - std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile, + std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile, this->Config); cmd += " "; if(this->OldStyle) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 32bf941eb..3fd4a5f8e 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -25,44 +25,29 @@ //---------------------------------------------------------------------------- cmGeneratorExpression::cmGeneratorExpression( cmListFileBacktrace const& backtrace): - Backtrace(backtrace), CompiledExpression(0) + Backtrace(backtrace) { } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr cmGeneratorExpression::Parse(std::string const& input) { return this->Parse(input.c_str()); } //---------------------------------------------------------------------------- -const cmCompiledGeneratorExpression & +cmsys::auto_ptr cmGeneratorExpression::Parse(const char* input) { - cmGeneratorExpressionLexer l; - std::vector tokens = l.Tokenize(input); - bool needsParsing = l.GetSawGeneratorExpression(); - std::vector evaluators; - - if (needsParsing) - { - cmGeneratorExpressionParser p(tokens); - p.Parse(evaluators); - } - - delete this->CompiledExpression; - this->CompiledExpression = new cmCompiledGeneratorExpression( - this->Backtrace, - evaluators, - input, - needsParsing); - return *this->CompiledExpression; + return cmsys::auto_ptr( + new cmCompiledGeneratorExpression( + this->Backtrace, + input)); } cmGeneratorExpression::~cmGeneratorExpression() { - delete this->CompiledExpression; } //---------------------------------------------------------------------------- @@ -73,7 +58,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( { if (!this->NeedsParsing) { - return this->Input; + return this->Input.c_str(); } this->Output = ""; @@ -108,12 +93,19 @@ const char *cmCompiledGeneratorExpression::Evaluate( cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace const& backtrace, - const std::vector &evaluators, - const char *input, bool needsParsing) - : Backtrace(backtrace), Evaluators(evaluators), Input(input), - NeedsParsing(needsParsing) + const char *input) + : Backtrace(backtrace), Input(input ? input : "") { + cmGeneratorExpressionLexer l; + std::vector tokens = + l.Tokenize(this->Input.c_str()); + this->NeedsParsing = l.GetSawGeneratorExpression(); + if (this->NeedsParsing) + { + cmGeneratorExpressionParser p(tokens); + p.Parse(this->Evaluators); + } } diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index ea3e7d03b..961e53d75 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -14,10 +14,12 @@ #define cmGeneratorExpression_h #include "cmStandardIncludes.h" +#include "cmListFileCache.h" #include #include +#include class cmTarget; class cmMakefile; @@ -44,8 +46,9 @@ public: cmGeneratorExpression(cmListFileBacktrace const& backtrace); ~cmGeneratorExpression(); - const cmCompiledGeneratorExpression& Parse(std::string const& input); - const cmCompiledGeneratorExpression& Parse(const char* input); + cmsys::auto_ptr Parse( + std::string const& input); + cmsys::auto_ptr Parse(const char* input); enum PreprocessContext { StripAllGeneratorExpressions @@ -59,7 +62,6 @@ private: void operator=(const cmGeneratorExpression &); cmListFileBacktrace const& Backtrace; - cmCompiledGeneratorExpression *CompiledExpression; }; class cmCompiledGeneratorExpression @@ -76,20 +78,24 @@ public: ~cmCompiledGeneratorExpression(); + std::string GetInput() const + { + return this->Input; + } + private: cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, - const std::vector &evaluators, - const char *input, bool needsParsing); + const char *input); friend class cmGeneratorExpression; cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &); void operator=(const cmCompiledGeneratorExpression &); - cmListFileBacktrace const& Backtrace; - const std::vector Evaluators; - const char* const Input; - const bool NeedsParsing; + cmListFileBacktrace Backtrace; + std::vector Evaluators; + const std::string Input; + bool NeedsParsing; mutable std::set Targets; mutable std::string Output; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index de8b5e369..55507ddf3 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -267,7 +267,7 @@ std::vector cmGeneratorTarget::GetIncludeDirectories( "INCLUDE_DIRECTORIES", 0, 0); cmSystemTools::ExpandListArgument(ge.Parse(prop) - .Evaluate(this->Makefile, + ->Evaluate(this->Makefile, config, false, this->Target, @@ -315,7 +315,7 @@ std::string cmGeneratorTarget::GetCompileDefinitions(const char *config) cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), defPropName, 0, 0); - return ge.Parse(prop).Evaluate(this->Makefile, + return ge.Parse(prop)->Evaluate(this->Makefile, config, false, this->Target, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index de3b23c78..e7b34ee42 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1728,9 +1728,10 @@ cmTargetTraceDependencies for(cmCustomCommandLine::const_iterator cli = cit->begin(); cli != cit->end(); ++cli) { - const cmCompiledGeneratorExpression &cge = ge.Parse(*cli); - cge.Evaluate(this->Makefile, 0, true); - std::set geTargets = cge.GetTargets(); + const cmsys::auto_ptr cge + = ge.Parse(*cli); + cge->Evaluate(this->Makefile, 0, true); + std::set geTargets = cge->GetTargets(); for(std::set::const_iterator it = geTargets.begin(); it != geTargets.end(); ++it) { diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 2f650e72e..42f511ea3 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, else { // Use the command name given. - exe = ge.Parse(exe.c_str()).Evaluate(mf, config); + exe = ge.Parse(exe.c_str())->Evaluate(mf, config); cmSystemTools::ConvertToUnixSlashes(exe); } @@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, for(std::vector::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) { - os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config)); + os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config)); } // Finish the test command. From 0d3b89ed7634598ef446da6b279f79b8bce20dd2 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 21 Dec 2012 00:01:16 -0500 Subject: [PATCH 031/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 66ae4c689..7eec30209 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121220) +set(CMake_VERSION_TWEAK 20121221) #set(CMake_VERSION_RC 1) From 349165223d26f0ffc5ad004b4a05a8a92121ac20 Mon Sep 17 00:00:00 2001 From: Riku Voipio Date: Fri, 21 Dec 2012 13:20:02 +0200 Subject: [PATCH 032/131] KWIML: Teach ABI.h about Aarch64 The __aarch64__ defines Aarch64, while __AARCH64EB__ defines bigendian and __AARCH64EL__ little endian. Only little endian tested, no big endian toolchain exists yet. Signed-off-by: Riku Voipio --- ABI.h.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ABI.h.in b/ABI.h.in index f93ddbaae..7f4772ae5 100644 --- a/ABI.h.in +++ b/ABI.h.in @@ -418,6 +418,14 @@ suppression macro @KWIML@_ABI_NO_VERIFY was defined. #elif defined(__vax__) # define @KWIML@_ABI_ENDIAN_ID @KWIML@_ABI_ENDIAN_ID_BIG +/* Aarch64 */ +#elif defined(__aarch64__) +# if !defined(__AARCH64EB__) +# define @KWIML@_ABI_ENDIAN_ID @KWIML@_ABI_ENDIAN_ID_LITTLE +# else +# define @KWIML@_ABI_ENDIAN_ID @KWIML@_ABI_ENDIAN_ID_BIG +# endif + /* Unknown CPU */ #elif !defined(@KWIML@_ABI_NO_ERROR_ENDIAN) # error "Byte order of target CPU unknown." From c95a13ecb9db33d4c74b0ab67b67baba1f9599ac Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 22 Dec 2012 00:01:12 -0500 Subject: [PATCH 033/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7eec30209..2d4011dc3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121221) +set(CMake_VERSION_TWEAK 20121222) #set(CMake_VERSION_RC 1) From 310455cc188c52373637f984b99017884e802e8a Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 22 Dec 2012 12:46:04 +0100 Subject: [PATCH 034/131] Fix some warnings from -Wundef Other warnings come from kwsys, so the flag can't be enabled. --- Source/cmCommandArgumentParser.cxx | 4 ++-- Source/cmake.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx index 696a6a8c3..c5146c5d7 100644 --- a/Source/cmCommandArgumentParser.cxx +++ b/Source/cmCommandArgumentParser.cxx @@ -279,7 +279,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -701,7 +701,7 @@ while (YYID (0)) we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ diff --git a/Source/cmake.cxx b/Source/cmake.cxx index fba4860fd..a44c825f7 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -953,7 +953,7 @@ int cmake::AddCMakePaths() cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str()); cMakeSelf += "/cmake"; cMakeSelf += cmSystemTools::GetExecutableExtension(); -#if __APPLE__ +#ifdef __APPLE__ // on the apple this might be the gui bundle if(!cmSystemTools::FileExists(cMakeSelf.c_str())) { From 567e7d946788e46f9709fe08985520b55e98293b Mon Sep 17 00:00:00 2001 From: KWSys Robot Date: Fri, 21 Dec 2012 08:29:37 -0500 Subject: [PATCH 035/131] KWSys 2012-12-21 (8ce09af5) Extract upstream KWSys using the following shell commands. $ git archive --prefix=upstream-kwsys/ 8ce09af5 | tar x $ git shortlog --no-merges --abbrev=8 --format='%h %s' 933eb822..8ce09af5 Riku Voipio (1): 8ce09af5 CPU: Add Aarch64 support Change-Id: I4bd0a97abaa0f958e2679afe2d4ad4bcc37434a0 --- CPU.h.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CPU.h.in b/CPU.h.in index ecd29d133..2e1a584b1 100644 --- a/CPU.h.in +++ b/CPU.h.in @@ -98,6 +98,14 @@ #elif defined(__SYSC_ZARCH__) # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG +/* Aarch64 */ +#elif defined(__aarch64__) +# if !defined(__AARCH64EB__) +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE +# else +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG +# endif + /* Unknown CPU */ #else # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID 0 From 00deb127be64cf8934d92c1593c8ea4a5f0f2061 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 23 Dec 2012 00:01:21 -0500 Subject: [PATCH 036/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2d4011dc3..a13524d0a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121222) +set(CMake_VERSION_TWEAK 20121223) #set(CMake_VERSION_RC 1) From 7d736af60e554e32115fdc188140fd63232d09c9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 11:32:42 +0100 Subject: [PATCH 037/131] Replace some 'if' with 'else if' For consistency with the rest of the method. --- Source/cmGeneratorExpressionEvaluator.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 102927edb..3b7cfc03a 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -553,13 +553,13 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) { if (identifier == "0") return &zeroNode; - if (identifier == "1") + else if (identifier == "1") return &oneNode; - if (identifier == "AND") + else if (identifier == "AND") return &andNode; - if (identifier == "OR") + else if (identifier == "OR") return &orNode; - if (identifier == "NOT") + else if (identifier == "NOT") return ¬Node; else if (identifier == "CONFIGURATION") return &configurationNode; From 4d580517a963138d5d22823b0827396d2864d3b0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 24 Dec 2012 00:01:20 -0500 Subject: [PATCH 038/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a13524d0a..493960bbe 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121223) +set(CMake_VERSION_TWEAK 20121224) #set(CMake_VERSION_RC 1) From a73294b9080bb1fbef889b29c0216f8bf47913bf Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 25 Dec 2012 00:01:07 -0500 Subject: [PATCH 039/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 493960bbe..6fef1aaa1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121224) +set(CMake_VERSION_TWEAK 20121225) #set(CMake_VERSION_RC 1) From 94933a5ec9a28909c4cb6fc883a4bb8da8c31ef0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 26 Dec 2012 00:01:05 -0500 Subject: [PATCH 040/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6fef1aaa1..0685525f5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121225) +set(CMake_VERSION_TWEAK 20121226) #set(CMake_VERSION_RC 1) From 539c222de029a8063f84ba528dd58b021f091e35 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 27 Dec 2012 00:01:14 -0500 Subject: [PATCH 041/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0685525f5..07d0371f8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121226) +set(CMake_VERSION_TWEAK 20121227) #set(CMake_VERSION_RC 1) From fb2db0e470002c372decf2aae2447de2cf27384c Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 28 Dec 2012 00:01:02 -0500 Subject: [PATCH 042/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 07d0371f8..f8fc90a78 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121227) +set(CMake_VERSION_TWEAK 20121228) #set(CMake_VERSION_RC 1) From 3793dca08a41fd9199e65ff834b839b4f65397c7 Mon Sep 17 00:00:00 2001 From: Eric LaFranchi Date: Fri, 14 Dec 2012 12:50:18 -0800 Subject: [PATCH 043/131] CPack: WIX Product Icon, UI Banner, UI Dialog support (#13789) --- Modules/CPackWIX.cmake | 26 ++++++++++++++++++++++++ Modules/WIX.template.in | 13 ++++++++++++ Source/CPack/WiX/cmCPackWIXGenerator.cxx | 3 +++ 3 files changed, 42 insertions(+) diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index f278953dd..0c0a8f19f 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -49,6 +49,32 @@ # by the WiX Generator in case CPACK_RESOURCE_FILE_LICENSE # is in an unsupported format or the .txt -> .rtf # conversion does not work as expected. +# +##end +# +##variable +# CPACK_WIX_PRODUCT_ICON - The Icon shown next to the program name in Add/Remove programs. +# +# If set, this icon is used in place of the default icon. +# +##end +# +##variable +# CPACK_WIX_UI_BANNER - The bitmap will appear at the top of all installer pages other than the welcome and completion dialogs. +# +# If set, this image will replace the default banner image. +# +# This image must be 493 by 58 pixels. +# +##end +# +##variable +# CPACK_WIX_UI_DIALOG - Background bitmap used on the welcome and completion dialogs. +# +# If this variable is set, the installer will replace the default dialog image. +# +# This image must be 493 by 312 pixels. +# ##end #============================================================================= diff --git a/Modules/WIX.template.in b/Modules/WIX.template.in index 63fad7cb7..0bc7e10ce 100644 --- a/Modules/WIX.template.in +++ b/Modules/WIX.template.in @@ -24,6 +24,19 @@ + + ProductIcon.ico + + + + + + + + + + + diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 8b5862559..e8b0ea971 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -221,6 +221,9 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_PACKAGE_NAME"); CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION"); CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF"); + CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON"); + CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER"); + CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG"); return true; } From 6bd93ea2402704e598519444d2d53252ed40153f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 29 Dec 2012 00:01:11 -0500 Subject: [PATCH 044/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f8fc90a78..cbe5b8760 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121228) +set(CMake_VERSION_TWEAK 20121229) #set(CMake_VERSION_RC 1) From 2716d8976fbbf728b2336b3793b5c2f7a470c0af Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 30 Dec 2012 00:01:07 -0500 Subject: [PATCH 045/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index cbe5b8760..d3e31c216 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121229) +set(CMake_VERSION_TWEAK 20121230) #set(CMake_VERSION_RC 1) From fb864d6e03efdb82f8f2744972ad14c012d86cc7 Mon Sep 17 00:00:00 2001 From: Benjamin Eikel Date: Sun, 30 Dec 2012 16:12:34 +0100 Subject: [PATCH 046/131] FindSDL_...: Restore dropped search paths (#13819) Restore the search paths that were accidentally dropped by me in commit 9ed24c53. This was already fixed for FindSDL.cmake in commit 7cb51739. --- Modules/FindSDL_image.cmake | 3 ++- Modules/FindSDL_mixer.cmake | 3 ++- Modules/FindSDL_net.cmake | 3 ++- Modules/FindSDL_sound.cmake | 3 ++- Modules/FindSDL_ttf.cmake | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/FindSDL_image.cmake b/Modules/FindSDL_image.cmake index 4cae03274..30d74acfb 100644 --- a/Modules/FindSDL_image.cmake +++ b/Modules/FindSDL_image.cmake @@ -40,7 +40,7 @@ find_path(SDL_IMAGE_INCLUDE_DIR SDL_image.h HINTS ENV SDLIMAGEDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_IMAGE_LIBRARY AND SDLIMAGE_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_IMAGE_LIBRARY HINTS ENV SDLIMAGEDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_IMAGE_INCLUDE_DIR AND EXISTS "${SDL_IMAGE_INCLUDE_DIR}/SDL_image.h") diff --git a/Modules/FindSDL_mixer.cmake b/Modules/FindSDL_mixer.cmake index 666fc6e0f..8ca7cc33c 100644 --- a/Modules/FindSDL_mixer.cmake +++ b/Modules/FindSDL_mixer.cmake @@ -40,7 +40,7 @@ find_path(SDL_MIXER_INCLUDE_DIR SDL_mixer.h HINTS ENV SDLMIXERDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_MIXER_LIBRARY AND SDLMIXER_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_MIXER_LIBRARY HINTS ENV SDLMIXERDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_MIXER_INCLUDE_DIR AND EXISTS "${SDL_MIXER_INCLUDE_DIR}/SDL_mixer.h") diff --git a/Modules/FindSDL_net.cmake b/Modules/FindSDL_net.cmake index d8f479f5b..ca707af8d 100644 --- a/Modules/FindSDL_net.cmake +++ b/Modules/FindSDL_net.cmake @@ -40,7 +40,7 @@ find_path(SDL_NET_INCLUDE_DIR SDL_net.h HINTS ENV SDLNETDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_NET_LIBRARY AND SDLNET_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_NET_LIBRARY HINTS ENV SDLNETDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_NET_INCLUDE_DIR AND EXISTS "${SDL_NET_INCLUDE_DIR}/SDL_net.h") diff --git a/Modules/FindSDL_sound.cmake b/Modules/FindSDL_sound.cmake index 5ff50be64..efd26580b 100644 --- a/Modules/FindSDL_sound.cmake +++ b/Modules/FindSDL_sound.cmake @@ -77,7 +77,7 @@ find_path(SDL_SOUND_INCLUDE_DIR SDL_sound.h HINTS ENV SDLSOUNDDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) find_library(SDL_SOUND_LIBRARY @@ -85,6 +85,7 @@ find_library(SDL_SOUND_LIBRARY HINTS ENV SDLSOUNDDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) diff --git a/Modules/FindSDL_ttf.cmake b/Modules/FindSDL_ttf.cmake index 2cc5ee232..bb0ca9147 100644 --- a/Modules/FindSDL_ttf.cmake +++ b/Modules/FindSDL_ttf.cmake @@ -40,7 +40,7 @@ find_path(SDL_TTF_INCLUDE_DIR SDL_ttf.h HINTS ENV SDLTTFDIR ENV SDLDIR - PATH_SUFFIXES SDL SDL12 SDL11 + PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include ) if(NOT SDL_TTF_LIBRARY AND SDLTTF_LIBRARY) @@ -52,6 +52,7 @@ find_library(SDL_TTF_LIBRARY HINTS ENV SDLTTFDIR ENV SDLDIR + PATH_SUFFIXES lib ) if(SDL_TTF_INCLUDE_DIR AND EXISTS "${SDL_TTF_INCLUDE_DIR}/SDL_ttf.h") From 34a8c823788c34e62f0c879c986a7b7940872976 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 31 Dec 2012 00:01:17 -0500 Subject: [PATCH 047/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d3e31c216..106a6f0fc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121230) +set(CMake_VERSION_TWEAK 20121231) #set(CMake_VERSION_RC 1) From 74be149bb3c28b45f20f330ff8d91f76ded28178 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 1 Jan 2013 00:01:05 -0500 Subject: [PATCH 048/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 106a6f0fc..bd2775847 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20121231) +set(CMake_VERSION_TWEAK 20130101) #set(CMake_VERSION_RC 1) From 953043e679286ed77907e4c9b5cad362e3155301 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 2 Jan 2013 00:01:16 -0500 Subject: [PATCH 049/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bd2775847..25a95d896 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130101) +set(CMake_VERSION_TWEAK 20130102) #set(CMake_VERSION_RC 1) From 510c9cfe030f400944bbcc1cfe8128e1636f1802 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 3 Jan 2013 00:01:17 -0500 Subject: [PATCH 050/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 25a95d896..3badbd7c5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130102) +set(CMake_VERSION_TWEAK 20130103) #set(CMake_VERSION_RC 1) From 30962029325b2126b0b986db0c5ce8e0660428a0 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 26 Dec 2012 10:58:21 +0100 Subject: [PATCH 051/131] Make targets depend on the link interface of their dependees. --- Source/cmComputeTargetDepends.cxx | 59 +++++++++++++++++++ Source/cmComputeTargetDepends.h | 6 +- .../target_link_libraries/CMakeLists.txt | 7 +++ .../target_link_libraries/depIfaceOnly.cpp | 7 +++ .../target_link_libraries/depIfaceOnly.h | 7 +++ .../target_link_libraries/targetA.cpp | 5 +- 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index ab77c6bc9..3b15ec11a 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -214,6 +214,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) if(emitted.insert(lib->first).second) { this->AddTargetDepend(depender_index, lib->first.c_str(), true); + this->AddInterfaceDepends(depender_index, lib->first.c_str(), + true, emitted); } } } @@ -236,6 +238,63 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) } } +//---------------------------------------------------------------------------- +void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, + cmTarget* dependee, + const char *config, + std::set &emitted) +{ + if(cmTarget::LinkInterface const* iface = + dependee->GetLinkInterface(config)) + { + for(std::vector::const_iterator + lib = iface->Libraries.begin(); + lib != iface->Libraries.end(); ++lib) + { + // Don't emit the same library twice for this target. + if(emitted.insert(*lib).second) + { + this->AddTargetDepend(depender_index, lib->c_str(), true); + } + } + } +} + +//---------------------------------------------------------------------------- +void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, + const char* dependee_name, + bool linking, + std::set &emitted) +{ + cmTarget* depender = this->Targets[depender_index]; + cmTarget* dependee = + depender->GetMakefile()->FindTargetToUse(dependee_name); + // Skip targets that will not really be linked. This is probably a + // name conflict between an external library and an executable + // within the project. + if(linking && dependee && + dependee->GetType() == cmTarget::EXECUTABLE && + !dependee->IsExecutableWithExports()) + { + dependee = 0; + } + + if(dependee) + { + this->AddInterfaceDepends(depender_index, dependee, 0, emitted); + std::vector configs; + depender->GetMakefile()->GetConfigurations(configs); + for (std::vector::const_iterator it = configs.begin(); + it != configs.end(); ++it) + { + // A target should not depend on itself. + emitted.insert(depender->GetName()); + this->AddInterfaceDepends(depender_index, dependee, + it->c_str(), emitted); + } + } +} + //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddTargetDepend(int depender_index, const char* dependee_name, diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 67bce72d9..d6131cf1c 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -48,7 +48,11 @@ private: bool linking); void AddTargetDepend(int depender_index, cmTarget* dependee, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); - + void AddInterfaceDepends(int depender_index, const char* dependee_name, + bool linking, std::set &emitted); + void AddInterfaceDepends(int depender_index, cmTarget* dependee, + const char *config, + std::set &emitted); cmGlobalGenerator* GlobalGenerator; bool DebugMode; bool NoCycles; diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 1faa88848..60b36fc27 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -56,3 +56,10 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "") target_link_libraries(targetA depB depC) assert_property(targetA LINK_INTERFACE_LIBRARIES "") + +# Exclude depIfaceOnly from ALL so that it will only be built if something +# depends on it. As it is in the link interface of depB, targetA +# will depend on it. That dependency is what is being tested here. +add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp) +generate_export_header(depIfaceOnly) +set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly) diff --git a/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp new file mode 100644 index 000000000..3b90af008 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.cpp @@ -0,0 +1,7 @@ + +#include "depIfaceOnly.h" + +int DepIfaceOnly::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h new file mode 100644 index 000000000..dddf6a5e4 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depIfaceOnly.h @@ -0,0 +1,7 @@ + +#include "depifaceonly_export.h" + +struct DEPIFACEONLY_EXPORT DepIfaceOnly +{ + int foo(); +}; diff --git a/Tests/CMakeCommands/target_link_libraries/targetA.cpp b/Tests/CMakeCommands/target_link_libraries/targetA.cpp index 3c6472e9a..6ff65b106 100644 --- a/Tests/CMakeCommands/target_link_libraries/targetA.cpp +++ b/Tests/CMakeCommands/target_link_libraries/targetA.cpp @@ -1,6 +1,7 @@ #include "depB.h" #include "depC.h" +#include "depIfaceOnly.h" int main(int argc, char **argv) { @@ -8,5 +9,7 @@ int main(int argc, char **argv) DepB b; DepC c; - return a.foo() + b.foo() + c.foo(); + DepIfaceOnly iface_only; + + return a.foo() + b.foo() + c.foo() + iface_only.foo(); } From e378ba5f39a9d8ebe0335390870a82774ecdd171 Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 26 Dec 2012 15:22:59 -0500 Subject: [PATCH 052/131] Add CTestLimitDashJ test (#12904) Add a test that verifies that when ctest -j 4 is called, at most, 4 tests are executed at any one time. The test works by running the same script as each of 100 tests. And then setting up test properties for DEPENDS, RUN_SERIAL, PROCESSORS and COST in order to get the tests to run in a semi-deterministic ordering, even in parallel. The script writes a file, sleeps for a bit, and then deletes the file. In the meantime, it counts files that currently exist, and emits output that triggers a test failure if the count of files is ever greater than 4. Prior to the commit that fixed bug #12904, this would result in a failed test because the output of some of the tests would indicate that more than 4 tests were running simultaneously. Now that this issue is resolved, this test will help guarantee that it stays resolved moving forward. --- Tests/CMakeLists.txt | 3 ++ Tests/CTestLimitDashJ/CMakeLists.txt | 50 +++++++++++++++++++ Tests/CTestLimitDashJ/CreateSleepDelete.cmake | 48 ++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 Tests/CTestLimitDashJ/CMakeLists.txt create mode 100644 Tests/CTestLimitDashJ/CreateSleepDelete.cmake diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index f443b5b36..b3302f91f 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1959,6 +1959,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --output-log "${CMake_BINARY_DIR}/Tests/CTestTestParallel/testOutput.log" ) + add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4 + --output-on-failure -C "\${CTestTest_CONFIG}") + add_test(CTestTestPrintLabels ${CMAKE_CTEST_COMMAND} --print-labels) set_tests_properties(CTestTestPrintLabels PROPERTIES LABELS "Label1;Label2") set_tests_properties(CTestTestPrintLabels PROPERTIES PASS_REGULAR_EXPRESSION diff --git a/Tests/CTestLimitDashJ/CMakeLists.txt b/Tests/CTestLimitDashJ/CMakeLists.txt new file mode 100644 index 000000000..0c5950c9d --- /dev/null +++ b/Tests/CTestLimitDashJ/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 2.8) +project(CTestLimitDashJ NONE) + +# This file demonstrates http://public.kitware.com/Bug/view.php?id=12904 +# when configured with CMake 2.8.10.2 and earlier, and when running +# "ctest -j 4" in the resulting build tree. This example is hard-coded +# to assume -j 4 just to reproduce the issue easily. Adjust the +# FAIL_REGULAR_EXPRESSION and PROCESSORS values to reproduce this problem +# with a different ctest -j value... + +if(EXISTS "${CMAKE_BINARY_DIR}/Testing/Temporary/CTestCostData.txt") + message(STATUS "Removing CTestCostData.txt to force ordering by COST PROPERTY value rather than prior run data") + file(REMOVE "${CMAKE_BINARY_DIR}/Testing/Temporary/CTestCostData.txt") +endif() + +include(CTest) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/CreateSleepDelete.cmake + ${CMAKE_CURRENT_BINARY_DIR}/CreateSleepDelete.cmake + @ONLY + ) + +foreach(n RANGE 1 100) + add_test(NAME t${n} + COMMAND ${CMAKE_CTEST_COMMAND} + -D basefilename=f${n} + -S ${CMAKE_CURRENT_BINARY_DIR}/CreateSleepDelete.cmake + ) + set_property(TEST t${n} PROPERTY FAIL_REGULAR_EXPRESSION "(c='[5-9]'|c='[1-9][0-9]+')") +endforeach() + +set_property(TEST t1 PROPERTY RUN_SERIAL 1) +set_property(TEST t1 PROPERTY PROCESSORS 4) + +set_property(TEST t51 PROPERTY RUN_SERIAL 1) +set_property(TEST t51 PROPERTY PROCESSORS 4) + +foreach(n RANGE 2 50) + set_property(TEST t${n} PROPERTY DEPENDS t1) +endforeach() +set_property(TEST t1 PROPERTY DEPENDS t51) +set_property(TEST t51 PROPERTY DEPENDS t100) + +foreach(n 50) + set_property(TEST t${n} PROPERTY COST 6) +endforeach() +foreach(n RANGE 52 99) + set_property(TEST t${n} PROPERTY COST 3) +endforeach() diff --git a/Tests/CTestLimitDashJ/CreateSleepDelete.cmake b/Tests/CTestLimitDashJ/CreateSleepDelete.cmake new file mode 100644 index 000000000..b09307feb --- /dev/null +++ b/Tests/CTestLimitDashJ/CreateSleepDelete.cmake @@ -0,0 +1,48 @@ +set(CTEST_RUN_CURRENT_SCRIPT 0) + +if(NOT DEFINED basefilename) + message(FATAL_ERROR "pass -Dbasefilename=f1") +endif() + +if(NOT DEFINED ext) + set(ext "jkqvxz") +endif() + +if(NOT DEFINED sleep_interval) + set(sleep_interval 1) +endif() + +get_filename_component(self_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) +set(filename "${self_dir}/${basefilename}.${ext}") + +# count files +file(GLOB f1 *.${ext}) +list(LENGTH f1 c1) +message("c='${c1}'") + +# write a new file +message("Writing file: filename='${filename}'") +file(WRITE "${filename}" "${filename}") + +# count files again +file(GLOB f2 *.${ext}) +list(LENGTH f2 c2) +message("c='${c2}'") + +# snooze +message("Sleeping: sleep_interval='${sleep_interval}'") +ctest_sleep(${sleep_interval}) + +# count files again +file(GLOB f3 *.${ext}) +list(LENGTH f3 c3) +message("c='${c3}'") + +# delete the file we wrote earlier +message("Removing file: filename='${filename}'") +file(REMOVE "${filename}") + +# count files again +file(GLOB f4 *.${ext}) +list(LENGTH f4 c4) +message("c='${c4}'") From 18a3195ad57cafd06851ecf4cb7265cab95cfa38 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 19 Nov 2012 22:47:30 +0100 Subject: [PATCH 053/131] Keep track of INCLUDE_DIRECTORIES as a vector of structs. The struct can keep track of where the include came from, which gives us proper backtraces. --- Source/cmGeneratorTarget.cxx | 40 +----- Source/cmMakefile.cxx | 90 +++++++------ Source/cmMakefile.h | 10 ++ Source/cmMakefileIncludeDirectoriesEntry.h | 28 ++++ Source/cmTarget.cxx | 125 +++++++++++++++++- Source/cmTarget.h | 4 + .../BadInvalidName1-stderr.txt | 4 +- .../BadInvalidName2-stderr.txt | 6 +- .../BadInvalidName3-stderr.txt | 6 +- .../BadInvalidName4-stderr.txt | 6 +- .../BadInvalidName5-stderr.txt | 4 +- .../BadInvalidName6-stderr.txt | 4 +- .../BadInvalidName7-stderr.txt | 4 +- .../BadInvalidName8-stderr.txt | 4 +- .../BadNonTarget-stderr.txt | 6 +- 15 files changed, 243 insertions(+), 98 deletions(-) create mode 100644 Source/cmMakefileIncludeDirectoriesEntry.h diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 55507ddf3..62ee26a22 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -252,45 +252,7 @@ const char* cmGeneratorTarget::GetCreateRuleVariable() std::vector cmGeneratorTarget::GetIncludeDirectories( const char *config) { - std::vector 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->Target, - &dagChecker), - includes); - - std::set uniqueIncludes; - std::vector orderedAndUniqueIncludes; - for(std::vector::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; + return this->Target->GetIncludeDirectories(config); } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index d943c450f..b432986a8 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1485,9 +1485,12 @@ void cmMakefile::InitializeFromParent() // Initialize definitions with the closure of the parent scope. this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure(); - // copy include paths - this->SetProperty("INCLUDE_DIRECTORIES", - parent->GetProperty("INCLUDE_DIRECTORIES")); + const std::vector parentIncludes = + parent->GetIncludeDirectoriesEntries(); + this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(), + parentIncludes.begin(), + parentIncludes.end()); + this->SystemIncludeDirectories = parent->SystemIncludeDirectories; // define flags @@ -1612,41 +1615,6 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath, } } -//---------------------------------------------------------------------------- -void AddStringToProperty(cmProperty *prop, const char* name, const char* s, - bool before) -{ - if (!prop) - { - return; - } - - // Don't worry about duplicates at this point. We eliminate them when - // we convert the property to a vector in GetIncludeDirectories. - - if (before) - { - const char *val = prop->GetValue(); - cmOStringStream oss; - - if(val && *val) - { - oss << s << ";" << val; - } - else - { - oss << s; - } - - std::string newVal = oss.str(); - prop->Set(name, newVal.c_str()); - } - else - { - prop->Append(name, s); - } -} - //---------------------------------------------------------------------------- void cmMakefile::AddIncludeDirectory(const char* inc, bool before) { @@ -1655,18 +1623,21 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before) return; } - // Directory property: - cmProperty *prop = - this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + std::vector::iterator position = + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(); + + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + IncludeDirectoriesEntry entry(inc, lfbt); + this->IncludeDirectoriesEntries.insert(position, entry); // Property on each target: for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end(); ++l) { cmTarget &t = l->second; - prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES"); - AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before); + t.InsertInclude(entry, before); } } @@ -3451,6 +3422,15 @@ void cmMakefile::SetProperty(const char* prop, const char* value) this->SetLinkDirectories(varArgsExpanded); return; } + if (propname == "INCLUDE_DIRECTORIES") + { + this->IncludeDirectoriesEntries.clear(); + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + IncludeDirectoriesEntry(value, lfbt)); + return; + } if ( propname == "INCLUDE_REGULAR_EXPRESSION" ) { @@ -3482,6 +3462,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value, // handle special props std::string propname = prop; + if (propname == "INCLUDE_DIRECTORIES") + { + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->IncludeDirectoriesEntries.push_back( + IncludeDirectoriesEntry(value, lfbt)); + return; + } if ( propname == "LINK_DIRECTORIES" ) { std::vector varArgsExpanded; @@ -3593,6 +3581,20 @@ const char *cmMakefile::GetProperty(const char* prop, output = str.str(); return output.c_str(); } + else if (!strcmp("INCLUDE_DIRECTORIES",prop)) + { + std::string sep; + for (std::vector::const_iterator + it = this->IncludeDirectoriesEntries.begin(), + end = this->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + output += sep; + output += it->Value; + sep = ";"; + } + return output.c_str(); + } bool chain = false; const char *retVal = diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index eff05d091..a85015fe6 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -22,6 +22,7 @@ #include "cmNewLineStyle.h" #include "cmGeneratorTarget.h" #include "cmake.h" +#include "cmMakefileIncludeDirectoriesEntry.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmSourceGroup.h" @@ -861,6 +862,13 @@ public: /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } + typedef cmMakefileIncludeDirectoriesEntry IncludeDirectoriesEntry; + + std::vector GetIncludeDirectoriesEntries() const + { + return this->IncludeDirectoriesEntries; + } + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -909,6 +917,8 @@ protected: std::vector HeaderFileExtensions; std::string DefineFlags; + std::vector IncludeDirectoriesEntries; + // Track the value of the computed DEFINITIONS property. void AddDefineFlag(const char*, std::string&); void RemoveDefineFlag(const char*, std::string::size_type, std::string&); diff --git a/Source/cmMakefileIncludeDirectoriesEntry.h b/Source/cmMakefileIncludeDirectoriesEntry.h new file mode 100644 index 000000000..f35642dfb --- /dev/null +++ b/Source/cmMakefileIncludeDirectoriesEntry.h @@ -0,0 +1,28 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2012 Stephen Kelly + + 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 cmMakefileIncludeDirectoriesEntry_h +#define cmMakefileIncludeDirectoriesEntry_h + +#include +#include "cmListFileCache.h" + +struct cmMakefileIncludeDirectoriesEntry { + cmMakefileIncludeDirectoriesEntry(const std::string &value, + const cmListFileBacktrace &bt) + : Value(value), Backtrace(bt) + {} + std::string Value; + cmListFileBacktrace Backtrace; +}; + +#endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e7b34ee42..0c6bb1c5f 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -21,6 +21,7 @@ #include "cmDocumentLocationUndefined.h" #include "cmListFileCache.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionDAGChecker.h" #include #include #include @@ -118,6 +119,14 @@ public: struct SourceEntry { std::vector Depends; }; typedef std::map SourceEntriesType; SourceEntriesType SourceEntries; + + struct IncludeDirectoriesEntry { + IncludeDirectoriesEntry(cmsys::auto_ptr cge) + : ge(cge) + {} + const cmsys::auto_ptr ge; + }; + std::vector IncludeDirectoriesEntries; }; //---------------------------------------------------------------------------- @@ -1392,8 +1401,14 @@ void cmTarget::SetMakefile(cmMakefile* mf) // Initialize the INCLUDE_DIRECTORIES property based on the current value // of the same directory property: - this->SetProperty("INCLUDE_DIRECTORIES", - this->Makefile->GetProperty("INCLUDE_DIRECTORIES")); + const std::vector parentIncludes = + this->Makefile->GetIncludeDirectoriesEntries(); + + for (std::vector::const_iterator it + = parentIncludes.begin(); it != parentIncludes.end(); ++it) + { + this->InsertInclude(*it); + } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) @@ -2445,6 +2460,20 @@ void cmTarget::GatherDependencies( const cmMakefile& mf, } } +//---------------------------------------------------------------------------- +void deleteAndClear( + std::vector &entries) +{ + for (std::vector::const_iterator + it = entries.begin(), + end = entries.end(); + it != end; ++it) + { + delete *it; + } + entries.clear(); +} + //---------------------------------------------------------------------------- void cmTarget::SetProperty(const char* prop, const char* value) { @@ -2453,6 +2482,16 @@ void cmTarget::SetProperty(const char* prop, const char* value) return; } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->IncludeDirectoriesEntries); + cmsys::auto_ptr cge = ge.Parse(value); + this->Internal->IncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(cge)); + return; + } this->Properties.SetProperty(prop, value, cmProperty::TARGET); this->MaybeInvalidatePropertyCache(prop); } @@ -2465,10 +2504,73 @@ void cmTarget::AppendProperty(const char* prop, const char* value, { return; } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + this->Internal->IncludeDirectoriesEntries.push_back( + new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); + return; + } this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); this->MaybeInvalidatePropertyCache(prop); } +//---------------------------------------------------------------------------- +void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector::iterator position + = before ? this->Internal->IncludeDirectoriesEntries.begin() + : this->Internal->IncludeDirectoriesEntries.end(); + + this->Internal->IncludeDirectoriesEntries.insert(position, + new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value))); +} + +//---------------------------------------------------------------------------- +std::vector cmTarget::GetIncludeDirectories(const char *config) +{ + std::vector includes; + std::set uniqueIncludes; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "INCLUDE_DIRECTORIES", 0, 0); + + for (std::vector::const_iterator + it = this->Internal->IncludeDirectoriesEntries.begin(), + end = this->Internal->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + std::vector entryIncludes; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker), + entryIncludes); + for(std::vector::const_iterator + li = entryIncludes.begin(); li != entryIncludes.end(); ++li) + { + std::string inc = *li; + if (!cmSystemTools::IsOff(inc.c_str())) + { + cmSystemTools::ConvertToUnixSlashes(inc); + } + + if(uniqueIncludes.insert(inc).second) + { + includes.push_back(*li); + } + } + } + return includes; +} + //---------------------------------------------------------------------------- void cmTarget::MaybeInvalidatePropertyCache(const char* prop) { @@ -2796,6 +2898,24 @@ const char *cmTarget::GetProperty(const char* prop, } } } + if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::IncludeDirectoriesEntry + IncludeDirectoriesEntry; + for (std::vector::const_iterator + it = this->Internal->IncludeDirectoriesEntries.begin(), + end = this->Internal->IncludeDirectoriesEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if (strcmp(prop,"IMPORTED") == 0) { @@ -4919,6 +5039,7 @@ cmTargetInternalPointer //---------------------------------------------------------------------------- cmTargetInternalPointer::~cmTargetInternalPointer() { + deleteAndClear(this->Pointer->IncludeDirectoriesEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 0dfbc68a1..3f3605043 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -15,6 +15,7 @@ #include "cmCustomCommand.h" #include "cmPropertyMap.h" #include "cmPolicies.h" +#include "cmMakefileIncludeDirectoriesEntry.h" #include @@ -470,6 +471,9 @@ public: /** @return the Mac framework directory without the base. */ std::string GetFrameworkDirectory(const char* config = 0); + std::vector GetIncludeDirectories(const char *config); + void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, + bool before = false); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt index 3287d19ac..9c146e057 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName1.cmake:7 \(include_directories\): Error evaluating generator expression: \$ Target name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt index e527e2275..451888cc6 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName2.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Target name and property name not supported.$ + Target name and property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt index 517debbca..39692c4ef 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName3.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Property name not supported.$ + Property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt index eab6fb690..c3aa1b1a9 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName4.cmake:9 \(include_directories\): Error evaluating generator expression: \$ - Property name not supported.$ + Property name not supported. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt index e2b4fc6fa..1c6fad4b0 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt @@ -1,7 +1,9 @@ -CMake Error: +CMake Error at BadInvalidName5.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty target name and property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt index e94f52fa2..8b147dca6 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName6.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty target name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt index 2548215f4..dad6bf86a 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName7.cmake:9 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt index 2a98f6f06..4e8c14c99 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadInvalidName8.cmake:7 \(include_directories\): Error evaluating generator expression: \$ \$ expression requires a non-empty property name. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt index d2ac7a963..3b3bab07d 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt @@ -1,6 +1,8 @@ -CMake Error: +CMake Error at BadNonTarget.cmake:7 \(include_directories\): Error evaluating generator expression: \$ - Target "NonExistant" not found.$ + Target "NonExistant" not found. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\)$ From 0941d6232a979a129a651915972ab7332c15550d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 18 Dec 2012 16:16:14 +0100 Subject: [PATCH 054/131] Add a way to print the origins of used include directories. --- Source/cmDocumentVariables.cxx | 9 ++++ Source/cmGeneratorExpression.h | 5 +++ Source/cmTarget.cxx | 27 ++++++++++++ .../DebugIncludes-result.txt | 1 + .../DebugIncludes-stderr.txt | 42 +++++++++++++++++++ .../include_directories/DebugIncludes.cmake | 38 +++++++++++++++++ .../include_directories/RunCMakeTest.cmake | 1 + 7 files changed, 123 insertions(+) create mode 100644 Tests/RunCMake/include_directories/DebugIncludes-result.txt create mode 100644 Tests/RunCMake/include_directories/DebugIncludes-stderr.txt create mode 100644 Tests/RunCMake/include_directories/DebugIncludes.cmake diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 32c543dce..d4a876d0a 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -896,6 +896,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) " script, it may get fatal error messages from the script.",false, "Variables That Change Behavior"); + cm->DefineProperty + ("CMAKE_DEBUG_TARGET_PROPERTIES", cmProperty::VARIABLE, + "Enables tracing output for target properties.", + "This variable can be populated with a list of properties to generate " + "debug output for when evaluating target properties. Currently it can " + "only be used when evaluating the INCLUDE_DIRECTORIES target property. " + "In that case, it outputs a backtrace for each include directory in " + "the build. Default is unset.",false,"Variables That Change Behavior"); + // Variables defined by CMake that describe the system cm->DefineProperty diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 961e53d75..15e637cb7 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -83,6 +83,11 @@ public: return this->Input; } + cmListFileBacktrace GetBacktrace() const + { + return this->Backtrace; + } + private: cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, const char *input); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0c6bb1c5f..58fab80cc 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2485,6 +2485,7 @@ void cmTarget::SetProperty(const char* prop, const char* value) if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) { cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); cmGeneratorExpression ge(lfbt); deleteAndClear(this->Internal->IncludeDirectoriesEntries); cmsys::auto_ptr cge = ge.Parse(value); @@ -2507,6 +2508,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value, if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) { cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); cmGeneratorExpression ge(lfbt); this->Internal->IncludeDirectoriesEntries.push_back( new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); @@ -2541,6 +2543,20 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this->GetName(), "INCLUDE_DIRECTORIES", 0, 0); + + std::vector debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugIncludes = std::find(debugProperties.begin(), + debugProperties.end(), + "INCLUDE_DIRECTORIES") + != debugProperties.end(); + for (std::vector::const_iterator it = this->Internal->IncludeDirectoriesEntries.begin(), end = this->Internal->IncludeDirectoriesEntries.end(); @@ -2553,6 +2569,7 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this, &dagChecker), entryIncludes); + std::string usedIncludes; for(std::vector::const_iterator li = entryIncludes.begin(); li != entryIncludes.end(); ++li) { @@ -2565,8 +2582,18 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) if(uniqueIncludes.insert(inc).second) { includes.push_back(*li); + if (debugIncludes) + { + usedIncludes += " * " + *li + "\n"; + } } } + if (!usedIncludes.empty()) + { + this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, + "Used includes:\n" + usedIncludes, + (*it)->ge->GetBacktrace()); + } } return includes; } diff --git a/Tests/RunCMake/include_directories/DebugIncludes-result.txt b/Tests/RunCMake/include_directories/DebugIncludes-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt new file mode 100644 index 000000000..948def117 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt @@ -0,0 +1,42 @@ +CMake Warning at DebugIncludes.cmake:8 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/one + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:8 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/two + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:13 \(set_property\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/three + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:18 \(include_directories\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/four + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning at DebugIncludes.cmake:25 \(set_property\): + Used includes: + + \* .*/Tests/RunCMake/include_directories/five + \* .*/Tests/RunCMake/include_directories/six + +Call Stack \(most recent call first\): + DebugIncludes.cmake:35 \(some_macro\) + DebugIncludes.cmake:38 \(some_function\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/include_directories/DebugIncludes.cmake b/Tests/RunCMake/include_directories/DebugIncludes.cmake new file mode 100644 index 000000000..51daf7480 --- /dev/null +++ b/Tests/RunCMake/include_directories/DebugIncludes.cmake @@ -0,0 +1,38 @@ + +project(DebugIncludes) + +set(CMAKE_DEBUG_TARGET_PROPERTIES INCLUDE_DIRECTORIES) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp" "enum { dummy };\n") + +include_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/one" + "${CMAKE_CURRENT_SOURCE_DIR}/two" +) + +set_property(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES + "${CMAKE_CURRENT_SOURCE_DIR}/three") + +add_library(lll "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp") + +include_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/two" + "${CMAKE_CURRENT_SOURCE_DIR}/three" + "${CMAKE_CURRENT_SOURCE_DIR}/four" +) + +macro(some_macro) + set_property(TARGET lll APPEND PROPERTY + INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/one" + "${CMAKE_CURRENT_SOURCE_DIR}/three" + "${CMAKE_CURRENT_SOURCE_DIR}/four" + "${CMAKE_CURRENT_SOURCE_DIR}/five" + "${CMAKE_CURRENT_SOURCE_DIR}/six" + ) +endmacro() + +function(some_function) + some_macro() +endfunction() + +some_function() diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake index aee3f799b..de3725226 100644 --- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake @@ -1,3 +1,4 @@ include(RunCMake) run_cmake(NotFoundContent) +run_cmake(DebugIncludes) From b6346f25565f06bde208b8303d70bbe0fabc8210 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 1 Jan 2013 18:35:28 +0100 Subject: [PATCH 055/131] Tests: Fix warning about unused variable Resolve this warning: ".../Tests/CMakeCommands/target_link_libraries/depB.cpp", line 8: warning: variable "a" was declared but never referenced DepA a; ^ --- Tests/CMakeCommands/target_link_libraries/depB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CMakeCommands/target_link_libraries/depB.cpp b/Tests/CMakeCommands/target_link_libraries/depB.cpp index 97e5be274..1bbe38bc2 100644 --- a/Tests/CMakeCommands/target_link_libraries/depB.cpp +++ b/Tests/CMakeCommands/target_link_libraries/depB.cpp @@ -7,5 +7,5 @@ int DepB::foo() { DepA a; - return 0; + return a.foo(); } From e767ffcda58ab73cf2c4394202eec7ae1f6035b5 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 3 Jan 2013 20:56:32 +0100 Subject: [PATCH 056/131] Don't crash when a target is expected but is not available. --- Source/cmGeneratorExpressionEvaluator.cxx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 3b7cfc03a..d86ae5497 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -18,6 +18,8 @@ #include +#include + //---------------------------------------------------------------------------- #if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510 static @@ -291,6 +293,17 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmTarget* target = context->Target; std::string propertyName = *parameters.begin(); + + if (!target && parameters.size() == 1) + { + reportError(context, content->GetOriginalExpression(), + "$ may only be used with targets. It may not " + "be used with add_custom_command. Specify the target to read a " + "property from using the $ signature " + "instead."); + return std::string(); + } + if (parameters.size() == 2) { if (parameters.begin()->empty() && parameters[1].empty()) @@ -351,6 +364,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return std::string(); } + assert(target); + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, target->GetName(), propertyName, From 95b74cafed4ba7ce572dc03b11e72d902f4df7ca Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 4 Jan 2013 00:01:13 -0500 Subject: [PATCH 057/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3badbd7c5..370c76bc8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130103) +set(CMake_VERSION_TWEAK 20130104) #set(CMake_VERSION_RC 1) From 51988a4f91c6c6a4b91eedfb5010fdbc57b71891 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jan 2013 09:38:22 -0500 Subject: [PATCH 058/131] add_library: Document object library portability suggestion Xcode and VS <= 7.1 will not build targets that have no source files besides $. Suggest in the documentation that projects always add at least one real source file. --- Source/cmAddLibraryCommand.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index c14456535..e5f27cb51 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -134,6 +134,10 @@ public: "They may contain custom commands generating such sources, but not " "PRE_BUILD, PRE_LINK, or POST_BUILD commands. " "Object libraries cannot be imported, exported, installed, or linked." + " " + "Some native build systems may not like targets that have only " + "object files, so consider adding at least one real source file " + "to any target that references $." ; } From b2f1700bc7caf12c3f28890ebe183ae09c90d7dc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 23 Sep 2012 13:16:44 +0200 Subject: [PATCH 059/131] GenEx: Add expressions to specify build- or install-only values This is for specifying INCLUDE_DIRECTORIES relevant to the build-location or the install location for example: set_property(TARGET foo PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$" "$" ) A 'bar' target can then use: set_property(TARGET bar PROPERTY INCLUDE_DIRECTORIES "$" ) and it will work whether foo is in the same project, or an imported target from an installation location, or an imported target from a build location generated by the export() command. Because the generator expressions are only evaluated at build-time, these new expressions are equivalent to the ZeroNode and OneNode. The GeneratorExpression test is split into parts. Some shells can't run the custom command as it is getting too long. --- Source/cmDocumentGeneratorExpressions.h | 6 ++ Source/cmGeneratorExpression.cxx | 88 +++++++++++++++++-- Source/cmGeneratorExpression.h | 4 +- Source/cmGeneratorExpressionEvaluator.cxx | 10 +++ Tests/GeneratorExpression/CMakeLists.txt | 15 +++- Tests/GeneratorExpression/check-common.cmake | 5 ++ .../{check.cmake => check-part1.cmake} | 28 +----- Tests/GeneratorExpression/check-part2.cmake | 26 ++++++ 8 files changed, 144 insertions(+), 38 deletions(-) create mode 100644 Tests/GeneratorExpression/check-common.cmake rename Tests/GeneratorExpression/{check.cmake => check-part1.cmake} (60%) create mode 100644 Tests/GeneratorExpression/check-part2.cmake diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 445fd0e12..19270120f 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -26,6 +26,12 @@ "strings which contain a '>' for example.\n" \ " $ = A literal ','. Used to compare " \ "strings which contain a ',' for example.\n" \ + " $ = content of \"...\" when the property " \ + "is exported using install(EXPORT), and empty otherwise.\n" \ + " $ = content of \"...\" when the property " \ + "is exported using export(), or when the target is used by another " \ + "target in the same buildsystem. Expands to the empty string " \ + "otherwise.\n" \ " $ = main file (.exe, .so.1.2, .a)\n" \ " $ = file used to link (.a, .lib, .so)\n" \ " $ = file with soname (.so.3)\n" \ diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 3fd4a5f8e..841fbb780 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -123,15 +123,9 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() } } -std::string cmGeneratorExpression::Preprocess(const std::string &input, - PreprocessContext context) +//---------------------------------------------------------------------------- +static std::string stripAllGeneratorExpressions(const std::string &input) { - 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; @@ -170,3 +164,81 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input, result += input.substr(lastPos); return result; } + +//---------------------------------------------------------------------------- +static std::string stripExportInterface(const std::string &input, + cmGeneratorExpression::PreprocessContext context) +{ + std::string result; + + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + while((pos = input.find("$') + { + --nestingLevel; + if (nestingLevel != 0) + { + continue; + } + if(context == cmGeneratorExpression::BuildInterface + && !gotInstallInterface) + { + result += input.substr(pos, c - cStart); + } + else if(context == cmGeneratorExpression::InstallInterface + && gotInstallInterface) + { + result += input.substr(pos, c - cStart); + } + break; + } + } + const std::string::size_type traversed = (c - cStart) + 1; + if (!*c) + { + result += std::string(gotInstallInterface ? "$ Parse(const char* input); enum PreprocessContext { - StripAllGeneratorExpressions + StripAllGeneratorExpressions, + BuildInterface, + InstallInterface }; static std::string Preprocess(const std::string &input, diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 3b7cfc03a..e20e203e6 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -95,6 +95,12 @@ static const struct OneNode : public cmGeneratorExpressionNode } } oneNode; +//---------------------------------------------------------------------------- +static const struct OneNode buildInterfaceNode; + +//---------------------------------------------------------------------------- +static const struct ZeroNode installInterfaceNode; + //---------------------------------------------------------------------------- #define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \ static const struct OP ## Node : public cmGeneratorExpressionNode \ @@ -593,6 +599,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &commaNode; else if (identifier == "TARGET_PROPERTY") return &targetPropertyNode; + else if (identifier == "BUILD_INTERFACE") + return &buildInterfaceNode; + else if (identifier == "INSTALL_INTERFACE") + return &installInterfaceNode; return 0; } diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 3a92d81b1..db6fb7479 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.8.8) project(GeneratorExpression NONE) -add_custom_target(check ALL +add_custom_target(check-part1 ALL COMMAND ${CMAKE_COMMAND} -Dtest_0=$<0:nothing> -Dtest_0_with_comma=$<0:-Wl,--no-undefined> @@ -57,6 +57,13 @@ add_custom_target(check ALL -Dtest_colons_3=$<1:Qt5::Core> -Dtest_colons_4=$<1:C:\\CMake> -Dtest_colons_5=$<1:C:/CMake> + -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part1.cmake + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 2)" + VERBATIM + ) + +add_custom_target(check-part2 ALL + COMMAND ${CMAKE_COMMAND} -Dtest_incomplete_1=$< -Dtest_incomplete_2=$ -Dtest_incomplete_20=$ -Dtest_incomplete_21=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake - COMMAND ${CMAKE_COMMAND} -E echo "check done" + -Dtest_build_interface=$ + -Dtest_install_interface=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)" VERBATIM ) diff --git a/Tests/GeneratorExpression/check-common.cmake b/Tests/GeneratorExpression/check-common.cmake new file mode 100644 index 000000000..8ffebd740 --- /dev/null +++ b/Tests/GeneratorExpression/check-common.cmake @@ -0,0 +1,5 @@ +macro(check var val) + if(NOT "${${var}}" STREQUAL "${val}") + message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"") + endif() +endmacro() diff --git a/Tests/GeneratorExpression/check.cmake b/Tests/GeneratorExpression/check-part1.cmake similarity index 60% rename from Tests/GeneratorExpression/check.cmake rename to Tests/GeneratorExpression/check-part1.cmake index af436de9e..7abfa823f 100644 --- a/Tests/GeneratorExpression/check.cmake +++ b/Tests/GeneratorExpression/check-part1.cmake @@ -1,8 +1,5 @@ -macro(check var val) - if(NOT "${${var}}" STREQUAL "${val}") - message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"") - endif() -endmacro() + +include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake) message(STATUS "config=[${config}]") check(test_0 "") @@ -57,24 +54,3 @@ check(test_colons_2 "::") check(test_colons_3 "Qt5::Core") check(test_colons_4 "C:\\\\CMake") check(test_colons_5 "C:/CMake") -check(test_incomplete_1 "$<") -check(test_incomplete_2 "$") -check(test_incomplete_6 "") -check(test_incomplete_7 "$") -check(test_incomplete_15 "$") -check(test_incomplete_20 "$") -check(test_incomplete_21 "$") diff --git a/Tests/GeneratorExpression/check-part2.cmake b/Tests/GeneratorExpression/check-part2.cmake new file mode 100644 index 000000000..149a658e3 --- /dev/null +++ b/Tests/GeneratorExpression/check-part2.cmake @@ -0,0 +1,26 @@ + +include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake) + +check(test_incomplete_1 "$<") +check(test_incomplete_2 "$") +check(test_incomplete_6 "") +check(test_incomplete_7 "$") +check(test_incomplete_15 "$") +check(test_incomplete_20 "$") +check(test_incomplete_21 "$") +check(test_build_interface "build") +check(test_install_interface "") From 77475fe61d0a1bbd562228bf66d5043bd001cb48 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 11:31:59 +0100 Subject: [PATCH 060/131] Allow generator expressions to require literals. --- Source/cmGeneratorExpressionEvaluator.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index e20e203e6..a67cad5b0 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -47,6 +47,8 @@ struct cmGeneratorExpressionNode virtual bool GeneratesContent() const { return true; } + virtual bool RequiresLiteralInput() const { return false; } + virtual bool AcceptsSingleArbitraryContentParameter() const { return false; } @@ -692,6 +694,15 @@ std::string GeneratorExpressionContent::Evaluate( = pit->end(); for ( ; it != end; ++it) { + if (node->RequiresLiteralInput()) + { + if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires literal input."); + return std::string(); + } + } result += (*it)->Evaluate(context, dagChecker); if (context->HadError) { @@ -699,6 +710,12 @@ std::string GeneratorExpressionContent::Evaluate( } } } + if (node->RequiresLiteralInput()) + { + std::vector parameters; + parameters.push_back(result); + return node->Evaluate(parameters, context, this, dagChecker); + } return result; } From b0c8f73eb62c5651b4a039f95676cae310bcada9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 11:33:23 +0100 Subject: [PATCH 061/131] Add the TARGET_NAME generator expression. It will be used as a preprocessing marker. --- Source/cmDocumentGeneratorExpressions.h | 4 ++++ Source/cmGeneratorExpressionEvaluator.cxx | 24 +++++++++++++++++++ Tests/GeneratorExpression/CMakeLists.txt | 2 ++ Tests/GeneratorExpression/check-part2.cmake | 2 ++ .../BadTargetName-result.txt | 1 + .../BadTargetName-stderr.txt | 8 +++++++ .../GeneratorExpression/BadTargetName.cmake | 3 +++ .../GeneratorExpression/RunCMakeTest.cmake | 1 + 8 files changed, 45 insertions(+) create mode 100644 Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt create mode 100644 Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/BadTargetName.cmake diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 19270120f..b8889ac20 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -26,6 +26,10 @@ "strings which contain a '>' for example.\n" \ " $ = A literal ','. Used to compare " \ "strings which contain a ',' for example.\n" \ + " $ = Marks ... as being the name of a " \ + "target. This is required if exporting targets to multiple " \ + "dependent export sets. The '...' must be a literal name of a " \ + "target- it may not contain generator expressions.\n" \ " $ = content of \"...\" when the property " \ "is exported using install(EXPORT), and empty otherwise.\n" \ " $ = content of \"...\" when the property " \ diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index a67cad5b0..c8f5b82d1 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -376,6 +376,28 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } } targetPropertyNode; +//---------------------------------------------------------------------------- +static const struct TargetNameNode : public cmGeneratorExpressionNode +{ + TargetNameNode() {} + + virtual bool GeneratesContent() const { return true; } + + virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } + virtual bool RequiresLiteralInput() const { return true; } + + std::string Evaluate(const std::vector ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return parameters.front(); + } + + virtual int NumExpectedParameters() const { return 1; } + +} targetNameNode; + //---------------------------------------------------------------------------- template struct TargetFilesystemArtifactResultCreator @@ -601,6 +623,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &commaNode; else if (identifier == "TARGET_PROPERTY") return &targetPropertyNode; + else if (identifier == "TARGET_NAME") + return &targetNameNode; else if (identifier == "BUILD_INTERFACE") return &buildInterfaceNode; else if (identifier == "INSTALL_INTERFACE") diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index db6fb7479..ecbbedf44 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -87,6 +87,8 @@ add_custom_target(check-part2 ALL -Dtest_incomplete_21=$ -Dtest_build_interface=$ -Dtest_install_interface=$ + -Dtest_target_name_1=$ + -Dtest_target_name_2=$ -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)" VERBATIM diff --git a/Tests/GeneratorExpression/check-part2.cmake b/Tests/GeneratorExpression/check-part2.cmake index 149a658e3..8855a977c 100644 --- a/Tests/GeneratorExpression/check-part2.cmake +++ b/Tests/GeneratorExpression/check-part2.cmake @@ -24,3 +24,5 @@ check(test_incomplete_20 "$") check(test_incomplete_21 "$") check(test_build_interface "build") check(test_install_interface "") +check(test_target_name_1 "tgt,ok") +check(test_target_name_2 "tgt:ok") diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt b/Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetName-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt new file mode 100644 index 000000000..969393acc --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetName-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at BadTargetName.cmake:1 \(add_custom_target\): + Error evaluating generator expression: + + \$> + + \$ expression requires literal input. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetName.cmake b/Tests/RunCMake/GeneratorExpression/BadTargetName.cmake new file mode 100644 index 000000000..e125cab42 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetName.cmake @@ -0,0 +1,3 @@ +add_custom_target(check ALL COMMAND check + $> + VERBATIM) diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index 992ba792f..8a6967594 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -6,3 +6,4 @@ run_cmake(BadAND) run_cmake(BadNOT) run_cmake(BadStrEqual) run_cmake(BadZero) +run_cmake(BadTargetName) From e04f737c7a3e66c49e2d50813af1fa40a415eff8 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 23:07:09 +0100 Subject: [PATCH 062/131] Add API to extract target names from a genex string. The TARGET_NAME expression, which requires a literal, provides target names. $ also provides target names in the cases where tgt is a literal, so that TARGET_NAME is not needed then in addition. --- Source/cmExportFileGenerator.cxx | 136 +++++++++++++++++++++++++++++++ Source/cmExportFileGenerator.h | 4 + 2 files changed, 140 insertions(+) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 3f738ccde..2507b72ab 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -124,6 +124,142 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, this->GenerateImportTargetsConfig(os, config, suffix); } +//---------------------------------------------------------------------------- +void +cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( + std::string &input, + cmTarget* target, + std::vector &missingTargets) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + cmMakefile *mf = target->GetMakefile(); + std::string errorString; + + while((pos = input.find("$", nameStartPos); + std::string::size_type commaPos = input.find(",", nameStartPos); + std::string::size_type nextOpenPos = input.find("$<", nameStartPos); + if (commaPos == input.npos // Implied 'this' target + || closePos == input.npos // Imcomplete expression. + || closePos < commaPos // Implied 'this' target + || nextOpenPos < commaPos) // Non-literal + { + lastPos = nameStartPos; + continue; + } + + const std::string targetName = input.substr(nameStartPos, + commaPos - nameStartPos); + + pos = nameStartPos; // We're not going to replace the entire expression, + // but only the target parameter. + if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) + { + if(tgt->IsImported()) + { + pos += targetName.size(); + } + else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input.replace(pos, targetName.size(), + this->Namespace + targetName); + pos += this->Namespace.size() + targetName.size(); + } + else + { + std::string namespacedTarget; + this->HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input.replace(pos, targetName.size(), namespacedTarget); + pos += namespacedTarget.size(); + } + } + } + else + { + errorString = "$ requires " + "its first parameter to be a reachable target."; + } + lastPos = pos; + if (!errorString.empty()) + { + break; + } + } + if (!errorString.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, errorString); + return; + } + + pos = 0; + lastPos = pos; + while((pos = input.find("$", nameStartPos); + if (endPos == input.npos) + { + errorString = "$ expression incomplete"; + } + const std::string targetName = input.substr(nameStartPos, + endPos - nameStartPos); + if(targetName.find("$<", lastPos) != input.npos) + { + errorString = "$ requires its parameter to be a " + "literal."; + } + if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) + { + if(tgt->IsImported()) + { + input.replace(pos, sizeof("$ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input.replace(pos, sizeof("$Namespace + targetName); + pos += sizeof("$HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input.replace(pos, sizeof("$IssueMessage(cmake::FATAL_ERROR, errorString); + } +} + //---------------------------------------------------------------------------- void cmExportFileGenerator diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 4a75c52d5..0b89a642d 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -94,6 +94,10 @@ protected: cmTarget* depender, cmTarget* dependee) = 0; + void ResolveTargetsInGeneratorExpressions(std::string &input, + cmTarget* target, + std::vector &missingTargets); + // The namespace in which the exports are placed in the generated file. std::string Namespace; From 0c657dc637ca4da6861102c7306069ad157ec08d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 23:05:11 +0100 Subject: [PATCH 063/131] Add API to populate INTERFACE properties in exported targets. The INTERFACE properties need to be preprocessed for context (build location or install location) and to extract target names etc. --- Source/cmExportFileGenerator.cxx | 59 ++++++++++++++++++++++++++++++++ Source/cmExportFileGenerator.h | 15 ++++++++ 2 files changed, 74 insertions(+) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 2507b72ab..2b133be09 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -124,6 +124,65 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, this->GenerateImportTargetsConfig(os, config, suffix); } +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + const char *outputName, + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector &missingTargets) +{ + const char *input = target->GetProperty(propName); + if (input) + { + if (!*input) + { + // Set to empty + properties[outputName] = ""; + return; + } + + std::string prepro = cmGeneratorExpression::Preprocess(input, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets); + properties[outputName] = prepro; + } + } +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector &missingTargets) +{ + this->PopulateInterfaceProperty(propName, propName, target, preprocessRule, + properties, missingTargets); +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, + std::ostream& os, + const ImportPropertyMap &properties) +{ + if (!properties.empty()) + { + std::string targetName = this->Namespace; + targetName += target->GetName(); + os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; + for(ImportPropertyMap::const_iterator pi = properties.begin(); + pi != properties.end(); ++pi) + { + os << " " << pi->first << " \"" << pi->second << "\"\n"; + } + os << ")\n\n"; + } +} + //---------------------------------------------------------------------------- void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 0b89a642d..7c58ad8b4 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -13,6 +13,7 @@ #define cmExportFileGenerator_h #include "cmCommand.h" +#include "cmGeneratorExpression.h" /** \class cmExportFileGenerator * \brief Generate a file exporting targets from a build or install tree. @@ -93,6 +94,13 @@ protected: cmMakefile* mf, cmTarget* depender, cmTarget* dependee) = 0; + void PopulateInterfaceProperty(const char *, + cmTarget *target, + cmGeneratorExpression::PreprocessContext, + ImportPropertyMap &properties, + std::vector &missingTargets); + void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, + const ImportPropertyMap &properties); void ResolveTargetsInGeneratorExpressions(std::string &input, cmTarget* target, @@ -113,6 +121,13 @@ protected: // The set of targets included in the export. std::set ExportedTargets; + +private: + void PopulateInterfaceProperty(const char *, const char *, + cmTarget *target, + cmGeneratorExpression::PreprocessContext, + ImportPropertyMap &properties, + std::vector &missingTargets); }; #endif From 26def1771dfbf502129212c9e728e34860477fac Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 6 Nov 2012 16:06:31 +0100 Subject: [PATCH 064/131] Make all relevant targets available in the genex context. The current node being evaluated transitively in the generator expression must be available to resolve mapped configs. --- Source/cmGeneratorExpression.cxx | 20 ++++++++++++++++++-- Source/cmGeneratorExpression.h | 7 ++++++- Source/cmGeneratorExpressionDAGChecker.cxx | 2 +- Source/cmGeneratorExpressionEvaluator.cxx | 2 +- Source/cmGeneratorExpressionEvaluator.h | 4 +++- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 841fbb780..6d003e10f 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -53,7 +53,22 @@ cmGeneratorExpression::~cmGeneratorExpression() //---------------------------------------------------------------------------- const char *cmCompiledGeneratorExpression::Evaluate( cmMakefile* mf, const char* config, bool quiet, - cmTarget *target, + cmTarget *headTarget, + cmGeneratorExpressionDAGChecker *dagChecker) const +{ + return this->Evaluate(mf, + config, + quiet, + headTarget, + headTarget, + dagChecker); +} + +//---------------------------------------------------------------------------- +const char *cmCompiledGeneratorExpression::Evaluate( + cmMakefile* mf, const char* config, bool quiet, + cmTarget *headTarget, + cmTarget *currentTarget, cmGeneratorExpressionDAGChecker *dagChecker) const { if (!this->NeedsParsing) @@ -73,7 +88,8 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Config = config; context.Quiet = quiet; context.HadError = false; - context.Target = target; + context.HeadTarget = headTarget; + context.CurrentTarget = currentTarget ? currentTarget : headTarget; context.Backtrace = this->Backtrace; for ( ; it != end; ++it) diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 99056a53a..dcdfefbad 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -71,8 +71,13 @@ class cmCompiledGeneratorExpression public: const char* Evaluate(cmMakefile* mf, const char* config, bool quiet = false, - cmTarget *target = 0, + cmTarget *headTarget = 0, + cmTarget *currentTarget = 0, cmGeneratorExpressionDAGChecker *dagChecker = 0) const; + const char* Evaluate(cmMakefile* mf, const char* config, + bool quiet, + cmTarget *headTarget, + cmGeneratorExpressionDAGChecker *dagChecker) const; /** Get set of targets found during evaluations. */ std::set const& GetTargets() const diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index bfb0ddf92..4a9fc28dc 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -57,7 +57,7 @@ void cmGeneratorExpressionDAGChecker::reportError( e << "Error evaluating generator expression:\n" << " " << expr << "\n" << "Self reference on target \"" - << context->Target->GetName() << "\".\n"; + << context->HeadTarget->GetName() << "\".\n"; context->Makefile->GetCMakeInstance() ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), parent->Backtrace); diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index c8f5b82d1..4a7a034c0 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -297,7 +297,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmsys::RegularExpression propertyNameValidator; propertyNameValidator.compile("^[A-Za-z0-9_]+$"); - cmTarget* target = context->Target; + cmTarget* target = context->HeadTarget; std::string propertyName = *parameters.begin(); if (parameters.size() == 2) { diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index d904b027f..59804ff95 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -26,7 +26,9 @@ struct cmGeneratorExpressionContext std::set Targets; cmMakefile *Makefile; const char *Config; - cmTarget *Target; + cmTarget *HeadTarget; // The target whose property is being evaluated. + cmTarget *CurrentTarget; // The dependent of HeadTarget which appears + // directly or indirectly in the property. bool Quiet; bool HadError; }; From d0f950fdba88ac08d0e25e340fe558eba008810e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 23 Dec 2012 11:20:37 +0100 Subject: [PATCH 065/131] Use mapped config properties to evaluate $ --- Source/cmGeneratorExpressionEvaluator.cxx | 20 +- Source/cmTarget.cxx | 236 ++++++++++++---------- Source/cmTarget.h | 5 + 3 files changed, 147 insertions(+), 114 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 4a7a034c0..8b8b86084 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -265,8 +265,24 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode return parameters.front().empty() ? "1" : "0"; } - return cmsysString_strcasecmp(parameters.begin()->c_str(), - context->Config) == 0 ? "1" : "0"; + if (cmsysString_strcasecmp(parameters.begin()->c_str(), + context->Config) == 0) + { + return "1"; + } + + if (context->CurrentTarget + && context->CurrentTarget->IsImported()) + { + const char* loc = 0; + const char* imp = 0; + std::string suffix; + return context->CurrentTarget->GetMappedConfig(context->Config, + &loc, + &imp, + suffix) ? "1" : "0"; + } + return "0"; } } configurationTestNode; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 58fab80cc..d60979c0a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4365,6 +4365,128 @@ cmTarget::GetImportInfo(const char* config) return &i->second; } +bool cmTarget::GetMappedConfig(std::string const& desired_config, + const char** loc, + const char** imp, + std::string& suffix) +{ + // Track the configuration-specific property suffix. + suffix = "_"; + suffix += desired_config; + + std::vector mappedConfigs; + { + std::string mapProp = "MAP_IMPORTED_CONFIG_"; + mapProp += desired_config; + if(const char* mapValue = this->GetProperty(mapProp.c_str())) + { + cmSystemTools::ExpandListArgument(mapValue, mappedConfigs); + } + } + + // If we needed to find one of the mapped configurations but did not + // On a DLL platform there may be only IMPORTED_IMPLIB for a shared + // library or an executable with exports. + bool allowImp = this->HasImportLibrary(); + + // If a mapping was found, check its configurations. + for(std::vector::const_iterator mci = mappedConfigs.begin(); + !*loc && !*imp && mci != mappedConfigs.end(); ++mci) + { + // Look for this configuration. + std::string mcUpper = cmSystemTools::UpperCase(mci->c_str()); + std::string locProp = "IMPORTED_LOCATION_"; + locProp += mcUpper; + *loc = this->GetProperty(locProp.c_str()); + if(allowImp) + { + std::string impProp = "IMPORTED_IMPLIB_"; + impProp += mcUpper; + *imp = this->GetProperty(impProp.c_str()); + } + + // If it was found, use it for all properties below. + if(*loc || *imp) + { + suffix = "_"; + suffix += mcUpper; + } + } + + // If we needed to find one of the mapped configurations but did not + // then the target is not found. The project does not want any + // other configuration. + if(!mappedConfigs.empty() && !*loc && !*imp) + { + return false; + } + + // If we have not yet found it then there are no mapped + // configurations. Look for an exact-match. + if(!*loc && !*imp) + { + std::string locProp = "IMPORTED_LOCATION"; + locProp += suffix; + *loc = this->GetProperty(locProp.c_str()); + if(allowImp) + { + std::string impProp = "IMPORTED_IMPLIB"; + impProp += suffix; + *imp = this->GetProperty(impProp.c_str()); + } + } + + // If we have not yet found it then there are no mapped + // configurations and no exact match. + if(!*loc && !*imp) + { + // The suffix computed above is not useful. + suffix = ""; + + // Look for a configuration-less location. This may be set by + // manually-written code. + *loc = this->GetProperty("IMPORTED_LOCATION"); + if(allowImp) + { + *imp = this->GetProperty("IMPORTED_IMPLIB"); + } + } + + // If we have not yet found it then the project is willing to try + // any available configuration. + if(!*loc && !*imp) + { + std::vector availableConfigs; + if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) + { + cmSystemTools::ExpandListArgument(iconfigs, availableConfigs); + } + for(std::vector::const_iterator + aci = availableConfigs.begin(); + !*loc && !*imp && aci != availableConfigs.end(); ++aci) + { + suffix = "_"; + suffix += cmSystemTools::UpperCase(*aci); + std::string locProp = "IMPORTED_LOCATION"; + locProp += suffix; + *loc = this->GetProperty(locProp.c_str()); + if(allowImp) + { + std::string impProp = "IMPORTED_IMPLIB"; + impProp += suffix; + *imp = this->GetProperty(impProp.c_str()); + } + } + } + // If we have not yet found it then the target is not available. + if(!*loc && !*imp) + { + return false; + } + + return true; +} + //---------------------------------------------------------------------------- void cmTarget::ComputeImportInfo(std::string const& desired_config, ImportInfo& info) @@ -4376,120 +4498,10 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, // Initialize members. info.NoSOName = false; - // Track the configuration-specific property suffix. - std::string suffix = "_"; - suffix += desired_config; - - // On a DLL platform there may be only IMPORTED_IMPLIB for a shared - // library or an executable with exports. - bool allowImp = this->HasImportLibrary(); - - // Look for a mapping from the current project's configuration to - // the imported project's configuration. - std::vector mappedConfigs; - { - std::string mapProp = "MAP_IMPORTED_CONFIG_"; - mapProp += desired_config; - if(const char* mapValue = this->GetProperty(mapProp.c_str())) - { - cmSystemTools::ExpandListArgument(mapValue, mappedConfigs); - } - } - - // If a mapping was found, check its configurations. const char* loc = 0; const char* imp = 0; - for(std::vector::const_iterator mci = mappedConfigs.begin(); - !loc && !imp && mci != mappedConfigs.end(); ++mci) - { - // Look for this configuration. - std::string mcUpper = cmSystemTools::UpperCase(mci->c_str()); - std::string locProp = "IMPORTED_LOCATION_"; - locProp += mcUpper; - loc = this->GetProperty(locProp.c_str()); - if(allowImp) - { - std::string impProp = "IMPORTED_IMPLIB_"; - impProp += mcUpper; - imp = this->GetProperty(impProp.c_str()); - } - - // If it was found, use it for all properties below. - if(loc || imp) - { - suffix = "_"; - suffix += mcUpper; - } - } - - // If we needed to find one of the mapped configurations but did not - // then the target is not found. The project does not want any - // other configuration. - if(!mappedConfigs.empty() && !loc && !imp) - { - return; - } - - // If we have not yet found it then there are no mapped - // configurations. Look for an exact-match. - if(!loc && !imp) - { - std::string locProp = "IMPORTED_LOCATION"; - locProp += suffix; - loc = this->GetProperty(locProp.c_str()); - if(allowImp) - { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; - imp = this->GetProperty(impProp.c_str()); - } - } - - // If we have not yet found it then there are no mapped - // configurations and no exact match. - if(!loc && !imp) - { - // The suffix computed above is not useful. - suffix = ""; - - // Look for a configuration-less location. This may be set by - // manually-written code. - loc = this->GetProperty("IMPORTED_LOCATION"); - if(allowImp) - { - imp = this->GetProperty("IMPORTED_IMPLIB"); - } - } - - // If we have not yet found it then the project is willing to try - // any available configuration. - if(!loc && !imp) - { - std::vector availableConfigs; - if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) - { - cmSystemTools::ExpandListArgument(iconfigs, availableConfigs); - } - for(std::vector::const_iterator - aci = availableConfigs.begin(); - !loc && !imp && aci != availableConfigs.end(); ++aci) - { - suffix = "_"; - suffix += cmSystemTools::UpperCase(*aci); - std::string locProp = "IMPORTED_LOCATION"; - locProp += suffix; - loc = this->GetProperty(locProp.c_str()); - if(allowImp) - { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; - imp = this->GetProperty(impProp.c_str()); - } - } - } - - // If we have not yet found it then the target is not available. - if(!loc && !imp) + std::string suffix; + if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix)) { return; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3f3605043..52d5ca611 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -404,6 +404,11 @@ public: // Get the properties cmPropertyMap &GetProperties() { return this->Properties; }; + bool GetMappedConfig(std::string const& desired_config, + const char** loc, + const char** imp, + std::string& suffix); + // Define the properties static void DefineProperties(cmake *cm); From c67b8124f735e7f96567a276e16969607b300e43 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 21 Dec 2012 15:49:19 +0100 Subject: [PATCH 066/131] Make cycles in target properties ignored, not an error. Constructs such as these are an error as they are direct self-references: set_property(TARGET foo APPEND PROPERTY INCLUDE_DIRECTORIES $) set_property(TARGET foo APPEND PROPERTY INCLUDE_DIRECTORIES $) However, this is an indirect self-reference in a cycle, and not an error: set_property(TARGET foo APPEND PROPERTY INCLUDE_DIRECTORIES $) set_property(TARGET bar APPEND PROPERTY INCLUDE_DIRECTORIES $) --- Source/cmGeneratorExpressionDAGChecker.cxx | 16 +++++++++------- Source/cmGeneratorExpressionDAGChecker.h | 12 +++++++++--- Source/cmGeneratorExpressionEvaluator.cxx | 8 +++++++- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 4a9fc28dc..2e5b5ae11 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -24,13 +24,14 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( : Parent(parent), Target(target), Property(property), Content(content), Backtrace(backtrace) { - this->IsDAG = this->isDAG(); + this->CheckResult = this->checkGraph(); } //---------------------------------------------------------------------------- -bool cmGeneratorExpressionDAGChecker::check() const +cmGeneratorExpressionDAGChecker::Result +cmGeneratorExpressionDAGChecker::check() const { - return this->IsDAG; + return this->CheckResult; } //---------------------------------------------------------------------------- @@ -38,7 +39,7 @@ void cmGeneratorExpressionDAGChecker::reportError( cmGeneratorExpressionContext *context, const std::string &expr) { - if (this->IsDAG) + if (this->CheckResult == DAG) { return; } @@ -91,16 +92,17 @@ void cmGeneratorExpressionDAGChecker::reportError( } //---------------------------------------------------------------------------- -bool cmGeneratorExpressionDAGChecker::isDAG() const +cmGeneratorExpressionDAGChecker::Result +cmGeneratorExpressionDAGChecker::checkGraph() const { const cmGeneratorExpressionDAGChecker *parent = this->Parent; while (parent) { if (this->Target == parent->Target && this->Property == parent->Property) { - return false; + return parent->Parent ? CYCLIC_REFERENCE : SELF_REFERENCE; } parent = parent->Parent; } - return true; + return DAG; } diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index ffc84f8fd..48f26ed38 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -25,12 +25,18 @@ struct cmGeneratorExpressionDAGChecker const GeneratorExpressionContent *content, cmGeneratorExpressionDAGChecker *parent); - bool check() const; + enum Result { + DAG, + SELF_REFERENCE, + CYCLIC_REFERENCE + }; + + Result check() const; void reportError(cmGeneratorExpressionContext *context, const std::string &expr); private: - bool isDAG() const; + Result checkGraph() const; private: const cmGeneratorExpressionDAGChecker * const Parent; @@ -38,7 +44,7 @@ private: const std::string Property; const GeneratorExpressionContent * const Content; const cmListFileBacktrace Backtrace; - bool IsDAG; + Result CheckResult; }; #endif diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 8b8b86084..4b44ebee3 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -381,10 +381,16 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode content, dagCheckerParent); - if (!dagChecker.check()) + switch (dagChecker.check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: dagChecker.reportError(context, content->GetOriginalExpression()); return std::string(); + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return std::string(); + case cmGeneratorExpressionDAGChecker::DAG: + break; } const char *prop = target->GetProperty(propertyName.c_str()); From f5b1980fb27fa902d37856ec3e22daddfeb9d52f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 30 Dec 2012 22:06:12 +0100 Subject: [PATCH 067/131] Populate the ExportedTargets member early in GenerateMainFile The member variable is checked to determine whether to call HandleMissingTarget(). As that could be called during the loop in the comming commits, ensure that it contains all targets being exported. --- Source/cmExportBuildFileGenerator.cxx | 25 ++++++++++++++----------- Source/cmExportInstallFileGenerator.cxx | 25 ++++++++++++++----------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index cd6a7ab9e..3e9a9fd7f 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -22,6 +22,7 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator() //---------------------------------------------------------------------------- bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { + std::vector allTargets; { std::string expectedTargets; std::string sep; @@ -31,20 +32,10 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { expectedTargets += sep + this->Namespace + (*tei)->GetName(); sep = " "; - } - - this->GenerateExpectedTargetsCode(os, expectedTargets); - } - - // Create all the imported targets. - for(std::vector::const_iterator - tei = this->Exports->begin(); - tei != this->Exports->end(); ++tei) - { cmTarget* te = *tei; if(this->ExportedTargets.insert(te).second) { - this->GenerateImportTargetCode(os, te); + allTargets.push_back(te); } else { @@ -58,6 +49,18 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) } } + this->GenerateExpectedTargetsCode(os, expectedTargets); + } + + // Create all the imported targets. + for(std::vector::const_iterator + tei = allTargets.begin(); + tei != allTargets.end(); ++tei) + { + cmTarget* te = *tei; + this->GenerateImportTargetCode(os, te); + } + // Generate import file content for each configuration. for(std::vector::const_iterator ci = this->Configurations.begin(); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 6ba7d9fc2..2b7937e53 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -39,6 +39,7 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob() //---------------------------------------------------------------------------- bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) { + std::vector allTargets; { std::string expectedTargets; std::string sep; @@ -48,20 +49,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) { expectedTargets += sep + this->Namespace + (*tei)->Target->GetName(); sep = " "; - } - - this->GenerateExpectedTargetsCode(os, expectedTargets); - } - - // Create all the imported targets. - for(std::vector::const_iterator - tei = this->IEGen->GetExportSet()->GetTargetExports()->begin(); - tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) - { cmTargetExport const* te = *tei; if(this->ExportedTargets.insert(te->Target).second) { - this->GenerateImportTargetCode(os, te->Target); + allTargets.push_back(te->Target); } else { @@ -75,6 +66,18 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) } } + this->GenerateExpectedTargetsCode(os, expectedTargets); + } + + // Create all the imported targets. + for(std::vector::const_iterator + tei = allTargets.begin(); + tei != allTargets.end(); ++tei) + { + cmTarget* te = *tei; + this->GenerateImportTargetCode(os, te); + } + // Now load per-configuration properties for them. os << "# Load information for each installed configuration.\n" << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n" From 894f52f32d96ae92df0ba3dac2a70fe9c87e818d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 23 Sep 2012 13:45:17 +0200 Subject: [PATCH 068/131] Handle INTERFACE properties transitively for includes and defines. Contextually, the behavior is as if the properties content from another target is included in the string and then the result is evaluated. --- Source/cmExportBuildFileGenerator.cxx | 15 ++++ Source/cmExportInstallFileGenerator.cxx | 17 +++++ Source/cmGeneratorExpressionEvaluator.cxx | 30 +++++++- Source/cmTarget.cxx | 22 ++++++ Tests/ExportImport/Export/CMakeLists.txt | 75 ++++++++++++++++++- Tests/ExportImport/Export/testLibDepends.c | 16 ++++ Tests/ExportImport/Import/A/CMakeLists.txt | 15 ++++ Tests/ExportImport/Import/A/deps_iface.cpp | 24 ++++++ .../TargetIncludeDirectories/CMakeLists.txt | 31 ++++++++ 9 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 Tests/ExportImport/Import/A/deps_iface.cpp diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 3e9a9fd7f..9533319e9 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -52,6 +52,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateExpectedTargetsCode(os, expectedTargets); } + std::vector missingTargets; + // Create all the imported targets. for(std::vector::const_iterator tei = allTargets.begin(); @@ -59,8 +61,21 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { cmTarget* te = *tei; this->GenerateImportTargetCode(os, te); + + ImportPropertyMap properties; + + this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + + this->GenerateInterfaceProperties(te, os, properties); } + this->GenerateMissingTargetsCheckCode(os, missingTargets); + // Generate import file content for each configuration. for(std::vector::const_iterator ci = this->Configurations.begin(); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 2b7937e53..bc953c9c1 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -69,6 +69,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateExpectedTargetsCode(os, expectedTargets); } + std::vector missingTargets; + // Create all the imported targets. for(std::vector::const_iterator tei = allTargets.begin(); @@ -76,8 +78,23 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) { cmTarget* te = *tei; this->GenerateImportTargetCode(os, te); + + ImportPropertyMap properties; + + this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + + this->GenerateInterfaceProperties(te, os, properties); } + this->GenerateMissingTargetsCheckCode(os, missingTargets); + // Now load per-configuration properties for them. os << "# Load information for each installed configuration.\n" << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n" diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 4b44ebee3..b7ce15578 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -286,6 +286,13 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode } } configurationTestNode; + +//---------------------------------------------------------------------------- +static const char* targetPropertyTransitiveWhitelist[] = { + "INTERFACE_INCLUDE_DIRECTORIES" + , "INTERFACE_COMPILE_DEFINITIONS" +}; + //---------------------------------------------------------------------------- static const struct TargetPropertyNode : public cmGeneratorExpressionNode { @@ -394,7 +401,28 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } const char *prop = target->GetProperty(propertyName.c_str()); - return prop ? prop : ""; + if (!prop) + { + return std::string(); + } + + for (size_t i = 0; + i < (sizeof(targetPropertyTransitiveWhitelist) / + sizeof(*targetPropertyTransitiveWhitelist)); + ++i) + { + if (targetPropertyTransitiveWhitelist[i] == propertyName) + { + cmGeneratorExpression ge(context->Backtrace); + return ge.Parse(prop)->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + &dagChecker); + } + } + return prop; } } targetPropertyNode; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index d60979c0a..ca53a39d2 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -719,6 +719,28 @@ void cmTarget::DefineProperties(cmake *cm) "If set, this property completely overrides the generic property " "for the named configuration."); + cm->DefineProperty + ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET, + "List of public include directories for a library.", + "Targets may populate this property to publish the include directories " + "required to compile against the headers for the target. Consuming " + "targets can add entries to their own INCLUDE_DIRECTORIES property such " + "as $ to use the " + "include directories specified in the interface of 'foo'." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty + ("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET, + "List of public compile definitions for a library.", + "Targets may populate this property to publish the compile definitions " + "required to compile against the headers for the target. Consuming " + "targets can add entries to their own COMPILE_DEFINITIONS property such " + "as $ to use the " + "compile definitions specified in the interface of 'foo'." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + cm->DefineProperty ("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET, "Repetition count for STATIC libraries with cyclic dependencies.", diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index e19ab88de..569845a71 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -90,9 +90,82 @@ set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3) # Test exporting dependent libraries into different exports add_library(testLibRequired testLibRequired.c) add_library(testLibDepends testLibDepends.c) +set_property(TARGET testLibDepends APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) +set_property(TARGET testLibDepends APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) +set_property(TARGET testLibDepends APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + $ +) +set_property(TARGET testLibDepends APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS + $ +) target_link_libraries(testLibDepends testLibRequired) -install(TARGETS testLibRequired EXPORT RequiredExp DESTINATION lib ) +macro(add_include_lib _libName) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n") + add_library(${_libName} "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c") + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_libName}") + set_property(TARGET ${_libName} APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/${_libName}") + if (NOT "${ARGV1}" STREQUAL "NO_HEADER") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h" "// no content\n") + endif() +endmacro() + +add_include_lib(testLibIncludeRequired1) +add_include_lib(testLibIncludeRequired2) +add_include_lib(testLibIncludeRequired3 NO_HEADER) +# Generate testLibIncludeRequired4 in the testLibIncludeRequired3 directory +# with an error. If the includes from testLibIncludeRequired3 appear first, +# the error will be hit. +# Below, the '3' library appears before the '4' library +# but we are testing that the INSTALL_INTERFACE causes it not to be used +# at build time. +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired3/testLibIncludeRequired4.h" "#error Should not be included\n") +add_include_lib(testLibIncludeRequired4) +add_include_lib(testLibIncludeRequired5 NO_HEADER) +# Generate testLibIncludeRequired6 in the testLibIncludeRequired5 directory +# with an error. If the includes from testLibIncludeRequired5 appear first, +# the error will be hit. +# Below, the '5' library appears before the '6' library +# but we are testing that when the installed IMPORTED target is used, from +# the Import side of this unit test, the '6' include from the '5' directory +# will not be used because it is in the BUILD_INTERFACE only. +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired5/testLibIncludeRequired6.h" "#error Should not be included\n") +add_include_lib(testLibIncludeRequired6) + +set_property(TARGET testLibRequired APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + $ + $>,INTERFACE_INCLUDE_DIRECTORIES> + $> + $> + $> + $> +) + +set_property(TARGET testLibRequired APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS + testLibRequired_IFACE_DEFINE + $ + $ +) + +install(TARGETS testLibRequired + testLibIncludeRequired1 + testLibIncludeRequired2 + testLibIncludeRequired3 + testLibIncludeRequired4 + testLibIncludeRequired5 + testLibIncludeRequired6 + EXPORT RequiredExp DESTINATION lib ) install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired) install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib ) diff --git a/Tests/ExportImport/Export/testLibDepends.c b/Tests/ExportImport/Export/testLibDepends.c index 2849b336d..fb5a002e0 100644 --- a/Tests/ExportImport/Export/testLibDepends.c +++ b/Tests/ExportImport/Export/testLibDepends.c @@ -1,4 +1,20 @@ +#include "testLibIncludeRequired1.h" +#include "testLibIncludeRequired2.h" +#include "testLibIncludeRequired4.h" + +#ifndef testLibRequired_IFACE_DEFINE +#error Expected testLibRequired_IFACE_DEFINE +#endif + +#ifndef BuildOnly_DEFINE +#error Expected BuildOnly_DEFINE +#endif + +#ifdef InstallOnly_DEFINE +#error Unexpected InstallOnly_DEFINE +#endif + extern int testLibRequired(void); int testLibDepends(void) { return testLibRequired(); } diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 884179225..b77562ee6 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -152,3 +152,18 @@ check_function_exists(testLib1 HAVE_TESTLIB1_FUNCTION) if (NOT HAVE_TESTLIB1_FUNCTION) message(SEND_ERROR "Using imported target testLib2 in check_function_exists() failed !") endif() + +#----------------------------------------------------------------------------- +# Test that dependent imported targets have usable +# INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES + +add_library(deps_iface deps_iface.cpp) +target_link_libraries(deps_iface testLibsDepends) +set_property(TARGET deps_iface APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) +set_property(TARGET deps_iface APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) diff --git a/Tests/ExportImport/Import/A/deps_iface.cpp b/Tests/ExportImport/Import/A/deps_iface.cpp new file mode 100644 index 000000000..7190b9242 --- /dev/null +++ b/Tests/ExportImport/Import/A/deps_iface.cpp @@ -0,0 +1,24 @@ + +#include "testLibIncludeRequired1.h" +#include "testLibIncludeRequired2.h" +#include "testLibIncludeRequired6.h" + +#ifndef testLibRequired_IFACE_DEFINE +#error Expected testLibRequired_IFACE_DEFINE +#endif + +#ifdef BuildOnly_DEFINE +#error Unexpected BuildOnly_DEFINE +#endif + +#ifndef InstallOnly_DEFINE +#error Expected InstallOnly_DEFINE +#endif + +extern int testLibDepends(void); + + +int main(int,char **) +{ + return testLibDepends(); +} diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt index 7cb1b42e0..63a54925a 100644 --- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt @@ -37,6 +37,37 @@ include_directories("sing$<1:/ting>") include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/arguments;${CMAKE_CURRENT_BINARY_DIR}/list>") +create_header(fee) +create_header(fiy) +create_header(foh) +create_header(fum) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp" "#include \"fee.h\"\n") +add_library(lib1 "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp") +set_property(TARGET lib1 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fee") +set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy") +set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<$,EXECUTABLE>:${CMAKE_CURRENT_BINARY_DIR}/foh>") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp" "#include \"fiy.h\"\n") +add_library(lib2 "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp") +set_property(TARGET lib2 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fum;$") +set_property(TARGET lib2 APPEND PROPERTY INCLUDE_DIRECTORIES "$") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n#include \"fum.h\"\nint main(int,char**) { return 0; }\n") +add_executable(exe3 "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp") +set_property(TARGET exe3 APPEND PROPERTY INCLUDE_DIRECTORIES "$") + +# Test cycles +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n") +add_library(lib3 "${CMAKE_CURRENT_BINARY_DIR}/lib3.cpp") +set_property(TARGET lib3 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy;$") +set_property(TARGET lib3 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy;$") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n") +add_library(lib4 "${CMAKE_CURRENT_BINARY_DIR}/lib4.cpp") +set_property(TARGET lib4 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foh;$") +set_property(TARGET lib4 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foh;$") + add_library(somelib::withcolons UNKNOWN IMPORTED) set_property(TARGET somelib::withcolons PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/target") set_property(TARGET somelib::withcolons PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/target") From 0c1f291a27e3916a62c66d48b37b21e0e5d3ce6e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 5 Jan 2013 00:01:14 -0500 Subject: [PATCH 069/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 370c76bc8..17b2b25eb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130104) +set(CMake_VERSION_TWEAK 20130105) #set(CMake_VERSION_RC 1) From 76c44309717adf25ebe5892adc3b4181766868a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20K=C3=BCmmel?= Date: Sat, 5 Jan 2013 08:29:58 +0100 Subject: [PATCH 070/131] Ninja: fix building from Codeblocks GUI Many thx to Chuck Frayman BUG: 13652 --- Source/cmExtraCodeBlocksGenerator.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 25b13e52e..0cf9cbbf2 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -811,6 +811,11 @@ std::string cmExtraCodeBlocksGenerator::BuildMakeCommand( command += " VERBOSE=1 "; command += target; } + else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0) + { + command += " -v "; + command += target; + } else { std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); From 427ef824988a926fc7c7e948345929fcd359d6fb Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 6 Jan 2013 00:01:29 -0500 Subject: [PATCH 071/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 17b2b25eb..69de3dd43 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130105) +set(CMake_VERSION_TWEAK 20130106) #set(CMake_VERSION_RC 1) From c7550d5ef12d8185fad93d581ebd52474ae3d1b0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 7 Jan 2013 00:01:16 -0500 Subject: [PATCH 072/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 69de3dd43..a18fcf042 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130106) +set(CMake_VERSION_TWEAK 20130107) #set(CMake_VERSION_RC 1) From 09a0da77891bae3820b48c44c48bef3837b0a6e2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 7 Jan 2013 10:31:07 -0500 Subject: [PATCH 073/131] Revert "load_command: Deprecate and document pending removal" This reverts commit d2d43986e7f5013465473a71c393fc3897cecbac. We will add a policy to remove the command more gracefully. --- Source/cmLoadCommandCommand.cxx | 4 ---- Source/cmLoadCommandCommand.h | 15 +-------------- Tests/RunCMake/CMakeLists.txt | 1 - Tests/RunCMake/load_command/CMakeLists.txt | 3 --- .../load_command/LoadCommandDeprecated-stderr.txt | 6 ------ .../load_command/LoadCommandDeprecated.cmake | 1 - Tests/RunCMake/load_command/RunCMakeTest.cmake | 3 --- 7 files changed, 1 insertion(+), 32 deletions(-) delete mode 100644 Tests/RunCMake/load_command/CMakeLists.txt delete mode 100644 Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt delete mode 100644 Tests/RunCMake/load_command/LoadCommandDeprecated.cmake delete mode 100644 Tests/RunCMake/load_command/RunCMakeTest.cmake diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 181b922b1..b2acf06ad 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -224,10 +224,6 @@ cmLoadedCommand::~cmLoadedCommand() bool cmLoadCommandCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) { - this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, - "The \"load_command\" command will be removed in CMake 3.0. " - "See command documentation for details."); if(args.size() < 1 ) { return true; diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index bcd1831e4..f0b34ee59 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -47,7 +47,7 @@ public: */ virtual const char* GetTerseDocumentation() const { - return "Deprecated. Use macro() or function() instead."; + return "Load a command into a running CMake."; } /** @@ -56,13 +56,6 @@ public: virtual const char* GetFullDocumentation() const { return - "This command will be removed in CMake 3.0. " - "It works only when the target architecture matches the " - "running CMake binary. " - "Use macro() or function() to add commands. " - "Use execute_process() to run advanced computations " - "in external processes." - "\n" " load_command(COMMAND_NAME [loc2 ...])\n" "The given locations are searched for a library whose name is " "cmCOMMAND_NAME. If found, it is loaded as a module and the command " @@ -74,12 +67,6 @@ public: "Otherwise the variable will not be set."; } - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmLoadCommandCommand, cmCommand); }; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index a484983cd..3ea54f169 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -53,7 +53,6 @@ add_RunCMake_test(build_command) add_RunCMake_test(find_package) add_RunCMake_test(include) add_RunCMake_test(list) -add_RunCMake_test(load_command) if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]") add_RunCMake_test(include_external_msproject) diff --git a/Tests/RunCMake/load_command/CMakeLists.txt b/Tests/RunCMake/load_command/CMakeLists.txt deleted file mode 100644 index e8db6b05b..000000000 --- a/Tests/RunCMake/load_command/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(${RunCMake_TEST} NONE) -include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt b/Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt deleted file mode 100644 index 7d374b2d5..000000000 --- a/Tests/RunCMake/load_command/LoadCommandDeprecated-stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -CMake Warning \(dev\) at LoadCommandDeprecated.cmake:1 \(load_command\): - The "load_command" command will be removed in CMake 3.0. See command - documentation for details. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/load_command/LoadCommandDeprecated.cmake b/Tests/RunCMake/load_command/LoadCommandDeprecated.cmake deleted file mode 100644 index 9e9b1f464..000000000 --- a/Tests/RunCMake/load_command/LoadCommandDeprecated.cmake +++ /dev/null @@ -1 +0,0 @@ -load_command() diff --git a/Tests/RunCMake/load_command/RunCMakeTest.cmake b/Tests/RunCMake/load_command/RunCMakeTest.cmake deleted file mode 100644 index 9a0f98d52..000000000 --- a/Tests/RunCMake/load_command/RunCMakeTest.cmake +++ /dev/null @@ -1,3 +0,0 @@ -include(RunCMake) - -run_cmake(LoadCommandDeprecated) From b684b395812872184cbf10e0e0513e2a18546047 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 7 Jan 2013 11:31:52 -0500 Subject: [PATCH 074/131] VS11: Simplify external object file handling (#13831) Since commit 9a6ff950 (Fix for bug where VS2010 did not use .obj files as part of the build, 2011-04-01) and commit b291d9e7 (VS10: Fix external objects generated outside target, 2012-03-19) we try to detect whether an external object file is also a custom command output in the same target. This is because VS10 includes .obj custom command outputs on the link line by default. VS 11 supports a "false" setting in custom command rules to tell VS not to link the outputs. From the VS help: Specify whether the Inputs and output files with specific extensions (.obj, .lib, .res, .rsc) are passed to the linker. Treat all external object files the same and add "" settings for them. --- Source/cmVisualStudio10TargetGenerator.cxx | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ec9c125a9..2596d7340 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -572,6 +572,12 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, sep = ";"; } (*this->BuildFileStream ) << "\n"; + if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) + { + // VS >= 11 let us turn off linking of custom command outputs. + this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3); + (*this->BuildFileStream ) << "false\n"; + } } this->WriteString("\n", 2); } @@ -879,14 +885,23 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } } - for(std::vector::const_iterator - si = this->GeneratorTarget->ExternalObjects.begin(); - si != this->GeneratorTarget->ExternalObjects.end(); ++si) + if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) + { + // For VS >= 11 we use LinkObjects to avoid linking custom command + // outputs. Use Object for all external objects, generated or not. + this->WriteSources("Object", this->GeneratorTarget->ExternalObjects); + } + else { // If an object file is generated in this target, then vs10 will use // it in the build, and we have to list it as None instead of Object. - std::vector const* d = this->Target->GetSourceDepends(*si); - this->WriteSource((d && !d->empty())? "None":"Object", *si); + for(std::vector::const_iterator + si = this->GeneratorTarget->ExternalObjects.begin(); + si != this->GeneratorTarget->ExternalObjects.end(); ++si) + { + std::vector const* d=this->Target->GetSourceDepends(*si); + this->WriteSource((d && !d->empty())? "None":"Object", *si); + } } this->WriteSources("None", this->GeneratorTarget->ExtraSources); From 4b9ec00d0e175ec4cc7e1fbe6ed7d1dcbcfb25ba Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Mon, 7 Jan 2013 11:06:35 -0700 Subject: [PATCH 075/131] FindQt4: set QT_VERSION_* variables sooner. Set QT_VERSION_* variables sooner so they can be set before Qt4ConfigDependentSettings.cmake uses them. --- Modules/FindQt4.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index ea4d8f473..84196cce6 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -538,6 +538,11 @@ endif () if (QT_QMAKE_EXECUTABLE AND QTVERSION) + # set version variables + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" QT_VERSION_MAJOR "${QTVERSION}") + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" QT_VERSION_MINOR "${QTVERSION}") + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" QT_VERSION_PATCH "${QTVERSION}") + # ask qmake for the mkspecs directory # we do this first because QT_LIBINFIX might be set if (NOT QT_MKSPECS_DIR OR QT_QMAKE_CHANGED) @@ -1174,11 +1179,6 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) include("${_qt4_current_dir}/Qt4Macros.cmake") - # set version variables - string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" QT_VERSION_MAJOR "${QTVERSION}") - string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" QT_VERSION_MINOR "${QTVERSION}") - string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" QT_VERSION_PATCH "${QTVERSION}") - endif() #support old QT_MIN_VERSION if set, but not if version is supplied by find_package() From 57a67bf27efc286fffa883baad86c7d5d51834cc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 31 Dec 2012 09:41:09 +0100 Subject: [PATCH 076/131] Qt4: Add module dependencies to the IMPORTED targets This means for example, that consumers can use: target_link_libraries(foo ${QT_QTGUI_LIBRARIES}) instead of also needing to specify all 'public' dependencies: target_link_libraries(foo ${QT_QTGUI_LIBRARIES} ${QT_QTCORE_LIBRARIES} ) when using the IMPORTED targets. Also populate the IMPORTED_LINK_DEPENDENT_LIBRARIES property so CMake can help the linker find shared library dependencies. --- Modules/FindQt4.cmake | 55 +++++++++++++++++++++++++++++++++ Tests/CMakeLists.txt | 15 +++++++++ Tests/Qt4Targets/CMakeLists.txt | 14 +++++++++ Tests/Qt4Targets/main.cpp | 16 ++++++++++ 4 files changed, 100 insertions(+) create mode 100644 Tests/Qt4Targets/CMakeLists.txt create mode 100644 Tests/Qt4Targets/main.cpp diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index ea4d8f473..381141c5f 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -942,12 +942,36 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ############################################ + macro(_qt4_add_target_depends_internal _QT_MODULE _PROPERTY) + if (TARGET Qt4::${_QT_MODULE}) + foreach(_DEPEND ${ARGN}) + if (NOT TARGET Qt4::Qt${_DEPEND}) + message(FATAL_ERROR "_qt4_add_target_depends invoked with invalid arguments") + endif() + set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY + ${_PROPERTY} + "Qt4::Qt${_DEPEND}" + ) + endforeach() + endif() + endmacro() + + macro(_qt4_add_target_depends _QT_MODULE) + _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_INTERFACE_LIBRARIES ${ARGN}) + endmacro() + + macro(_qt4_add_target_private_depends _QT_MODULE) + _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_DEPENDENT_LIBRARIES ${ARGN}) + endmacro() + + # Set QT_xyz_LIBRARY variable and add # library include path to QT_INCLUDES _QT4_ADJUST_LIB_VARS(QtCore) foreach(QT_MODULE ${QT_MODULES}) _QT4_ADJUST_LIB_VARS(${QT_MODULE}) + _qt4_add_target_depends(${QT_MODULE} Core) endforeach() _QT4_ADJUST_LIB_VARS(QtAssistant) @@ -962,6 +986,37 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) _QT4_ADJUST_LIB_VARS(QAxContainer) endif() + # Only public dependencies are listed here. + # Eg, QtDBus links to QtXml, but users of QtDBus do not need to + # link to QtXml because QtDBus only uses it internally, not in public + # headers. + # Everything depends on QtCore, but that is covered above already + _qt4_add_target_depends(Qt3Support Sql Gui Network) + _qt4_add_target_depends(QtDeclarative Script Gui) + _qt4_add_target_depends(QtDesigner Gui) + _qt4_add_target_depends(QtHelp Gui) + _qt4_add_target_depends(QtMultimedia Gui) + _qt4_add_target_depends(QtOpenGL Gui) + _qt4_add_target_depends(QtSvg Gui) + _qt4_add_target_depends(QtWebKit Gui Network) + + _qt4_add_target_private_depends(Qt3Support Xml) + _qt4_add_target_private_depends(QtSvg Xml) + _qt4_add_target_private_depends(QtDBus Xml) + _qt4_add_target_private_depends(QtUiTools Xml Gui) + _qt4_add_target_private_depends(QtHelp Sql Xml Network) + _qt4_add_target_private_depends(QtXmlPatterns Network) + _qt4_add_target_private_depends(QtScriptTools Gui) + _qt4_add_target_private_depends(QtWebKit XmlPatterns) + _qt4_add_target_private_depends(QtDeclarative XmlPatterns Svg Sql Gui) + _qt4_add_target_private_depends(QtMultimedia Gui) + _qt4_add_target_private_depends(QtOpenGL Gui) + _qt4_add_target_private_depends(QAxServer Gui) + _qt4_add_target_private_depends(QAxContainer Gui) + _qt4_add_target_private_depends(phonon Gui) + if(QT_QTDBUS_FOUND) + _qt4_add_target_private_depends(phonon DBus) + endif() ####################################### # diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index f443b5b36..924ff38c1 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -989,6 +989,21 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomoc") endif() + if(QT4_WORKS AND QT_QTGUI_FOUND) + add_test(Qt4Targets ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Qt4Targets" + "${CMake_BINARY_DIR}/Tests/Qt4Targets" + --build-generator ${CMAKE_TEST_GENERATOR} + --build-project Qt4Targets + --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM} + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4Targets" + --force-new-ctest-process + --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + --test-command ${CMAKE_CTEST_COMMAND} -V + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Targets") + endif() add_test(ExternalProject ${CMAKE_CTEST_COMMAND} --build-and-test diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt new file mode 100644 index 000000000..3adff48fd --- /dev/null +++ b/Tests/Qt4Targets/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8) + +project(Qt4Targets) + +find_package(Qt4 REQUIRED) + +include_directories(${QT_INCLUDES}) + +add_executable(Qt4Targets WIN32 main.cpp) +target_link_libraries(Qt4Targets Qt4::QtGui) + +if (WIN32) + target_link_libraries(Qt4Targets Qt4::qtmain) +endif() diff --git a/Tests/Qt4Targets/main.cpp b/Tests/Qt4Targets/main.cpp new file mode 100644 index 000000000..f4890fa9e --- /dev/null +++ b/Tests/Qt4Targets/main.cpp @@ -0,0 +1,16 @@ + +#include +#include + +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QWidget w; + w.setWindowTitle(QString::fromLatin1("SomeTitle")); + w.show(); + + return 0; +} From 119bf4bf7f1db2aea6afb64fff471d6994cadf44 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 3 Jan 2013 19:56:54 +0100 Subject: [PATCH 077/131] Add test for custom command with a genex referring to a target. This test failed before d8a59ea4 (Port cmGeneratorExpression to cmTarget from cmGeneratorTarget, 2012-10-27), and passes after. --- .../TargetIncludeDirectories/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt index 7cb1b42e0..3044abd5e 100644 --- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt @@ -45,3 +45,9 @@ set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "$" ) + +add_custom_target(test_custom_target + "some_bogus_custom_tool" + $ + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}") From ed96d9a605471694465dd7142dd25748dfdf3a90 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 7 Jan 2013 21:09:18 +0100 Subject: [PATCH 078/131] bootstrap: use better defaults for Haiku These values are patched into that file by Haiku since 2.8.1. --- bootstrap | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bootstrap b/bootstrap index 643720c86..9a4f796fe 100755 --- a/bootstrap +++ b/bootstrap @@ -159,7 +159,9 @@ if ${cmake_system_mingw}; then cmake_default_prefix="c:/Program Files/CMake" fi elif ${cmake_system_haiku}; then - cmake_default_prefix=`/bin/finddir B_COMMON_DIRECTORY` + cmake_default_prefix=`finddir B_COMMON_DIRECTORY` + cmake_man_dir="/documentation/man" + cmake_doc_dir="/documentation/doc/cmake-${cmake_version}" else cmake_default_prefix="/usr/local" fi From 7a1b961de8b79416d168355e71f5af80fa4dbd02 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 7 Jan 2013 21:20:11 +0100 Subject: [PATCH 079/131] Haiku no longer defines __BEOS__ --- Modules/CheckForPthreads.c | 2 +- Source/CPack/cmCPackGeneratorFactory.cxx | 4 ++-- Source/cmCTest.cxx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/CheckForPthreads.c b/Modules/CheckForPthreads.c index 882dc21b7..7250fbff6 100644 --- a/Modules/CheckForPthreads.c +++ b/Modules/CheckForPthreads.c @@ -16,7 +16,7 @@ int main(int ac, char*av[]){ pthread_create(&tid[0], 0, runner, (void*)1); pthread_create(&tid[1], 0, runner, (void*)2); -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) // (no usleep on BeOS 5.) +#if defined(__BEOS__) && !defined(__ZETA__) // (no usleep on BeOS 5.) usleep(1); // for strange behavior on single-processor sun #endif diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 557767391..b36c2a2f8 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -33,7 +33,7 @@ #endif #if !defined(_WIN32) \ - && !defined(__QNXNTO__) && !defined(__BEOS__) + && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__) # include "cmCPackDebGenerator.h" # include "cmCPackRPMGenerator.h" #endif @@ -126,7 +126,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() } #endif #if !defined(_WIN32) \ - && !defined(__QNXNTO__) && !defined(__BEOS__) + && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__) if (cmCPackDebGenerator::CanGenerate()) { this->RegisterGenerator("DEB", "Debian packages", diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index bb6f3f29d..322a6a26f 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -53,7 +53,7 @@ #include #include -#if defined(__BEOS__) && !defined(__HAIKU__) +#if defined(__BEOS__) #include /* disable_debugger() API. */ #endif From 3d2e6a06874603ebe6152045c34de9147a0c11dc Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 7 Jan 2013 21:52:45 +0100 Subject: [PATCH 080/131] check for Haiku only with __HAIKU__ --- Modules/CMakeFortranCompilerId.F.in | 6 +----- Modules/CMakePlatformId.h.in | 5 +---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 4d25de0ba..f84852aeb 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -74,12 +74,8 @@ PRINT *, 'INFO:platform[IRIX]' #elif defined(__hpux) || defined(__hpux__) PRINT *, 'INFO:platform[HP-UX]' -#elif defined(__HAIKU) || defined(__HAIKU__) || defined(_HAIKU) +#elif defined(__HAIKU__) PRINT *, 'INFO:platform[Haiku]' -# if 0 -! Haiku also defines __BEOS__ so we must -! put it prior to the check for __BEOS__ -# endif #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) PRINT *, 'INFO:platform[BeOS]' #elif defined(__QNX__) || defined(__QNXNTO__) diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index c37341411..69171c2a3 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -35,11 +35,8 @@ #elif defined(__hpux) || defined(__hpux__) # define PLATFORM_ID "HP-UX" -#elif defined(__HAIKU) || defined(__HAIKU__) || defined(_HAIKU) +#elif defined(__HAIKU__) # define PLATFORM_ID "Haiku" -/* Haiku also defines __BEOS__ so we must - put it prior to the check for __BEOS__ -*/ #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) # define PLATFORM_ID "BeOS" From 50bfedf391a078e628bf1259f819da42dea1cde0 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 7 Jan 2013 23:26:18 +0100 Subject: [PATCH 081/131] FindLua51: do not try to link libm on BeOS This includes Haiku, which currently is treated as BeOS. The ComplexOneConfig test already knew about this. --- Modules/FindLua51.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindLua51.cmake b/Modules/FindLua51.cmake index 2d7ed3d6c..a2bf0c0ef 100644 --- a/Modules/FindLua51.cmake +++ b/Modules/FindLua51.cmake @@ -54,7 +54,7 @@ find_library(LUA_LIBRARY if(LUA_LIBRARY) # include the math library for Unix - if(UNIX AND NOT APPLE) + if(UNIX AND NOT APPLE AND NOT BEOS) find_library(LUA_MATH_LIBRARY m) set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") # For Windows and Mac, don't need to explicitly include the math library From 8e9630c719f59f69f813e3eb4a4f91ba2396b4ef Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 7 Jan 2013 23:57:07 +0100 Subject: [PATCH 082/131] FindGLUT: BeOS does not have libXi and libXmu --- Modules/FindGLUT.cmake | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 55790ae7c..843d1389f 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -40,25 +40,39 @@ else () set(GLUT_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX") else () + if (BEOS) + + set(_GLUT_INC_DIR /boot/develop/headers/os/opengl) + set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86) + + else() + + find_library( GLUT_Xi_LIBRARY Xi + /usr/openwin/lib + ) + + find_library( GLUT_Xmu_LIBRARY Xmu + /usr/openwin/lib + ) + + endif () + find_path( GLUT_INCLUDE_DIR GL/glut.h /usr/include/GL /usr/openwin/share/include /usr/openwin/include /opt/graphics/OpenGL/include /opt/graphics/OpenGL/contrib/libglut + ${_GLUT_INC_DIR} ) find_library( GLUT_glut_LIBRARY glut /usr/openwin/lib + ${_GLUT_glut_LIB_DIR} ) - find_library( GLUT_Xi_LIBRARY Xi - /usr/openwin/lib - ) - - find_library( GLUT_Xmu_LIBRARY Xmu - /usr/openwin/lib - ) + unset(_GLUT_INC_DIR) + unset(_GLUT_glut_LIB_DIR) endif () From 0380f36cd8dbdf7a89f8fac91d99235e75075bde Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Tue, 8 Jan 2013 00:38:08 +0100 Subject: [PATCH 083/131] FindOpenGL: add Haiku paths Also check the HP-UX specific paths only when on HP-UX. --- Modules/FindOpenGL.cmake | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake index 4a393f225..96c4d8db5 100644 --- a/Modules/FindOpenGL.cmake +++ b/Modules/FindOpenGL.cmake @@ -58,14 +58,22 @@ else () find_path(OPENGL_INCLUDE_DIR OpenGL/gl.h DOC "Include for OpenGL on OSX") else() - # Handle HP-UX cases where we only want to find OpenGL in either hpux64 - # or hpux32 depending on if we're doing a 64 bit build. - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(HPUX_IA_OPENGL_LIB_PATH /opt/graphics/OpenGL/lib/hpux32/) - else() - set(HPUX_IA_OPENGL_LIB_PATH - /opt/graphics/OpenGL/lib/hpux64/ - /opt/graphics/OpenGL/lib/pa20_64) + if (CMAKE_SYSTEM_NAME MATCHES "HP-UX") + # Handle HP-UX cases where we only want to find OpenGL in either hpux64 + # or hpux32 depending on if we're doing a 64 bit build. + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(_OPENGL_LIB_PATH + /opt/graphics/OpenGL/lib/hpux32/) + else() + set(_OPENGL_LIB_PATH + /opt/graphics/OpenGL/lib/hpux64/ + /opt/graphics/OpenGL/lib/pa20_64) + endif() + elseif(CMAKE_SYSTEM_NAME STREQUAL Haiku) + set(_OPENGL_LIB_PATH + /boot/develop/lib/x86) + set(_OPENGL_INCLUDE_PATH + /boot/develop/headers/os/opengl) endif() # The first line below is to make sure that the proper headers @@ -80,6 +88,7 @@ else () /usr/share/doc/NVIDIA_GLX-1.0/include /usr/openwin/share/include /opt/graphics/OpenGL/include /usr/X11R6/include + ${_OPENGL_INCLUDE_PATH} ) find_path(OPENGL_xmesa_INCLUDE_DIR GL/xmesa.h @@ -93,9 +102,12 @@ else () PATHS /opt/graphics/OpenGL/lib /usr/openwin/lib /usr/shlib /usr/X11R6/lib - ${HPUX_IA_OPENGL_LIB_PATH} + ${_OPENGL_LIB_PATH} ) + unset(_OPENGL_INCLUDE_PATH) + unset(_OPENGL_LIB_PATH) + # On Unix OpenGL most certainly always requires X11. # Feel free to tighten up these conditions if you don't # think this is always true. From 97758f29206a172524edd144e588558bb4a83700 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 8 Jan 2013 00:01:19 -0500 Subject: [PATCH 084/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a18fcf042..528fa13e6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130107) +set(CMake_VERSION_TWEAK 20130108) #set(CMake_VERSION_RC 1) From 495fa24d70ce4c5b594e15cae464af243a127fb8 Mon Sep 17 00:00:00 2001 From: KWSys Robot Date: Mon, 7 Jan 2013 10:20:26 -0500 Subject: [PATCH 085/131] KWSys 2013-01-07 (fc60c8b8) Extract upstream KWSys using the following shell commands. $ git archive --prefix=upstream-kwsys/ fc60c8b8 | tar x $ git shortlog --no-merges --abbrev=8 --format='%h %s' 8ce09af5..fc60c8b8 Brad King (3): cb5f835f SystemTools: Fix MakeDirectory with colon in path 1643507a IOStream: Fix check for compiler 'long long' support 34177aec SystemTools: Fix MakeDirectory after recent cleanup Rolf Eike Beer (24): 4da9894d SystemInformation: Clean up QuerySolarisInfo() 01392358 SystemInformation: don't attribute i386 Solaris systems to Sun 3db65ac1 SystemInformation: wrap the call to CPUID in a function 61bd9b42 SystemInformation: use the __cpuid compiler intrinsic if present 5932e7c0 SystemInformation: query memory size on Cygwin using sysconf() ea5612ed SystemInformation: count memory with _SC_PAGESIZE and _SC_PHYS_PAGES 3aca6642 SystemInformation: query memory size, CPU count, and CPU speed on BSD 3572c54d SystemInformation: count CPUs on HP-UX e6771b34 SystemInformation: determine CPU type on HP-UX 640210e5 SystemInformation: use /proc/cpuinfo only when present 5bdcfd10 SystemInformation: query total memory on AIX de69d547 SystemInformation: use intrinsic for RDTSC if supported 9808d4e7 SystemInformation: get CPU speed on Windows when RDTSC fails f4c625b5 tests: avoid truncation of testSystemInformation output in CDash 03d6fbe5 SystemInformation: get x86 CPU features from /proc/cpuinfo f8e917c1 SystemInformation: remove the #define CPUID_INSTRUCTION 59c4b5c5 SystemInformation: split Windows code out of QueryMemory() 200ee91f SystemInformation: split HP-UX code out of QueryMemory() 88217703 SystemInformation: split Linux code out of QueryMemory() 9e317872 SystemInformation: split AIX code out of QueryMemory() 349cee5b SystemInformation: remove useless zeroing from QueryMemory() 7271926e SystemInformation: split Cygwin code out of QueryMemory() 6da78ad1 SystemInformation: make QueryMemory() return bool 182179e9 Haiku no longer defines __BEOS__ Stephen Kelly (1): 247b8a3c SystemTools: Rename MakeCnidentifier() to MakeCidentifier() Change-Id: Ib95b5bddab7ecc0a4025ab29792426acf57e5623 --- CMakeLists.txt | 7 + IOStream.hxx.in | 6 +- ProcessUNIX.c | 4 - SystemInformation.cxx | 1185 +++++++++++++++++++------------------ SystemTools.cxx | 19 +- SystemTools.hxx.in | 9 +- testDynamicLoader.cxx | 2 +- testProcess.c | 2 +- testSystemInformation.cxx | 9 + 9 files changed, 641 insertions(+), 602 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ccdff1255..6bfcab040 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -596,6 +596,13 @@ IF(KWSYS_USE_SystemInformation) ENDIF() ENDIF() ENDIF() + IF(CMAKE_SYSTEM MATCHES "HP-UX") + CHECK_INCLUDE_FILES("sys/mpctl.h" KWSYS_SYS_HAS_MPCTL_H) + IF(KWSYS_SYS_HAS_MPCTL_H) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1) + ENDIF() + ENDIF() IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE) SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1) ENDIF() diff --git a/IOStream.hxx.in b/IOStream.hxx.in index 9eb99e058..2eeedf2ff 100644 --- a/IOStream.hxx.in +++ b/IOStream.hxx.in @@ -26,12 +26,9 @@ /* Whether ostream supports long long. */ #define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@ -/* Size of type long long and 0 if not available. */ -#define @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG @KWSYS_SIZEOF_LONG_LONG@ - /* Determine whether we need to define the streaming operators for long long or __int64. */ -#if @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG +#if @KWSYS_USE_LONG_LONG@ # if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \ !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG # define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1 @@ -136,7 +133,6 @@ operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamULL value) /* If building a C++ file in kwsys itself, give the source file access to the macros without a configured namespace. */ #if defined(KWSYS_NAMESPACE) -# define KWSYS_IOS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG # define KWSYS_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG # define KWSYS_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG # define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL diff --git a/ProcessUNIX.c b/ProcessUNIX.c index 19922111a..83838affc 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -63,10 +63,6 @@ do. #include /* DIR, dirent */ #include /* isspace */ -#ifdef __HAIKU__ -#undef __BEOS__ -#endif - #if defined(__VMS) # define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK #else diff --git a/SystemInformation.cxx b/SystemInformation.cxx index bfdb0edd6..0460b2906 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -86,6 +86,15 @@ typedef int siginfo_t; # endif #endif +#if defined(__OpenBSD__) || defined(__NetBSD__) +# include +# include +#endif + +#if defined(__DragonFly__) +# include +#endif + #ifdef __APPLE__ # include # include @@ -133,6 +142,9 @@ typedef struct rlimit ResourceLimitType; #elif defined( __hpux ) # include # include +# if defined(KWSYS_SYS_HAS_MPCTL_H) +# include +# endif #endif #ifdef __HAIKU__ @@ -173,6 +185,87 @@ typedef struct rlimit ResourceLimitType; # endif #endif +#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) +#define USE_ASM_INSTRUCTIONS 1 +#else +#define USE_ASM_INSTRUCTIONS 0 +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#include +#define USE_CPUID_INTRINSICS 1 +#else +#define USE_CPUID_INTRINSICS 0 +#endif + +#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS +# define USE_CPUID 1 +#else +# define USE_CPUID 0 +#endif + +#if USE_CPUID + +#define CPUID_AWARE_COMPILER + +/** + * call CPUID instruction + * + * Will return false if the instruction failed. + */ +static bool call_cpuid(int select, int result[4]) +{ +#if USE_CPUID_INTRINSICS + __cpuid(result, select); + return true; +#else + int tmp[4]; + // Use SEH to determine CPUID presence + __try { + _asm { +#ifdef CPUID_AWARE_COMPILER + ; we must push/pop the registers <> writes to, as the + ; optimiser doesn't know about <>, and so doesn't expect + ; these registers to change. + push eax + push ebx + push ecx + push edx +#endif + ; <> + mov eax, select +#ifdef CPUID_AWARE_COMPILER + cpuid +#else + _asm _emit 0x0f + _asm _emit 0xa2 +#endif + mov tmp[0 * TYPE int], eax + mov tmp[1 * TYPE int], ebx + mov tmp[2 * TYPE int], ecx + mov tmp[3 * TYPE int], edx + +#ifdef CPUID_AWARE_COMPILER + pop edx + pop ecx + pop ebx + pop eax +#endif + } + } + __except(1) + { + return false; + } + + memcpy(result, tmp, sizeof(tmp)); + // The cpuid instruction succeeded. + return true; +#endif +} +#endif + + namespace KWSYS_NAMESPACE { template @@ -336,13 +429,16 @@ protected: unsigned char LogicalCPUPerPhysicalCPU(); unsigned char GetAPICId(); unsigned int IsHyperThreadingSupported(); - LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); + static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For Linux and Cygwin, /proc/cpuinfo formats are slightly different - int RetreiveInformationFromCpuInfoFile(); + bool RetreiveInformationFromCpuInfoFile(); kwsys_stl::string ExtractValueFromCpuInfoFile(kwsys_stl::string buffer, const char* word, size_t init=0); + bool QueryLinuxMemory(); + bool QueryCygwinMemory(); + static void Delay (unsigned int); static void DelayOverhead (unsigned int); @@ -367,8 +463,24 @@ protected: bool QueryQNXMemory(); bool QueryQNXProcessor(); + //For OpenBSD, FreeBSD, NetBSD, DragonFly + bool QueryBSDMemory(); + bool QueryBSDProcessor(); + + //For HP-UX + bool QueryHPUXMemory(); + bool QueryHPUXProcessor(); + + //For Microsoft Windows + bool QueryWindowsMemory(); + + //For AIX + bool QueryAIXMemory(); + + bool QueryProcessor(); + // Evaluate the memory information. - int QueryMemory(); + bool QueryMemory(); size_t TotalVirtualMemory; size_t AvailableVirtualMemory; size_t TotalPhysicalMemory; @@ -695,24 +807,11 @@ void SystemInformation::RunMemoryCheck() // -------------------------------------------------------------- // SystemInformationImplementation starts here -#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) -#define USE_ASM_INSTRUCTIONS 1 -#else -#define USE_ASM_INSTRUCTIONS 0 -#endif - #define STORE_TLBCACHE_INFO(x,y) x = (x < y) ? y : x #define TLBCACHE_INFO_UNITS (15) #define CLASSICAL_CPU_FREQ_LOOP 10000000 #define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31 -#define CPUID_AWARE_COMPILER -#ifdef CPUID_AWARE_COMPILER - #define CPUID_INSTRUCTION cpuid -#else - #define CPUID_INSTRUCTION _asm _emit 0x0f _asm _emit 0xa2 -#endif - #define MMX_FEATURE 0x00000001 #define MMX_PLUS_FEATURE 0x00000002 #define SSE_FEATURE 0x00000004 @@ -1189,8 +1288,14 @@ void SystemInformationImplementation::RunCPUCheck() this->QueryHaikuInfo(); #elif defined(__QNX__) this->QueryQNXProcessor(); -#else +#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + this->QueryBSDProcessor(); +#elif defined(__hpux) + this->QueryHPUXProcessor(); +#elif defined(__linux) || defined(__CYGWIN__) this->RetreiveInformationFromCpuInfoFile(); +#else + this->QueryProcessor(); #endif } @@ -1209,6 +1314,18 @@ void SystemInformationImplementation::RunMemoryCheck() this->QueryHaikuInfo(); #elif defined(__QNX__) this->QueryQNXMemory(); +#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + this->QueryBSDMemory(); +#elif defined(__CYGWIN__) + this->QueryCygwinMemory(); +#elif defined(_WIN32) + this->QueryWindowsMemory(); +#elif defined(__hpux) + this->QueryHPUXMemory(); +#elif defined(__linux) + this->QueryLinuxMemory(); +#elif defined(_AIX) + this->QueryAIXMemory(); #else this->QueryMemory(); #endif @@ -1612,40 +1729,15 @@ void SystemInformationImplementation::Delay(unsigned int uiMS) bool SystemInformationImplementation::DoesCPUSupportCPUID() { +#if USE_CPUID + int dummy[4] = { 0, 0, 0, 0 }; + #if USE_ASM_INSTRUCTIONS - // Use SEH to determine CPUID presence - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx + return call_cpuid(0, dummy); +#else + call_cpuid(0, dummy); + return dummy[0] || dummy[1] || dummy[2] || dummy[3]; #endif - ; <> - mov eax, 0 - CPUID_INSTRUCTION - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) - { - // Stop the class from trying to use CPUID again! - return false; - } - - // The cpuid instruction succeeded. - return true; - #else // Assume no cpuid instruction. return false; @@ -1655,58 +1747,29 @@ bool SystemInformationImplementation::DoesCPUSupportCPUID() bool SystemInformationImplementation::RetrieveCPUFeatures() { -#if USE_ASM_INSTRUCTIONS - int localCPUFeatures = 0; - int localCPUAdvanced = 0; +#if USE_CPUID + int cpuinfo[4] = { 0, 0, 0, 0 }; - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID - ; edx: CPU feature flags - mov eax,1 - CPUID_INSTRUCTION - mov localCPUFeatures, edx - mov localCPUAdvanced, ebx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(1, cpuinfo)) { return false; } // Retrieve the features of CPU present. - this->Features.HasFPU = ((localCPUFeatures & 0x00000001) != 0); // FPU Present --> Bit 0 - this->Features.HasTSC = ((localCPUFeatures & 0x00000010) != 0); // TSC Present --> Bit 4 - this->Features.HasAPIC = ((localCPUFeatures & 0x00000200) != 0); // APIC Present --> Bit 9 - this->Features.HasMTRR = ((localCPUFeatures & 0x00001000) != 0); // MTRR Present --> Bit 12 - this->Features.HasCMOV = ((localCPUFeatures & 0x00008000) != 0); // CMOV Present --> Bit 15 - this->Features.HasSerial = ((localCPUFeatures & 0x00040000) != 0); // Serial Present --> Bit 18 - this->Features.HasACPI = ((localCPUFeatures & 0x00400000) != 0); // ACPI Capable --> Bit 22 - this->Features.HasMMX = ((localCPUFeatures & 0x00800000) != 0); // MMX Present --> Bit 23 - this->Features.HasSSE = ((localCPUFeatures & 0x02000000) != 0); // SSE Present --> Bit 25 - this->Features.HasSSE2 = ((localCPUFeatures & 0x04000000) != 0); // SSE2 Present --> Bit 26 - this->Features.HasThermal = ((localCPUFeatures & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29 - this->Features.HasIA64 = ((localCPUFeatures & 0x40000000) != 0); // IA64 Present --> Bit 30 + this->Features.HasFPU = ((cpuinfo[3] & 0x00000001) != 0); // FPU Present --> Bit 0 + this->Features.HasTSC = ((cpuinfo[3] & 0x00000010) != 0); // TSC Present --> Bit 4 + this->Features.HasAPIC = ((cpuinfo[3] & 0x00000200) != 0); // APIC Present --> Bit 9 + this->Features.HasMTRR = ((cpuinfo[3] & 0x00001000) != 0); // MTRR Present --> Bit 12 + this->Features.HasCMOV = ((cpuinfo[3] & 0x00008000) != 0); // CMOV Present --> Bit 15 + this->Features.HasSerial = ((cpuinfo[3] & 0x00040000) != 0); // Serial Present --> Bit 18 + this->Features.HasACPI = ((cpuinfo[3] & 0x00400000) != 0); // ACPI Capable --> Bit 22 + this->Features.HasMMX = ((cpuinfo[3] & 0x00800000) != 0); // MMX Present --> Bit 23 + this->Features.HasSSE = ((cpuinfo[3] & 0x02000000) != 0); // SSE Present --> Bit 25 + this->Features.HasSSE2 = ((cpuinfo[3] & 0x04000000) != 0); // SSE2 Present --> Bit 26 + this->Features.HasThermal = ((cpuinfo[3] & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29 + this->Features.HasIA64 = ((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30 +#if USE_ASM_INSTRUCTIONS // Retrieve extended SSE capabilities if SSE is available. if (this->Features.HasSSE) { @@ -1735,17 +1798,20 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() // Set the advanced SSE capabilities to not available. this->Features.HasSSEFP = false; } +#else + this->Features.HasSSEFP = false; +#endif // Retrieve Intel specific extended features. if (this->ChipManufacturer == Intel) { - this->Features.ExtendedFeatures.SupportsHyperthreading = ((localCPUFeatures & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28 - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((localCPUAdvanced & 0x00FF0000) >> 16) : 1; + this->Features.ExtendedFeatures.SupportsHyperthreading = ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28 + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((cpuinfo[1] & 0x00FF0000) >> 16) : 1; if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && (this->Features.HasAPIC)) { // Retrieve APIC information if there is one present. - this->Features.ExtendedFeatures.APIC_ID = ((localCPUAdvanced & 0xFF000000) >> 24); + this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24); } } @@ -1773,6 +1839,7 @@ void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& else if (this->ChipID.Vendor == "Geode By NSC") this->ChipManufacturer = NSC; // National Semiconductor else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics + else if (this->ChipID.Vendor == "Hewlett-Packard") this->ChipManufacturer = HP; // Hewlett-Packard else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer @@ -1782,71 +1849,41 @@ void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& /** */ bool SystemInformationImplementation::RetrieveCPUIdentity() { -#if USE_ASM_INSTRUCTIONS - int localCPUVendor[3]; - int localCPUSignature; +#if USE_CPUID + int localCPUVendor[4]; + int localCPUSignature[4]; - // Use assembly to detect CPUID information... - __try + if (!call_cpuid(0, localCPUVendor)) { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0 --> eax: maximum value of CPUID instruction. - ; ebx: part 1 of 3; CPU signature. - ; edx: part 2 of 3; CPU signature. - ; ecx: part 3 of 3; CPU signature. - mov eax, 0 - CPUID_INSTRUCTION - mov localCPUVendor[0 * TYPE int], ebx - mov localCPUVendor[1 * TYPE int], edx - mov localCPUVendor[2 * TYPE int], ecx - - ; <> - ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID - ; edx: CPU feature flags - mov eax,1 - CPUID_INSTRUCTION - mov localCPUSignature, eax - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif + return false; } - } - __except(1) + if (!call_cpuid(1, localCPUSignature)) { return false; } // Process the returned information. + // ; eax = 0 --> eax: maximum value of CPUID instruction. + // ; ebx: part 1 of 3; CPU signature. + // ; edx: part 2 of 3; CPU signature. + // ; ecx: part 3 of 3; CPU signature. char vbuf[13]; - memcpy (&(vbuf[0]), &(localCPUVendor[0]), sizeof (int)); - memcpy (&(vbuf[4]), &(localCPUVendor[1]), sizeof (int)); + memcpy (&(vbuf[0]), &(localCPUVendor[1]), sizeof (int)); + memcpy (&(vbuf[4]), &(localCPUVendor[3]), sizeof (int)); memcpy (&(vbuf[8]), &(localCPUVendor[2]), sizeof (int)); vbuf[12] = '\0'; this->ChipID.Vendor = vbuf; // Retrieve the family of CPU present. - this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used - this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used - this->ChipID.Type = ((localCPUSignature & 0x0000F000) >> 12); // Bits 15..12 Used - this->ChipID.Family = ((localCPUSignature & 0x00000F00) >> 8); // Bits 11..8 Used - this->ChipID.Model = ((localCPUSignature & 0x000000F0) >> 4); // Bits 7..4 Used - this->ChipID.Revision = ((localCPUSignature & 0x0000000F) >> 0); // Bits 3..0 Used + // ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision + // ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID + // ; edx: CPU feature flags + this->ChipID.ExtendedFamily = ((localCPUSignature[0] & 0x0FF00000) >> 20); // Bits 27..20 Used + this->ChipID.ExtendedModel = ((localCPUSignature[0] & 0x000F0000) >> 16); // Bits 19..16 Used + this->ChipID.Type = ((localCPUSignature[0] & 0x0000F000) >> 12); // Bits 15..12 Used + this->ChipID.Family = ((localCPUSignature[0] & 0x00000F00) >> 8); // Bits 11..8 Used + this->ChipID.Model = ((localCPUSignature[0] & 0x000000F0) >> 4); // Bits 7..4 Used + this->ChipID.Revision = ((localCPUSignature[0] & 0x0000000F) >> 0); // Bits 3..0 Used return true; @@ -1859,48 +1896,14 @@ bool SystemInformationImplementation::RetrieveCPUIdentity() /** */ bool SystemInformationImplementation::RetrieveCPUCacheDetails() { -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID int L1Cache[4] = { 0, 0, 0, 0 }; int L2Cache[4] = { 0, 0, 0, 0 }; // Check to see if what we are about to do is supported... if (RetrieveCPUExtendedLevelSupport (0x80000005)) { - // Use assembly to retrieve the L1 cache information ... - __try - { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000005 --> eax: L1 cache information - Part 1 of 4. - ; ebx: L1 cache information - Part 2 of 4. - ; edx: L1 cache information - Part 3 of 4. - ; ecx: L1 cache information - Part 4 of 4. - mov eax, 0x80000005 - CPUID_INSTRUCTION - mov L1Cache[0 * TYPE int], eax - mov L1Cache[1 * TYPE int], ebx - mov L1Cache[2 * TYPE int], ecx - mov L1Cache[3 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000005, L1Cache)) { return false; } @@ -1917,41 +1920,7 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails() // Check to see if what we are about to do is supported... if (RetrieveCPUExtendedLevelSupport (0x80000006)) { - // Use assembly to retrieve the L2 cache information ... - __try - { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000006 --> eax: L2 cache information - Part 1 of 4. - ; ebx: L2 cache information - Part 2 of 4. - ; edx: L2 cache information - Part 3 of 4. - ; ecx: L2 cache information - Part 4 of 4. - mov eax, 0x80000006 - CPUID_INSTRUCTION - mov L2Cache[0 * TYPE int], eax - mov L2Cache[1 * TYPE int], ebx - mov L2Cache[2 * TYPE int], ecx - mov L2Cache[3 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000006, L2Cache)) { return false; } @@ -1977,7 +1946,7 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails() /** */ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails() { -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1; int TLBCacheData[4] = { 0, 0, 0, 0 }; int TLBPassCounter = 0; @@ -1985,39 +1954,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails() do { - // Use assembly to retrieve the L2 cache information ... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 2 --> eax: TLB and cache information - Part 1 of 4. - ; ebx: TLB and cache information - Part 2 of 4. - ; ecx: TLB and cache information - Part 3 of 4. - ; edx: TLB and cache information - Part 4 of 4. - mov eax, 2 - CPUID_INSTRUCTION - mov TLBCacheData[0 * TYPE int], eax - mov TLBCacheData[1 * TYPE int], ebx - mov TLBCacheData[2 * TYPE int], ecx - mov TLBCacheData[3 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(2, TLBCacheData)) { return false; } @@ -2184,11 +2121,40 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() bool retrieved = false; #if defined(_WIN32) - // First of all we check to see if the RDTSC (0x0F, 0x31) instruction is - // supported. If not, we fallback to trying to read this value from the - // registry: - // - if (!this->Features.HasTSC) + unsigned int uiRepetitions = 1; + unsigned int uiMSecPerRepetition = 50; + __int64 i64Total = 0; + __int64 i64Overhead = 0; + + // Check if the TSC implementation works at all + if (this->Features.HasTSC && + GetCyclesDifference(SystemInformationImplementation::Delay, + uiMSecPerRepetition) > 0) + { + for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) + { + i64Total += GetCyclesDifference (SystemInformationImplementation::Delay, + uiMSecPerRepetition); + i64Overhead += + GetCyclesDifference (SystemInformationImplementation::DelayOverhead, + uiMSecPerRepetition); + } + + // Calculate the MHz speed. + i64Total -= i64Overhead; + i64Total /= uiRepetitions; + i64Total /= uiMSecPerRepetition; + i64Total /= 1000; + + // Save the CPU speed. + this->CPUSpeedInMHz = (float) i64Total; + + retrieved = true; + } + + // If RDTSC is not supported, we fallback to trying to read this value + // from the registry: + if (!retrieved) { HKEY hKey = NULL; LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, @@ -2213,34 +2179,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() RegCloseKey(hKey); hKey = NULL; } - - return retrieved; } - - unsigned int uiRepetitions = 1; - unsigned int uiMSecPerRepetition = 50; - __int64 i64Total = 0; - __int64 i64Overhead = 0; - - for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) - { - i64Total += GetCyclesDifference (SystemInformationImplementation::Delay, - uiMSecPerRepetition); - i64Overhead += - GetCyclesDifference (SystemInformationImplementation::DelayOverhead, - uiMSecPerRepetition); - } - - // Calculate the MHz speed. - i64Total -= i64Overhead; - i64Total /= uiRepetitions; - i64Total /= uiMSecPerRepetition; - i64Total /= 1000; - - // Save the CPU speed. - this->CPUSpeedInMHz = (float) i64Total; - - retrieved = true; #endif return retrieved; @@ -2312,7 +2251,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed() /** */ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULevelToCheck) { - int MaxCPUExtendedLevel = 0; + int cpuinfo[4] = { 0, 0, 0, 0 }; // The extended CPUID is supported by various vendors starting with the following CPU models: // @@ -2355,35 +2294,8 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev } } -#if USE_ASM_INSTRUCTIONS - - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000000 --> eax: maximum supported extended level - mov eax,0x80000000 - CPUID_INSTRUCTION - mov MaxCPUExtendedLevel, eax - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) +#if USE_CPUID + if (!call_cpuid(0x80000000, cpuinfo)) { return false; } @@ -2391,7 +2303,7 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev // Now we have to check the level wanted vs level returned... int nLevelWanted = (CPULevelToCheck & 0x7FFFFFFF); - int nLevelReturn = (MaxCPUExtendedLevel & 0x7FFFFFFF); + int nLevelReturn = (cpuinfo[0] & 0x7FFFFFFF); // Check to see if the level provided is supported... if (nLevelWanted > nLevelReturn) @@ -2419,60 +2331,30 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures() return false; } -#if USE_ASM_INSTRUCTIONS - int localCPUExtendedFeatures = 0; +#if USE_CPUID + int localCPUExtendedFeatures[4] = { 0, 0, 0, 0 }; - // Use assembly to detect CPUID information... - __try - { - _asm - { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision - ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID - ; edx: CPU feature flags - mov eax,0x80000001 - CPUID_INSTRUCTION - mov localCPUExtendedFeatures, edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000001, localCPUExtendedFeatures)) { return false; } // Retrieve the extended features of CPU present. - this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures & 0x80000000) != 0); // 3DNow Present --> Bit 31. - this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30. - this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures & 0x00400000) != 0); // SSE MMX Present --> Bit 22. - this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures & 0x00080000) != 0); // MP Capable -- > Bit 19. + this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures[3] & 0x80000000) != 0); // 3DNow Present --> Bit 31. + this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures[3] & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30. + this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // SSE MMX Present --> Bit 22. + this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures[3] & 0x00080000) != 0); // MP Capable -- > Bit 19. // Retrieve AMD specific extended features. if (this->ChipManufacturer == AMD) { - this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22 + this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22 } // Retrieve Cyrix specific extended features. if (this->ChipManufacturer == Cyrix) { - this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24 + this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24 } return true; @@ -2492,51 +2374,20 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber() return false; } -#if USE_ASM_INSTRUCTIONS - int SerialNumber[3]; +#if USE_CPUID + int SerialNumber[4]; - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!? - ; ecx: middle 32 bits are the processor signature bits - ; edx: bottom 32 bits are the processor signature bits - mov eax, 3 - CPUID_INSTRUCTION - mov SerialNumber[0 * TYPE int], ebx - mov SerialNumber[1 * TYPE int], ecx - mov SerialNumber[2 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(3, SerialNumber)) { return false; } // Process the returned information. + // ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!? + // ; ecx: middle 32 bits are the processor signature bits + // ; edx: bottom 32 bits are the processor signature bits char sn[128]; sprintf (sn, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x", - ((SerialNumber[0] & 0xff000000) >> 24), - ((SerialNumber[0] & 0x00ff0000) >> 16), - ((SerialNumber[0] & 0x0000ff00) >> 8), - ((SerialNumber[0] & 0x000000ff) >> 0), ((SerialNumber[1] & 0xff000000) >> 24), ((SerialNumber[1] & 0x00ff0000) >> 16), ((SerialNumber[1] & 0x0000ff00) >> 8), @@ -2544,7 +2395,11 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber() ((SerialNumber[2] & 0xff000000) >> 24), ((SerialNumber[2] & 0x00ff0000) >> 16), ((SerialNumber[2] & 0x0000ff00) >> 8), - ((SerialNumber[2] & 0x000000ff) >> 0)); + ((SerialNumber[2] & 0x000000ff) >> 0), + ((SerialNumber[3] & 0xff000000) >> 24), + ((SerialNumber[3] & 0x00ff0000) >> 16), + ((SerialNumber[3] & 0x0000ff00) >> 8), + ((SerialNumber[3] & 0x000000ff) >> 0)); this->ChipID.SerialNumber = sn; return true; @@ -2566,45 +2421,18 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement() return false; } -#if USE_ASM_INSTRUCTIONS - int localCPUPowerManagement = 0; +#if USE_CPUID + int localCPUPowerManagement[4] = { 0, 0, 0, 0 }; - - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000007 --> edx: get processor power management - mov eax,0x80000007 - CPUID_INSTRUCTION - mov localCPUPowerManagement, edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif - } - } - __except(1) + if (!call_cpuid(0x80000007, localCPUPowerManagement)) { return false; } // Check for the power management capabilities of the CPU. - this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement & 0x00000001) != 0); - this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement & 0x00000002) != 0); - this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement & 0x00000004) != 0); + this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement[3] & 0x00000001) != 0); + this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement[3] & 0x00000002) != 0); + this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement[3] & 0x00000004) != 0); return true; @@ -2634,57 +2462,18 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity() if (!RetrieveCPUExtendedLevelSupport(static_cast(0x80000004))) return false; -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID int CPUExtendedIdentity[12]; - // Use assembly to detect CPUID information... - __try { - _asm { -#ifdef CPUID_AWARE_COMPILER - ; we must push/pop the registers <> writes to, as the - ; optimiser doesn't know about <>, and so doesn't expect - ; these registers to change. - push eax - push ebx - push ecx - push edx -#endif - ; <> - ; eax = 0x80000002 --> eax, ebx, ecx, edx: get processor name string (part 1) - mov eax,0x80000002 - CPUID_INSTRUCTION - mov CPUExtendedIdentity[0 * TYPE int], eax - mov CPUExtendedIdentity[1 * TYPE int], ebx - mov CPUExtendedIdentity[2 * TYPE int], ecx - mov CPUExtendedIdentity[3 * TYPE int], edx - - ; <> - ; eax = 0x80000003 --> eax, ebx, ecx, edx: get processor name string (part 2) - mov eax,0x80000003 - CPUID_INSTRUCTION - mov CPUExtendedIdentity[4 * TYPE int], eax - mov CPUExtendedIdentity[5 * TYPE int], ebx - mov CPUExtendedIdentity[6 * TYPE int], ecx - mov CPUExtendedIdentity[7 * TYPE int], edx - - ; <> - ; eax = 0x80000004 --> eax, ebx, ecx, edx: get processor name string (part 3) - mov eax,0x80000004 - CPUID_INSTRUCTION - mov CPUExtendedIdentity[8 * TYPE int], eax - mov CPUExtendedIdentity[9 * TYPE int], ebx - mov CPUExtendedIdentity[10 * TYPE int], ecx - mov CPUExtendedIdentity[11 * TYPE int], edx - -#ifdef CPUID_AWARE_COMPILER - pop edx - pop ecx - pop ebx - pop eax -#endif + if (!call_cpuid(0x80000002, CPUExtendedIdentity)) + { + return false; } - } - __except(1) + if (!call_cpuid(0x80000003, CPUExtendedIdentity + 4)) + { + return false; + } + if (!call_cpuid(0x80000004, CPUExtendedIdentity + 8)) { return false; } @@ -3022,7 +2811,7 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k } /** Query for the cpu status */ -int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() +bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() { this->NumberOfLogicalCPU = 0; this->NumberOfPhysicalCPU = 0; @@ -3032,7 +2821,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if ( !fd ) { kwsys_ios::cout << "Problem opening /proc/cpuinfo" << kwsys_ios::endl; - return 0; + return false; } size_t fileSize = 0; @@ -3171,7 +2960,79 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->Features.L1CacheSize += atoi(cacheSize.c_str()); } } - return 1; + + // processor feature flags (probably x86 specific) + kwsys_stl::string cpuflags = this->ExtractValueFromCpuInfoFile(buffer,"flags"); + if(!cpurev.empty()) + { + // now we can match every flags as space + flag + space + cpuflags = " " + cpuflags + " "; + if ((cpuflags.find(" fpu ")!=kwsys_stl::string::npos)) + { + this->Features.HasFPU = true; + } + if ((cpuflags.find(" tsc ")!=kwsys_stl::string::npos)) + { + this->Features.HasTSC = true; + } + if ((cpuflags.find(" mmx ")!=kwsys_stl::string::npos)) + { + this->Features.HasMMX = true; + } + if ((cpuflags.find(" sse ")!=kwsys_stl::string::npos)) + { + this->Features.HasSSE = true; + } + if ((cpuflags.find(" sse2 ")!=kwsys_stl::string::npos)) + { + this->Features.HasSSE2 = true; + } + if ((cpuflags.find(" apic ")!=kwsys_stl::string::npos)) + { + this->Features.HasAPIC = true; + } + if ((cpuflags.find(" cmov ")!=kwsys_stl::string::npos)) + { + this->Features.HasCMOV = true; + } + if ((cpuflags.find(" mtrr ")!=kwsys_stl::string::npos)) + { + this->Features.HasMTRR = true; + } + if ((cpuflags.find(" acpi ")!=kwsys_stl::string::npos)) + { + this->Features.HasACPI = true; + } + if ((cpuflags.find(" 3dnow ")!=kwsys_stl::string::npos)) + { + this->Features.ExtendedFeatures.Has3DNow = true; + } + } + + return true; +} + +bool SystemInformationImplementation::QueryProcessor() +{ +#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) +// IRIX names this slightly different +# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN +#endif + +#ifdef _SC_NPROCESSORS_ONLN + long c = sysconf(_SC_NPROCESSORS_ONLN); + if (c <= 0) + { + return false; + } + + this->NumberOfPhysicalCPU = c; + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + + return true; +#else + return false; +#endif } /** @@ -3501,16 +3362,9 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) #endif } -/** Query for the memory status */ -int SystemInformationImplementation::QueryMemory() +bool SystemInformationImplementation::QueryWindowsMemory() { - this->TotalVirtualMemory = 0; - this->TotalPhysicalMemory = 0; - this->AvailableVirtualMemory = 0; - this->AvailablePhysicalMemory = 0; -#ifdef __CYGWIN__ - return 0; -#elif defined(_WIN32) +#if defined(_WIN32) # if defined(_MSC_VER) && _MSC_VER < 1300 MEMORYSTATUS ms; unsigned long tv, tp, av, ap; @@ -3535,8 +3389,15 @@ int SystemInformationImplementation::QueryMemory() this->TotalPhysicalMemory = tp>>10>>10; this->AvailableVirtualMemory = av>>10>>10; this->AvailablePhysicalMemory = ap>>10>>10; - return 1; -#elif defined(__linux) + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryLinuxMemory() +{ +#if defined(__linux) unsigned long tv=0; unsigned long tp=0; unsigned long av=0; @@ -3553,7 +3414,7 @@ int SystemInformationImplementation::QueryMemory() if( errorFlag!=0 ) { kwsys_ios::cout << "Problem calling uname(): " << strerror(errno) << kwsys_ios::endl; - return 0; + return false; } if( unameInfo.release!=0 && strlen(unameInfo.release)>=3 ) @@ -3577,7 +3438,7 @@ int SystemInformationImplementation::QueryMemory() if ( !fd ) { kwsys_ios::cout << "Problem opening /proc/meminfo" << kwsys_ios::endl; - return 0; + return false; } if( linuxMajor>=3 || ( (linuxMajor>=2) && (linuxMinor>=6) ) ) @@ -3616,7 +3477,7 @@ int SystemInformationImplementation::QueryMemory() { kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl; fclose(fd); - return 0; + return false; } } else @@ -3648,39 +3509,87 @@ int SystemInformationImplementation::QueryMemory() { kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl; fclose(fd); - return 0; + return false; } } fclose( fd ); - return 1; -#elif defined(__hpux) - unsigned long tv=0; - unsigned long tp=0; - unsigned long av=0; - unsigned long ap=0; - struct pst_static pst; - struct pst_dynamic pdy; - unsigned long ps = 0; - if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) != -1) - { - ps = pst.page_size; - tp = pst.physical_memory *ps; - tv = (pst.physical_memory + pst.pst_maxmem) * ps; - if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) != -1) - { - ap = tp - pdy.psd_rm * ps; - av = tv - pdy.psd_vm; - this->TotalVirtualMemory = tv>>10>>10; - this->TotalPhysicalMemory = tp>>10>>10; - this->AvailableVirtualMemory = av>>10>>10; - this->AvailablePhysicalMemory = ap>>10>>10; - return 1; - } - } - return 0; + return true; #else - return 0; + return false; +#endif +} + +bool SystemInformationImplementation::QueryCygwinMemory() +{ +#ifdef __CYGWIN__ + // _SC_PAGE_SIZE does return the mmap() granularity on Cygwin, + // see http://cygwin.com/ml/cygwin/2006-06/msg00350.html + // Therefore just use 4096 as the page size of Windows. + long m = sysconf(_SC_PHYS_PAGES); + if (m < 0) + { + return false; + } + this->TotalPhysicalMemory = m >> 8; + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryAIXMemory() +{ +#if defined(_AIX) + long c = sysconf(_SC_AIX_REALMEM); + if (c <= 0) + { + return false; + } + + this->TotalPhysicalMemory = c / 1024; + + return true; +#else + return false; +#endif +} + +/** Query for the memory status */ +bool SystemInformationImplementation::QueryMemory() +{ +#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) + // Assume the mmap() granularity as returned by _SC_PAGESIZE is also + // the system page size. The only known system where this isn't true + // is Cygwin. + long p = sysconf(_SC_PHYS_PAGES); + long m = sysconf(_SC_PAGESIZE); + + if (p < 0 || m < 0) + { + return false; + } + + // assume pagesize is a power of 2 and smaller 1 MiB + size_t pagediv = (1024 * 1024 / m); + + this->TotalPhysicalMemory = p; + this->TotalPhysicalMemory /= pagediv; + +#if defined(_SC_AVPHYS_PAGES) + p = sysconf(_SC_AVPHYS_PAGES); + if (p < 0) + { + return false; + } + + this->AvailablePhysicalMemory = p; + this->AvailablePhysicalMemory /= pagediv; +#endif + + return true; +#else + return false; #endif } @@ -3712,7 +3621,15 @@ SystemInformation::LongLong SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction, unsigned int uiParameter) { -#if USE_ASM_INSTRUCTIONS +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + unsigned __int64 stamp1, stamp2; + + stamp1 = __rdtsc(); + DelayFunction(uiParameter); + stamp2 = __rdtsc(); + + return stamp2 - stamp1; +#elif USE_ASM_INSTRUCTIONS unsigned int edx1, eax1; unsigned int edx2, eax2; @@ -3794,20 +3711,15 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) } return static_cast(cores_per_package); #else - unsigned int Regebx = 0; -#if USE_ASM_INSTRUCTIONS + int Regs[4] = { 0, 0, 0, 0 }; +#if USE_CPUID if (!this->IsHyperThreadingSupported()) { return static_cast(1); // HT not supported } - __asm - { - mov eax, 1 - cpuid - mov Regebx, ebx - } + call_cpuid(1, Regs); #endif - return static_cast ((Regebx & NUM_LOGICAL_BITS) >> 16); + return static_cast ((Regs[1] & NUM_LOGICAL_BITS) >> 16); #endif } @@ -3815,40 +3727,30 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) /** Works only for windows */ unsigned int SystemInformationImplementation::IsHyperThreadingSupported() { -#if USE_ASM_INSTRUCTIONS - unsigned int Regedx = 0, - Regeax = 0, - VendorId[3] = {0, 0, 0}; - __try // Verify cpuid instruction is supported +#if USE_CPUID + int Regs[4] = { 0, 0, 0, 0 }, + VendorId[4] = { 0, 0, 0, 0 }; + // Get vendor id string + if (!call_cpuid(0, VendorId)) { - __asm - { - xor eax, eax // call cpuid with eax = 0 - cpuid // Get vendor id string - mov VendorId, ebx - mov VendorId + 4, edx - mov VendorId + 8, ecx - - mov eax, 1 // call cpuid with eax = 1 - cpuid - mov Regeax, eax // eax contains family processor type - mov Regedx, edx // edx has info about the availability of hyper-Threading - } + return false; } - __except (EXCEPTION_EXECUTE_HANDLER) + // eax contains family processor type + // edx has info about the availability of hyper-Threading + if (!call_cpuid(1, Regs)) { - return(0); // cpuid is unavailable + return false; } - if (((Regeax & FAMILY_ID) == PENTIUM4_ID) || (Regeax & EXT_FAMILY_ID)) + if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { - if (VendorId[0] == 'uneG') + if (VendorId[1] == 'uneG') { - if (VendorId[1] == 'Ieni') + if (VendorId[3] == 'Ieni') { if (VendorId[2] == 'letn') { - return(Regedx & HT_BIT); // Genuine Intel with hyper-Threading technology + return(Regs[3] & HT_BIT); // Genuine Intel with hyper-Threading technology } } } @@ -3862,22 +3764,17 @@ unsigned int SystemInformationImplementation::IsHyperThreadingSupported() /** Return the APIC Id. Works only for windows. */ unsigned char SystemInformationImplementation::GetAPICId() { - unsigned int Regebx = 0; + int Regs[4] = { 0, 0, 0, 0 }; -#if USE_ASM_INSTRUCTIONS +#if USE_CPUID if (!this->IsHyperThreadingSupported()) { return static_cast(-1); // HT not supported } // Logical processor = 1 - __asm - { - mov eax, 1 - cpuid - mov Regebx, ebx - } + call_cpuid(1, Regs); #endif - return static_cast((Regebx & INITIAL_APIC_ID_BITS) >> 24); + return static_cast((Regs[1] & INITIAL_APIC_ID_BITS) >> 24); } @@ -4284,25 +4181,24 @@ bool SystemInformationImplementation::QuerySolarisInfo() this->NumberOfPhysicalCPU = static_cast( atoi(this->ParseValueFromKStat("-n syste_misc -s ncpus").c_str())); this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; - - if(this->NumberOfPhysicalCPU!=0) - { - this->NumberOfLogicalCPU /= this->NumberOfPhysicalCPU; - } + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = 1; this->CPUSpeedInMHz = static_cast(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str())); // Chip family this->ChipID.Family = 0; - // Chip Vendor - this->ChipID.Vendor = "Sun"; - this->FindManufacturer(); - // Chip Model this->ChipID.ProcessorName = this->ParseValueFromKStat("-s cpu_type"); this->ChipID.Model = 0; + // Chip Vendor + if (this->ChipID.ProcessorName != "i386") + { + this->ChipID.Vendor = "Sun"; + this->FindManufacturer(); + } + // Cache size this->Features.L1CacheSize = 0; this->Features.L2CacheSize = 0; @@ -4310,9 +4206,7 @@ bool SystemInformationImplementation::QuerySolarisInfo() char* tail; unsigned long totalMemory = strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0); - this->TotalPhysicalMemory = totalMemory/1024; - this->TotalPhysicalMemory *= 8192; - this->TotalPhysicalMemory /= 1024; + this->TotalPhysicalMemory = totalMemory/128; // Undefined values (for now at least) this->TotalVirtualMemory = 0; @@ -4426,6 +4320,31 @@ bool SystemInformationImplementation::QueryQNXMemory() return false; } +bool SystemInformationImplementation::QueryBSDMemory() +{ +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + int ctrl[2] = { CTL_HW, HW_PHYSMEM }; +#if defined(HW_PHYSMEM64) + int64_t k; + ctrl[1] = HW_PHYSMEM64; +#else + int k; +#endif + size_t sz = sizeof(k); + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->TotalPhysicalMemory = k>>10>>10; + + return true; +#else + return false; +#endif +} + bool SystemInformationImplementation::QueryQNXProcessor() { #if defined(__QNX__) @@ -4479,6 +4398,124 @@ bool SystemInformationImplementation::QueryQNXProcessor() #endif } +bool SystemInformationImplementation::QueryBSDProcessor() +{ +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + int k; + size_t sz = sizeof(k); + int ctrl[2] = { CTL_HW, HW_NCPU }; + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->NumberOfPhysicalCPU = k; + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + +#if defined(HW_CPUSPEED) + ctrl[1] = HW_CPUSPEED; + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->CPUSpeedInMHz = (float) k; +#endif + + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryHPUXMemory() +{ +#if defined(__hpux) + unsigned long tv=0; + unsigned long tp=0; + unsigned long av=0; + unsigned long ap=0; + struct pst_static pst; + struct pst_dynamic pdy; + + unsigned long ps = 0; + if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) == -1) + { + return false; + } + + ps = pst.page_size; + tp = pst.physical_memory *ps; + tv = (pst.physical_memory + pst.pst_maxmem) * ps; + if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) == -1) + { + return false; + } + + ap = tp - pdy.psd_rm * ps; + av = tv - pdy.psd_vm; + this->TotalVirtualMemory = tv>>10>>10; + this->TotalPhysicalMemory = tp>>10>>10; + this->AvailableVirtualMemory = av>>10>>10; + this->AvailablePhysicalMemory = ap>>10>>10; + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QueryHPUXProcessor() +{ +#if defined(__hpux) +# if defined(KWSYS_SYS_HAS_MPCTL_H) + int c = mpctl(MPC_GETNUMSPUS_SYS, 0, 0); + if (c <= 0) + { + return false; + } + + this->NumberOfPhysicalCPU = c; + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + + long t = sysconf(_SC_CPU_VERSION); + + if (t == -1) + { + return false; + } + + switch (t) + { + case CPU_PA_RISC1_0: + this->ChipID.Vendor = "Hewlett-Packard"; + this->ChipID.Family = 0x100; + case CPU_PA_RISC1_1: + this->ChipID.Vendor = "Hewlett-Packard"; + this->ChipID.Family = 0x110; + case CPU_PA_RISC2_0: + this->ChipID.Vendor = "Hewlett-Packard"; + this->ChipID.Family = 0x200; + case CPU_IA64_ARCHREV_0: + this->ChipID.Vendor = "GenuineIntel"; + this->Features.HasIA64 = true; + break; + default: + return false; + } + + this->FindManufacturer(); + + return true; +# else + return false; +# endif +#else + return false; +#endif +} + /** Query the operating system information */ bool SystemInformationImplementation::QueryOSInformation() { diff --git a/SystemTools.cxx b/SystemTools.cxx index 1054d6526..b75993ea6 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -157,7 +157,7 @@ public: #include #endif -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) +#if defined(__BEOS__) && !defined(__ZETA__) #include #include @@ -622,11 +622,7 @@ bool SystemTools::MakeDirectory(const char* path) } SystemTools::ConvertToUnixSlashes(dir); - kwsys_stl::string::size_type pos = dir.find(':'); - if(pos == kwsys_stl::string::npos) - { - pos = 0; - } + kwsys_stl::string::size_type pos = 0; kwsys_stl::string topdir; while((pos = dir.find('/', pos)) != kwsys_stl::string::npos) { @@ -634,14 +630,7 @@ bool SystemTools::MakeDirectory(const char* path) Mkdir(topdir.c_str()); pos++; } - if(dir[dir.size()-1] == '/') - { - topdir = dir.substr(0, dir.size()); - } - else - { - topdir = dir; - } + topdir = dir; if(Mkdir(topdir.c_str()) != 0) { // There is a bug in the Borland Run time library which makes MKDIR @@ -4054,7 +4043,7 @@ kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format) return kwsys_stl::string(buf); } -kwsys_stl::string SystemTools::MakeCindentifier(const char* s) +kwsys_stl::string SystemTools::MakeCidentifier(const char* s) { kwsys_stl::string str(s); if (str.find_first_of("0123456789") == 0) diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index 5171125ce..9c56e96b0 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -91,8 +91,13 @@ public: * then an underscore is prepended. Note that this can produce * identifiers that the standard reserves (_[A-Z].* and __.*). */ - static kwsys_stl::string MakeCindentifier(const char* s); - + static kwsys_stl::string MakeCidentifier(const char* s); + + static kwsys_stl::string MakeCindentifier(const char* s) + { + return MakeCidentifier(s); + } + /** * Replace replace all occurences of the string in the source string. */ diff --git a/testDynamicLoader.cxx b/testDynamicLoader.cxx index a7adbcad9..cbfb65b1c 100644 --- a/testDynamicLoader.cxx +++ b/testDynamicLoader.cxx @@ -15,7 +15,7 @@ #include KWSYS_HEADER(ios/iostream) #include KWSYS_HEADER(stl/string) -#if defined(__BEOS__) && !defined(__HAIKU__) +#if defined(__BEOS__) #include /* disable_debugger() API. */ #endif diff --git a/testProcess.c b/testProcess.c index ec561ead7..269b84ba8 100644 --- a/testProcess.c +++ b/testProcess.c @@ -32,7 +32,7 @@ # pragma warn -8060 /* possibly incorrect assignment */ #endif -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) +#if defined(__BEOS__) && !defined(__ZETA__) /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */ # include static inline void testProcess_usleep(unsigned int msec) diff --git a/testSystemInformation.cxx b/testSystemInformation.cxx index cfd7ce210..49a686c17 100644 --- a/testSystemInformation.cxx +++ b/testSystemInformation.cxx @@ -47,6 +47,8 @@ int testSystemInformation(int, char*[]) { + kwsys_ios::cout << "CTEST_FULL_OUTPUT\n"; // avoid truncation + kwsys::SystemInformation info; info.RunCPUCheck(); info.RunOSCheck(); @@ -86,6 +88,13 @@ int testSystemInformation(int, char*[]) printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB"); + for (int i = 0; i <= 31; i++) + { + if (info.DoesCPUSupportFeature(1 << i)) + { + kwsys_ios::cout << "CPU feature " << i << "\n"; + } + } //int GetProcessorCacheXSize(long int); // bool DoesCPUSupportFeature(long int); return 0; From 40cf3fb95bc391519c0db4be1dc03c49e040579f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 4 Jan 2013 13:31:01 +0100 Subject: [PATCH 086/131] Make linking APIs aware of 'head' target The 'head' is the dependent target to be linked with the current target. It will be used to evaluate generator expressions with proper handling of mapped configurations and is used as the source target of properties. This requires that memoization is done with a key of a pair of target and config, instead of just config, because now the result also depends on the target. Removing the memoization entirely is not an option because it slows cmake down considerably. --- Source/cmComputeLinkDepends.cxx | 11 +-- Source/cmComputeLinkDepends.h | 3 +- Source/cmComputeLinkInformation.cxx | 11 ++- Source/cmComputeLinkInformation.h | 4 +- Source/cmComputeTargetDepends.cxx | 3 +- Source/cmExportFileGenerator.cxx | 3 +- Source/cmGlobalXCodeGenerator.cxx | 2 +- Source/cmTarget.cxx | 120 ++++++++++++++++++---------- Source/cmTarget.h | 32 +++++--- 9 files changed, 119 insertions(+), 70 deletions(-) diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 055aab032..dec2b54d1 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -172,10 +172,11 @@ satisfy dependencies. //---------------------------------------------------------------------------- cmComputeLinkDepends -::cmComputeLinkDepends(cmTarget* target, const char* config) +::cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget* head) { // Store context information. this->Target = target; + this->HeadTarget = head; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); @@ -352,7 +353,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) { // Follow the target dependencies. if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config)) + entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) { // This target provides its own link interface information. this->AddLinkEntries(depender_index, iface->Libraries); @@ -444,7 +445,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) if(entry.Target) { if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config)) + entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) { // Follow public and private dependencies transitively. this->FollowSharedDeps(index, iface, true); @@ -533,7 +534,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries() { // Add direct link dependencies in this configuration. cmTarget::LinkImplementation const* impl = - this->Target->GetLinkImplementation(this->Config); + this->Target->GetLinkImplementation(this->Config, this->HeadTarget); this->AddLinkEntries(-1, impl->Libraries); for(std::vector::const_iterator wi = impl->WrongConfigLibraries.begin(); @@ -944,7 +945,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) if(cmTarget* target = this->EntryList[*ni].Target) { if(cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config)) + target->GetLinkInterface(this->Config, this->HeadTarget)) { if(iface->Multiplicity > count) { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 80a04541f..1d5d1b920 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -32,7 +32,7 @@ class cmake; class cmComputeLinkDepends { public: - cmComputeLinkDepends(cmTarget* target, const char* config); + cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget *head); ~cmComputeLinkDepends(); // Basic information about each link item. @@ -59,6 +59,7 @@ private: // Context information. cmTarget* Target; + cmTarget* HeadTarget; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d8ffb5e83..504c6e76f 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -239,10 +239,12 @@ because this need be done only for shared libraries without soname-s. //---------------------------------------------------------------------------- cmComputeLinkInformation -::cmComputeLinkInformation(cmTarget* target, const char* config) +::cmComputeLinkInformation(cmTarget* target, const char* config, + cmTarget *headTarget) { // Store context information. this->Target = target; + this->HeadTarget = headTarget; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); @@ -265,7 +267,7 @@ cmComputeLinkInformation this->OrderDependentRPath = 0; // Get the language used for linking this target. - this->LinkLanguage = this->Target->GetLinkerLanguage(config); + this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget); if(!this->LinkLanguage) { // The Compute method will do nothing, so skip the rest of the @@ -503,7 +505,7 @@ bool cmComputeLinkInformation::Compute() } // Compute the ordered link line items. - cmComputeLinkDepends cld(this->Target, this->Config); + cmComputeLinkDepends cld(this->Target, this->Config, this->HeadTarget); cld.SetOldLinkDirMode(this->OldLinkDirMode); cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute(); @@ -569,7 +571,8 @@ bool cmComputeLinkInformation::Compute() void cmComputeLinkInformation::AddImplicitLinkInfo() { // The link closure lists all languages whose implicit info is needed. - cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config); + cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config, + this->HeadTarget); for(std::vector::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) { diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index e0078af2a..1a76922a5 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -29,7 +29,8 @@ class cmOrderDirectories; class cmComputeLinkInformation { public: - cmComputeLinkInformation(cmTarget* target, const char* config); + cmComputeLinkInformation(cmTarget* target, const char* config, + cmTarget* headTarget); ~cmComputeLinkInformation(); bool Compute(); @@ -74,6 +75,7 @@ private: // Context information. cmTarget* Target; + cmTarget* HeadTarget; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 3b15ec11a..c3a75e4b6 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -244,8 +244,9 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, const char *config, std::set &emitted) { + cmTarget* depender = this->Targets[depender_index]; if(cmTarget::LinkInterface const* iface = - dependee->GetLinkInterface(config)) + dependee->GetLinkInterface(config, depender)) { for(std::vector::const_iterator lib = iface->Libraries.begin(); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 2b133be09..90c0c4111 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -357,7 +357,8 @@ cmExportFileGenerator } // Add the transitive link dependencies for this configuration. - if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config)) + if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, + target)) { this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index b2d325c8a..4c26b829b 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1206,7 +1206,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) // If the language is compiled as a source trust Xcode to link with it. cmTarget::LinkImplementation const* impl = - cmtarget.GetLinkImplementation("NOCONFIG"); + cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget); for(std::vector::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ca53a39d2..1338ec491 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -72,6 +72,11 @@ struct cmTarget::ImportInfo cmTarget::LinkInterface LinkInterface; }; +struct TargetConfigPair : public std::pair { + TargetConfigPair(cmTarget* tgt, const std::string &config) + : std::pair(tgt, config) {} +}; + //---------------------------------------------------------------------------- class cmTargetInternals { @@ -100,20 +105,24 @@ public: OptionalLinkInterface(): Exists(false) {} bool Exists; }; - typedef std::map LinkInterfaceMapType; + typedef std::map + LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; typedef std::map OutputInfoMapType; OutputInfoMapType OutputInfoMap; - typedef std::map ImportInfoMapType; + typedef std::map + ImportInfoMapType; ImportInfoMapType ImportInfoMap; // Cache link implementation computation from each configuration. - typedef std::map LinkImplMapType; + typedef std::map LinkImplMapType; LinkImplMapType LinkImplMap; - typedef std::map LinkClosureMapType; + typedef std::map + LinkClosureMapType; LinkClosureMapType LinkClosureMap; struct SourceEntry { std::vector Depends; }; @@ -3024,8 +3033,11 @@ class cmTargetCollectLinkLanguages { public: cmTargetCollectLinkLanguages(cmTarget* target, const char* config, - std::set& languages): - Config(config), Languages(languages) { this->Visited.insert(target); } + std::set& languages, + cmTarget* head): + Config(config), Languages(languages), HeadTarget(head) + { this->Visited.insert(target); } + void Visit(cmTarget* target) { if(!target || !this->Visited.insert(target).second) @@ -3034,7 +3046,7 @@ public: } cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config); + target->GetLinkInterface(this->Config, this->HeadTarget); if(!iface) { return; } for(std::vector::const_iterator @@ -3053,26 +3065,30 @@ public: private: const char* Config; std::set& Languages; + cmTarget* HeadTarget; std::set Visited; }; //---------------------------------------------------------------------------- -const char* cmTarget::GetLinkerLanguage(const char* config) +const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head) { - const char* lang = this->GetLinkClosure(config)->LinkerLanguage.c_str(); + cmTarget *headTarget = head ? head : this; + const char* lang = this->GetLinkClosure(config, headTarget) + ->LinkerLanguage.c_str(); return *lang? lang : 0; } //---------------------------------------------------------------------------- -cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config) +cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config, + cmTarget *head) { - std::string key = cmSystemTools::UpperCase(config? config : ""); + TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : "")); cmTargetInternals::LinkClosureMapType::iterator i = this->Internal->LinkClosureMap.find(key); if(i == this->Internal->LinkClosureMap.end()) { LinkClosure lc; - this->ComputeLinkClosure(config, lc); + this->ComputeLinkClosure(config, lc, head); cmTargetInternals::LinkClosureMapType::value_type entry(key, lc); i = this->Internal->LinkClosureMap.insert(entry).first; } @@ -3133,11 +3149,12 @@ public: }; //---------------------------------------------------------------------------- -void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc) +void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc, + cmTarget *head) { // Get languages built in this target. std::set languages; - LinkImplementation const* impl = this->GetLinkImplementation(config); + LinkImplementation const* impl = this->GetLinkImplementation(config, head); for(std::vector::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -3145,7 +3162,7 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc) } // Add interface languages from linked targets. - cmTargetCollectLinkLanguages cll(this, config, languages); + cmTargetCollectLinkLanguages cll(this, config, languages, head); for(std::vector::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { @@ -3284,7 +3301,8 @@ bool cmTarget::HasSOName(const char* config) return ((this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY) && !this->GetPropertyAsBool("NO_SONAME") && - this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); + this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config, + this))); } //---------------------------------------------------------------------------- @@ -3293,7 +3311,7 @@ std::string cmTarget::GetSOName(const char* config) if(this->IsImported()) { // Lookup the imported soname. - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) { if(info->NoSOName) { @@ -3330,7 +3348,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) { if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) { return info->NoSOName; } @@ -3444,7 +3462,7 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib, std::string cmTarget::ImportedGetFullPath(const char* config, bool implib) { std::string result; - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) { result = implib? info->ImportLibrary : info->Location; } @@ -3529,7 +3547,7 @@ void cmTarget::GetFullNameInternal(const char* config, const char* suffixVar = this->GetSuffixVariableInternal(implib); // Check for language-specific default prefix and suffix. - if(const char* ll = this->GetLinkerLanguage(config)) + if(const char* ll = this->GetLinkerLanguage(config, this)) { if(!targetSuffix && suffixVar && *suffixVar) { @@ -3900,7 +3918,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config) } // Check for rpath support on this platform. - if(const char* ll = this->GetLinkerLanguage(config)) + if(const char* ll = this->GetLinkerLanguage(config, this)) { std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; flagVar += ll; @@ -4322,7 +4340,7 @@ bool cmTarget::IsChrpathUsed(const char* config) // Enable if the rpath flag uses a separator and the target uses ELF // binaries. - if(const char* ll = this->GetLinkerLanguage(config)) + if(const char* ll = this->GetLinkerLanguage(config, this)) { std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; sepVar += ll; @@ -4346,7 +4364,7 @@ bool cmTarget::IsChrpathUsed(const char* config) //---------------------------------------------------------------------------- cmTarget::ImportInfo const* -cmTarget::GetImportInfo(const char* config) +cmTarget::GetImportInfo(const char* config, cmTarget *headTarget) { // There is no imported information for non-imported targets. if(!this->IsImported()) @@ -4365,14 +4383,16 @@ cmTarget::GetImportInfo(const char* config) { config_upper = "NOCONFIG"; } + TargetConfigPair key(headTarget, config_upper); typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType; + ImportInfoMapType::const_iterator i = - this->Internal->ImportInfoMap.find(config_upper); + this->Internal->ImportInfoMap.find(key); if(i == this->Internal->ImportInfoMap.end()) { ImportInfo info; - this->ComputeImportInfo(config_upper, info); - ImportInfoMapType::value_type entry(config_upper, info); + this->ComputeImportInfo(config_upper, info, headTarget); + ImportInfoMapType::value_type entry(key, info); i = this->Internal->ImportInfoMap.insert(entry).first; } @@ -4511,8 +4531,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, //---------------------------------------------------------------------------- void cmTarget::ComputeImportInfo(std::string const& desired_config, - ImportInfo& info) + ImportInfo& info, + cmTarget *headTarget) { + (void)headTarget; // This method finds information about an imported target from its // properties. The "IMPORTED_" namespace is reserved for properties // defined by the project exporting the target. @@ -4669,12 +4691,13 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } //---------------------------------------------------------------------------- -cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config) +cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, + cmTarget *head) { // Imported targets have their own link interface. if(this->IsImported()) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) { return &info->LinkInterface; } @@ -4690,14 +4713,15 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config) } // Lookup any existing link interface for this configuration. - std::string key = cmSystemTools::UpperCase(config? config : ""); + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + cmTargetInternals::LinkInterfaceMapType::iterator i = this->Internal->LinkInterfaceMap.find(key); if(i == this->Internal->LinkInterfaceMap.end()) { // Compute the link interface for this configuration. cmTargetInternals::OptionalLinkInterface iface; - iface.Exists = this->ComputeLinkInterface(config, iface); + iface.Exists = this->ComputeLinkInterface(config, iface, head); // Store the information for this configuration. cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); @@ -4708,7 +4732,8 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config) } //---------------------------------------------------------------------------- -bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) +bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, + cmTarget *headTarget) { // Construct the property name suffix for this configuration. std::string suffix = "_"; @@ -4765,7 +4790,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) { emitted.insert(*li); } - LinkImplementation const* impl = this->GetLinkImplementation(config); + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); for(std::vector::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { @@ -4793,7 +4819,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) else { // The link implementation is the default link interface. - LinkImplementation const* impl = this->GetLinkImplementation(config); + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); iface.Libraries = impl->Libraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries; if(this->GetType() == cmTarget::STATIC_LIBRARY) @@ -4825,7 +4852,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) //---------------------------------------------------------------------------- cmTarget::LinkImplementation const* -cmTarget::GetLinkImplementation(const char* config) +cmTarget::GetLinkImplementation(const char* config, cmTarget *head) { // There is no link implementation for imported targets. if(this->IsImported()) @@ -4834,14 +4861,15 @@ cmTarget::GetLinkImplementation(const char* config) } // Lookup any existing link implementation for this configuration. - std::string key = cmSystemTools::UpperCase(config? config : ""); + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + cmTargetInternals::LinkImplMapType::iterator i = this->Internal->LinkImplMap.find(key); if(i == this->Internal->LinkImplMap.end()) { // Compute the link implementation for this configuration. LinkImplementation impl; - this->ComputeLinkImplementation(config, impl); + this->ComputeLinkImplementation(config, impl, head); // Store the information for this configuration. cmTargetInternals::LinkImplMapType::value_type entry(key, impl); @@ -4853,8 +4881,10 @@ cmTarget::GetLinkImplementation(const char* config) //---------------------------------------------------------------------------- void cmTarget::ComputeLinkImplementation(const char* config, - LinkImplementation& impl) + LinkImplementation& impl, + cmTarget *head) { + (void)head; // Compute which library configuration to link. cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); @@ -4977,16 +5007,19 @@ std::string cmTarget::CheckCMP0004(std::string const& item) //---------------------------------------------------------------------------- cmComputeLinkInformation* -cmTarget::GetLinkInformation(const char* config) +cmTarget::GetLinkInformation(const char* config, cmTarget *head) { + cmTarget *headTarget = head ? head : this; // Lookup any existing information for this configuration. - std::map::iterator - i = this->LinkInformation.find(config?config:""); + TargetConfigPair key(headTarget, + cmSystemTools::UpperCase(config?config:"")); + cmTargetLinkInformationMap::iterator + i = this->LinkInformation.find(key); if(i == this->LinkInformation.end()) { // Compute information for this configuration. cmComputeLinkInformation* info = - new cmComputeLinkInformation(this, config); + new cmComputeLinkInformation(this, config, headTarget); if(!info || !info->Compute()) { delete info; @@ -4994,8 +5027,7 @@ cmTarget::GetLinkInformation(const char* config) } // Store the information for this configuration. - std::map::value_type - entry(config?config:"", info); + cmTargetLinkInformationMap::value_type entry(key, info); i = this->LinkInformation.insert(entry).first; } return i->second; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 52d5ca611..29c73b616 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -25,11 +25,13 @@ class cmSourceFile; class cmGlobalGenerator; class cmComputeLinkInformation; class cmListFileBacktrace; +class cmTarget; struct cmTargetLinkInformationMap: - public std::map + public std::map, cmComputeLinkInformation*> { - typedef std::map derived; + typedef std::map, + cmComputeLinkInformation*> derived; cmTargetLinkInformationMap() {} cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); ~cmTargetLinkInformationMap(); @@ -258,7 +260,8 @@ public: /** Get the link interface for the given configuration. Returns 0 if the target cannot be linked. */ - LinkInterface const* GetLinkInterface(const char* config); + LinkInterface const* GetLinkInterface(const char* config, + cmTarget *headTarget); /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ @@ -274,7 +277,8 @@ public: // Needed only for OLD behavior of CMP0003. std::vector WrongConfigLibraries; }; - LinkImplementation const* GetLinkImplementation(const char* config); + LinkImplementation const* GetLinkImplementation(const char* config, + cmTarget *head); /** Link information from the transitive closure of the link implementation and the interfaces of its dependencies. */ @@ -286,7 +290,7 @@ public: // Languages whose runtime libraries must be linked. std::vector Languages; }; - LinkClosure const* GetLinkClosure(const char* config); + LinkClosure const* GetLinkClosure(const char* config, cmTarget *head); /** Strip off leading and trailing whitespace from an item named in the link dependencies of this target. */ @@ -331,7 +335,7 @@ public: bool FindSourceFiles(); ///! Return the preferred linker language for this target - const char* GetLinkerLanguage(const char* config = 0); + const char* GetLinkerLanguage(const char* config = 0, cmTarget *head = 0); /** Get the full name of the target according to the settings in its makefile. */ @@ -399,7 +403,8 @@ public: std::string GetInstallNameDirForInstallTree(const char* config, bool for_xcode = false); - cmComputeLinkInformation* GetLinkInformation(const char* config); + cmComputeLinkInformation* GetLinkInformation(const char* config, + cmTarget *head = 0); // Get the properties cmPropertyMap &GetProperties() { return this->Properties; }; @@ -597,16 +602,19 @@ private: // 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); + ImportInfo const* GetImportInfo(const char* config, + cmTarget *workingTarget); + void ComputeImportInfo(std::string const& desired_config, ImportInfo& info, + cmTarget *head); cmTargetLinkInformationMap LinkInformation; - bool ComputeLinkInterface(const char* config, LinkInterface& iface); + bool ComputeLinkInterface(const char* config, LinkInterface& iface, + cmTarget *head); void ComputeLinkImplementation(const char* config, - LinkImplementation& impl); - void ComputeLinkClosure(const char* config, LinkClosure& lc); + LinkImplementation& impl, cmTarget *head); + void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget *head); void ClearLinkMaps(); From 765386279815f208c5f83b1ad2b66776e990feb9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 6 Dec 2012 12:14:03 +0100 Subject: [PATCH 087/131] Add LINK_LIBRARIES property for direct target link dependencies Previously we kept direct link dependencies in OriginalLinkLibraries. The property exposes the information in the CMake language through the get/set_property commands. We preserve the OriginalLinkLibraries value internally to support old APIs like that for CMP0003's OLD behavior, but the property is now authoritative. This follows up from commit d5cf644a (Split link information processing into two steps, 2012-11-01). This will be used later to populate the link interface properties when exporting targets, and will later allow use of generator expressions when linking to libraries with target_link_libraries. Also make targets depend on the (config-specific) union of dependencies. CMake now allows linking to dependencies or not depending on the config. However, generated build systems are not all capable of processing config-specific dependencies, so the targets depend on the union of dependencies for all configs. --- Source/cmComputeTargetDepends.cxx | 40 +++++-- Source/cmTarget.cxx | 103 ++++++++++++++++-- Source/cmTarget.h | 6 + .../target_link_libraries/CMakeLists.txt | 7 ++ .../target_link_libraries/depB.cpp | 6 +- .../target_link_libraries/libgenex.cpp | 7 ++ .../target_link_libraries/libgenex.h | 12 ++ 7 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 Tests/CMakeCommands/target_link_libraries/libgenex.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/libgenex.h diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index c3a75e4b6..8fd95b9cd 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -200,25 +200,51 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Get the depender. cmTarget* depender = this->Targets[depender_index]; - // Loop over all targets linked directly. + // Loop over all targets linked directly in all configs. + // We need to make targets depend on the union of all config-specific + // dependencies in all targets, because the generated build-systems can't + // deal with config-specific dependencies. { - cmTarget::LinkLibraryVectorType const& tlibs = - depender->GetOriginalLinkLibraries(); std::set emitted; + { + std::vector tlibs; + depender->GetDirectLinkLibraries(0, tlibs, depender); // A target should not depend on itself. emitted.insert(depender->GetName()); - for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin(); + for(std::vector::const_iterator lib = tlibs.begin(); lib != tlibs.end(); ++lib) { // Don't emit the same library twice for this target. - if(emitted.insert(lib->first).second) + if(emitted.insert(*lib).second) { - this->AddTargetDepend(depender_index, lib->first.c_str(), true); - this->AddInterfaceDepends(depender_index, lib->first.c_str(), + this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), true, emitted); } } } + std::vector configs; + depender->GetMakefile()->GetConfigurations(configs); + for (std::vector::const_iterator it = configs.begin(); + it != configs.end(); ++it) + { + std::vector tlibs; + depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender); + // A target should not depend on itself. + emitted.insert(depender->GetName()); + for(std::vector::const_iterator lib = tlibs.begin(); + lib != tlibs.end(); ++lib) + { + // Don't emit the same library twice for this target. + if(emitted.insert(*lib).second) + { + this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), + true, emitted); + } + } + } + } // Loop over all utility dependencies. { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 1338ec491..25054c536 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -519,6 +519,22 @@ void cmTarget::DefineProperties(cmake *cm) "Installing a target with EXCLUDE_FROM_ALL set to true has " "undefined behavior."); + cm->DefineProperty + ("LINK_LIBRARIES", cmProperty::TARGET, + "List of direct link dependencies.", + "This property specifies the list of libraries or targets which will be " + "used for linking. " + "In addition to accepting values from the target_link_libraries " + "command, values may be set directly on any target using the " + "set_property command. " + "\n" + "The target property values are used by the generators to set " + "the link libraries for the compiler. " + "See also the target_link_libraries command.\n" + "Contents of LINK_LIBRARIES may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + cm->DefineProperty ("INCLUDE_DIRECTORIES", cmProperty::TARGET, "List of preprocessor include file search directories.", @@ -2139,6 +2155,66 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) NameResolvesToFramework(libname); } +//---------------------------------------------------------------------------- +void cmTarget::GetDirectLinkLibraries(const char *config, + std::vector &libs, cmTarget *head) +{ + const char *prop = this->GetProperty("LINK_LIBRARIES"); + if (prop) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "LINK_LIBRARIES", 0, 0); + cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile, + config, + false, + head, + &dagChecker), + libs); + } +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt) +{ + if (llt == GENERAL) + { + return value; + } + + // Get the list of configurations considered to be DEBUG. + std::vector const& debugConfigs = + this->Makefile->GetCMakeInstance()->GetDebugConfigs(); + + std::string configString = "$"; + + if (debugConfigs.size() > 1) + { + for(std::vector::const_iterator + li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li) + { + configString += ",$"; + } + configString = "$"; + } + + if (llt == OPTIMIZED) + { + configString = "$"; + } + return "$<" + configString + ":" + value + ">"; +} + +//---------------------------------------------------------------------------- +static std::string targetNameGenex(const char *lib) +{ + return std::string("$"; +} + //---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, @@ -2149,6 +2225,18 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, { return; } + + { + cmTarget *tgt = this->Makefile->FindTargetToUse(lib); + const bool isNonImportedTarget = tgt && !tgt->IsImported(); + + std::string libName = isNonImportedTarget ? targetNameGenex(lib) + : std::string(lib); + this->AppendProperty("LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(libName, + llt).c_str()); + } + cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; @@ -4884,26 +4972,23 @@ void cmTarget::ComputeLinkImplementation(const char* config, LinkImplementation& impl, cmTarget *head) { - (void)head; // Compute which library configuration to link. cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); // Collect libraries directly linked in this configuration. - LinkLibraryVectorType const& llibs = this->GetOriginalLinkLibraries(); - for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin(); + std::vector llibs; + this->GetDirectLinkLibraries(config, llibs, head); + for(std::vector::const_iterator li = llibs.begin(); li != llibs.end(); ++li) { // Skip entries that resolve to the target itself or are empty. - std::string item = this->CheckCMP0004(li->first); + std::string item = this->CheckCMP0004(*li); if(item == this->GetName() || item.empty()) { continue; } - if(li->second == cmTarget::GENERAL || li->second == linkType) - { - // The entry is meant for this configuration. - impl.Libraries.push_back(item); - } + // The entry is meant for this configuration. + impl.Libraries.push_back(item); } LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries(); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 29c73b616..d4069fa01 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -168,6 +168,9 @@ public: return this->LinkLibraries;} const LinkLibraryVectorType &GetOriginalLinkLibraries() const {return this->OriginalLinkLibraries;} + void GetDirectLinkLibraries(const char *config, + std::vector &, + cmTarget *head); /** Compute the link type to use for the given configuration. */ LinkLibraryType ComputeLinkType(const char* config); @@ -622,6 +625,9 @@ private: void ProcessSourceExpression(std::string const& expr); + std::string GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt); + // The cmMakefile instance that owns this target. This should // always be set. cmMakefile* Makefile; diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 60b36fc27..63ae675d2 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -34,6 +34,13 @@ generate_export_header(depB) target_link_libraries(depB LINK_PRIVATE depA) +add_library(libgenex SHARED libgenex.cpp) +generate_export_header(libgenex) + +set_property(TARGET depB APPEND PROPERTY + LINK_LIBRARIES $<1:libgenex> +) + add_library(depC SHARED depC.cpp) generate_export_header(depC) diff --git a/Tests/CMakeCommands/target_link_libraries/depB.cpp b/Tests/CMakeCommands/target_link_libraries/depB.cpp index 1bbe38bc2..4f46552d7 100644 --- a/Tests/CMakeCommands/target_link_libraries/depB.cpp +++ b/Tests/CMakeCommands/target_link_libraries/depB.cpp @@ -3,9 +3,13 @@ #include "depA.h" +#include "libgenex.h" + int DepB::foo() { DepA a; - return a.foo(); + LibGenex lg; + + return a.foo() + lg.foo(); } diff --git a/Tests/CMakeCommands/target_link_libraries/libgenex.cpp b/Tests/CMakeCommands/target_link_libraries/libgenex.cpp new file mode 100644 index 000000000..c925c0821 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/libgenex.cpp @@ -0,0 +1,7 @@ + +#include "libgenex.h" + +int LibGenex::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/libgenex.h b/Tests/CMakeCommands/target_link_libraries/libgenex.h new file mode 100644 index 000000000..733f9b6df --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/libgenex.h @@ -0,0 +1,12 @@ + +#include "libgenex_export.h" + +#ifndef LIBGENEX_H +#define LIBGENEX_H + +struct LIBGENEX_EXPORT LibGenex +{ + int foo(); +}; + +#endif From 9cfe4f1b769597bd9ba179eba46572a9df27f64c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 26 Nov 2012 12:30:00 +0100 Subject: [PATCH 088/131] Allow target_link_libraries with IMPORTED targets. This makes it possible to use: target_link_libraries(foo LINK_INTERFACE_LIBRARIES bar) where foo is an IMPORTED target. Other tll() signatures are not allowed. --- Source/cmTargetLinkLibrariesCommand.cxx | 14 ++++++++++++++ .../target_link_libraries/CMakeLists.txt | 3 +++ 2 files changed, 17 insertions(+) diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index f42b0f687..0705fb4d6 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -33,6 +33,10 @@ bool cmTargetLinkLibrariesCommand this->Target = this->Makefile->GetCMakeInstance() ->GetGlobalGenerator()->FindTarget(0, args[0].c_str()); + if(!this->Target) + { + this->Target = this->Makefile->FindTargetToUse(args[0].c_str()); + } if(!this->Target) { cmake::MessageType t = cmake::FATAL_ERROR; // fail by default @@ -257,6 +261,16 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, // Handle normal case first. if(this->CurrentProcessingState != ProcessingLinkInterface) { + if (this->Target->IsImported()) + { + cmOStringStream e; + e << "Imported targets may only be used with the " + "LINK_INTERFACE_LIBRARIES specifier to target_link_libraries."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + + this->Makefile ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); if (this->CurrentProcessingState != ProcessingPublicInterface) diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 60b36fc27..e586c28d9 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -29,6 +29,9 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_library(depA SHARED depA.cpp) generate_export_header(depA) +add_library(importedlib UNKNOWN IMPORTED) +target_link_libraries(importedlib LINK_INTERFACE_LIBRARIES depA) + add_library(depB SHARED depB.cpp) generate_export_header(depB) From 9ce1b9ef2946ead0605e766c7dcf1302fe122f3a Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 25 Nov 2012 01:15:44 +0100 Subject: [PATCH 089/131] Add CMAKE_BUILD_INTERFACE_INCLUDES build-variable. This makes set(CMAKE_BUILD_INTERFACE_INCLUDES ON) add the equivalent of set_property(TARGET tgt APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES $ ) to every target. If the headers are in CMAKE_CURRENT_SOURCE_DIR, and the generated headers are in CMAKE_CURRENT_BINARY_DIR, this is a convenient way to build a target bar, which depends on foo, just by using target_link_libraries() and adding the INTERFACE_INCLUDE_DIRECTORIES to the INCLUDE_DIRECTORIES of the target being linked. There will be more-convenient porcelain API to consume the property in the future. --- Source/cmDocumentVariables.cxx | 11 +++++++++++ Source/cmGlobalGenerator.cxx | 17 +++++++++++++++++ .../target_link_libraries/CMakeLists.txt | 7 +++++++ .../target_link_libraries/subdir/CMakeLists.txt | 5 +++++ .../target_link_libraries/subdir/subdirlib.cpp | 7 +++++++ .../target_link_libraries/subdir/subdirlib.h | 12 ++++++++++++ .../target_link_libraries/targetA.cpp | 6 +++++- 7 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt create mode 100644 Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index be45e2d27..08b3ef168 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1146,6 +1146,17 @@ void cmDocumentVariables::DefineVariables(cmake* cm) false, "Variables that Control the Build"); + cm->DefineProperty + ("CMAKE_BUILD_INTERFACE_INCLUDES", cmProperty::VARIABLE, + "Automatically add the current source- and build directories " + "to the INTERFACE_INCLUDE_DIRECTORIES.", + "If this variable is enabled, CMake automatically adds for each " + "target ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} " + "to the INTERFACE_INCLUDE_DIRECTORIES." + "By default CMAKE_BUILD_INTERFACE_INCLUDES is OFF.", + false, + "Variables that Control the Build"); + cm->DefineProperty ("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE, "The rpath to use for installed targets.", diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0f439e9cd..d030aa7ba 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -938,6 +938,23 @@ void cmGlobalGenerator::Generate() (*targets)[tit->first] = tit->second; (*targets)[tit->first].SetMakefile(mf); } + + for ( tit = targets->begin(); tit != targets->end(); ++ tit ) + { + if (mf->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES")) + { + const char *binDir = mf->GetStartOutputDirectory(); + const char *srcDir = mf->GetStartDirectory(); + const std::string dirs = std::string(binDir ? binDir : "") + + std::string(binDir ? ";" : "") + + std::string(srcDir ? srcDir : ""); + if (!dirs.empty()) + { + tit->second.AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", + ("$").c_str()); + } + } + } } // Add generator specific helper commands diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 60b36fc27..29b69d944 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -53,6 +53,13 @@ set_target_properties(targetA PROPERTIES LINK_INTERFACE_LIBRARIES "") assert_property(targetA LINK_INTERFACE_LIBRARIES "") +add_subdirectory(subdir) +target_link_libraries(targetA subdirlib) +set_property(TARGET targetA APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) + target_link_libraries(targetA depB depC) assert_property(targetA LINK_INTERFACE_LIBRARIES "") diff --git a/Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt new file mode 100644 index 000000000..61a1a5988 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/subdir/CMakeLists.txt @@ -0,0 +1,5 @@ + +set(CMAKE_BUILD_INTERFACE_INCLUDES ON) + +add_library(subdirlib SHARED subdirlib.cpp) +generate_export_header(subdirlib) diff --git a/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp new file mode 100644 index 000000000..cd2f1a23a --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.cpp @@ -0,0 +1,7 @@ + +#include "subdirlib.h" + +int SubDirLibObject::foo() const +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h new file mode 100644 index 000000000..e386f87b2 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/subdir/subdirlib.h @@ -0,0 +1,12 @@ + +#ifndef SUBDIRLIB_H +#define SUBDIRLIB_H + +#include "subdirlib_export.h" + +struct SUBDIRLIB_EXPORT SubDirLibObject +{ + int foo() const; +}; + +#endif diff --git a/Tests/CMakeCommands/target_link_libraries/targetA.cpp b/Tests/CMakeCommands/target_link_libraries/targetA.cpp index 6ff65b106..559aef7f0 100644 --- a/Tests/CMakeCommands/target_link_libraries/targetA.cpp +++ b/Tests/CMakeCommands/target_link_libraries/targetA.cpp @@ -3,6 +3,8 @@ #include "depC.h" #include "depIfaceOnly.h" +#include "subdirlib.h" + int main(int argc, char **argv) { DepA a; @@ -11,5 +13,7 @@ int main(int argc, char **argv) DepIfaceOnly iface_only; - return a.foo() + b.foo() + c.foo() + iface_only.foo(); + SubDirLibObject sd; + + return a.foo() + b.foo() + c.foo() + iface_only.foo() + sd.foo(); } From c77281061c1b931842d5f0a03fc68b3f16999a5b Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 7 Jan 2013 16:07:49 +0100 Subject: [PATCH 090/131] Add the -Wundef flag when compiling CMake. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ad9587e5..e84f8980e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -588,10 +588,10 @@ if(NOT CMake_VERSION_IS_RELEASE) NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2) set(C_FLAGS_LIST -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security - -Wmissing-format-attribute -fno-common + -Wmissing-format-attribute -fno-common -Wundef ) set(CXX_FLAGS_LIST -Wnon-virtual-dtor -Wcast-align -Wchar-subscripts -Wall -W - -Wshadow -Wpointer-arith -Wformat-security + -Wshadow -Wpointer-arith -Wformat-security -Wundef ) foreach(FLAG_LANG C CXX) From bf5ece51c3827dc05018128fefe8270da88cfefb Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 5 Nov 2012 14:48:42 +0100 Subject: [PATCH 091/131] Keep track of properties used to determine linker libraries. Those properties can't later be implicitly defined by the interface of those link libraries. --- Source/cmGeneratorExpression.cxx | 10 +++++- Source/cmGeneratorExpression.h | 4 +++ Source/cmGeneratorExpressionEvaluator.cxx | 8 +++++ Source/cmGeneratorExpressionEvaluator.h | 1 + Source/cmTarget.cxx | 42 ++++++++++++++++++++++- Source/cmTarget.h | 10 ++++++ 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 6d003e10f..4063697cd 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -94,7 +94,15 @@ const char *cmCompiledGeneratorExpression::Evaluate( for ( ; it != end; ++it) { - this->Output += (*it)->Evaluate(&context, dagChecker); + const std::string result = (*it)->Evaluate(&context, dagChecker); + this->Output += result; + + for(std::set::const_iterator + p = context.SeenTargetProperties.begin(); + p != context.SeenTargetProperties.end(); ++p) + { + this->SeenTargetProperties[*p] += result + ";"; + } if (context.HadError) { this->Output = ""; diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index dcdfefbad..b58dde52b 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -83,6 +83,9 @@ public: std::set const& GetTargets() const { return this->Targets; } + std::map const& GetSeenTargetProperties() const + { return this->SeenTargetProperties; } + ~cmCompiledGeneratorExpression(); std::string GetInput() const @@ -110,6 +113,7 @@ private: bool NeedsParsing; mutable std::set Targets; + mutable std::map SeenTargetProperties; mutable std::string Output; }; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 82becaf75..f4e413123 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -380,6 +380,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } } + if (target == context->HeadTarget) + { + // Keep track of the properties seen while processing. + // The evaluation of the LINK_LIBRARIES generator expressions + // will check this to ensure that properties form a DAG. + context->SeenTargetProperties.insert(propertyName); + } + if (propertyName.empty()) { reportError(context, content->GetOriginalExpression(), diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 59804ff95..fb6c7eee5 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -24,6 +24,7 @@ struct cmGeneratorExpressionContext { cmListFileBacktrace Backtrace; std::set Targets; + std::set SeenTargetProperties; cmMakefile *Makefile; const char *Config; cmTarget *HeadTarget; // The target whose property is being evaluated. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 25054c536..e4adb09c3 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2164,16 +2164,19 @@ void cmTarget::GetDirectLinkLibraries(const char *config, { cmListFileBacktrace lfbt; cmGeneratorExpression ge(lfbt); + const cmsys::auto_ptr cge = ge.Parse(prop); cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), "LINK_LIBRARIES", 0, 0); - cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile, + cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile, config, false, head, &dagChecker), libs); + + this->AddLinkDependentTargetsForProperties(cge->GetSeenTargetProperties()); } } @@ -4376,6 +4379,43 @@ const char* cmTarget::GetExportMacro() } } +//---------------------------------------------------------------------------- +void cmTarget::GetLinkDependentTargetsForProperty(const std::string &p, + std::set &targets) +{ + const std::map >::const_iterator findIt + = this->LinkDependentProperties.find(p); + if (findIt != this->LinkDependentProperties.end()) + { + targets = findIt->second; + } +} + +//---------------------------------------------------------------------------- +bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) +{ + return this->LinkImplicitNullProperties.find(p) + != this->LinkImplicitNullProperties.end(); +} + +//---------------------------------------------------------------------------- +void cmTarget::AddLinkDependentTargetsForProperties( + const std::map &map) +{ + for (std::map::const_iterator it = map.begin(); + it != map.end(); ++it) + { + std::vector targets; + cmSystemTools::ExpandListArgument(it->second.c_str(), targets); + this->LinkDependentProperties[it->first].insert(targets.begin(), + targets.end()); + if (!this->GetProperty(it->first.c_str())) + { + this->LinkImplicitNullProperties.insert(it->first); + } + } +} + //---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set& languages) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index d4069fa01..5ce7d53c5 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -487,6 +487,13 @@ public: std::vector GetIncludeDirectories(const char *config); void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, bool before = false); + + void GetLinkDependentTargetsForProperty(const std::string &p, + std::set &targets); + bool IsNullImpliedByLinkLibraries(const std::string &p); + + void AddLinkDependentTargetsForProperties( + const std::map &map); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -596,6 +603,9 @@ private: bool DLLPlatform; bool IsApple; bool IsImportedTarget; + mutable std::map > + LinkDependentProperties; + mutable std::set LinkImplicitNullProperties; // Cache target output paths for each configuration. struct OutputInfo; From 042ecf0471be84ce6c3e6c32dae526fdbd9a3a14 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 6 Jan 2013 13:49:05 +0100 Subject: [PATCH 092/131] Add API to calculate link-interface-dependent bool properties or error. This new method checks that the property FOO on a target is consistent with the INTERFACE_FOO properties of its dependees. If they are not the consistent, an error is reported. 'Consistent' means that iff the property is set, it must have the same boolean value as all other related properties. --- Source/cmTarget.cxx | 128 ++++++++++++++++++++++++++++++++++++++++++++ Source/cmTarget.h | 3 ++ 2 files changed, 131 insertions(+) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e4adb09c3..c8f9c1ddb 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4416,6 +4416,134 @@ void cmTarget::AddLinkDependentTargetsForProperties( } } +//---------------------------------------------------------------------------- +bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config) +{ + bool propContent = this->GetPropertyAsBool(p.c_str()); + const bool explicitlySet = this->GetProperties() + .find(p.c_str()) + != this->GetProperties().end(); + std::set dependentTargets; + this->GetLinkDependentTargetsForProperty(p, + dependentTargets); + const bool impliedByUse = + this->IsNullImpliedByLinkLibraries(p); + assert((impliedByUse ^ explicitlySet) + || (!impliedByUse && !explicitlySet)); + + cmComputeLinkInformation *info = this->GetLinkInformation(config); + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + bool propInitialized = explicitlySet; + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + // An error should be reported if one dependency + // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other + // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the + // target itself has a POSITION_INDEPENDENT_CODE which disagrees + // with a dependency. + + if (!li->Target) + { + continue; + } + + const bool ifaceIsSet = li->Target->GetProperties() + .find("INTERFACE_" + p) + != li->Target->GetProperties().end(); + const bool ifacePropContent = li->Target->GetPropertyAsBool( + ("INTERFACE_" + p).c_str()); + if (explicitlySet) + { + if (ifaceIsSet) + { + if (propContent != ifacePropContent) + { + cmOStringStream e; + e << "Property " << p << " on target \"" + << this->GetName() << "\" does\nnot match the " + "INTERFACE_" << p << " property requirement\nof " + "dependency \"" << li->Target->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + } + else + { + // Agree + continue; + } + } + else + { + // Explicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else if (impliedByUse) + { + if (ifaceIsSet) + { + if (propContent != ifacePropContent) + { + cmOStringStream e; + e << "Property " << p << " on target \"" + << this->GetName() << "\" is\nimplied to be FALSE because it " + "was used to determine the link libraries\nalready. The " + "INTERFACE_" << p << " property on\ndependency \"" + << li->Target->GetName() << "\" is in conflict.\n"; + cmSystemTools::Error(e.str().c_str()); + } + else + { + // Agree + continue; + } + } + else + { + // Implicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else + { + if (ifaceIsSet) + { + if (propInitialized) + { + if (propContent != ifacePropContent) + { + cmOStringStream e; + e << "The INTERFACE_" << p << " property of \"" + << li->Target->GetName() << "\" does\nnot agree with the value " + "of " << p << " already determined\nfor \"" + << this->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + } + else + { + // Agree. + continue; + } + } + else + { + propContent = ifacePropContent; + propInitialized = true; + } + } + else + { + // Not set. Nothing to agree on. + continue; + } + } + } + return propContent; +} + //---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set& languages) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 5ce7d53c5..1188a6a6a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -494,6 +494,9 @@ public: void AddLinkDependentTargetsForProperties( const std::map &map); + + bool GetLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. From 9fdfe07411d8846f2adf0e46cf9046238c149d2b Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jan 2013 14:43:26 -0500 Subject: [PATCH 093/131] KWIML: Teach ABI about 'long long' on older GNU Old GNU compilers do not define __SIZEOF_LONG_LONG__ or __LONG_LONG_MAX__ but do provide a 64-bit 'long long' type. Suggested-by: Rolf Eike Beer --- ABI.h.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ABI.h.in b/ABI.h.in index 7f4772ae5..b71cdfb9f 100644 --- a/ABI.h.in +++ b/ABI.h.in @@ -253,7 +253,9 @@ suppression macro @KWIML@_ABI_NO_VERIFY was defined. # else # define @KWIML@_ABI_SIZEOF_LONG_LONG 0 # endif -# elif defined(__hpux) && !defined(__GNUC__) /* Old HP: no __HP_cc/__HP_aCC above */ +# elif defined(__GNUC__) /* GNU */ +# define @KWIML@_ABI_SIZEOF_LONG_LONG 8 +# elif defined(__hpux) /* Old HP: no __HP_cc/__HP_aCC/__GNUC__ above */ # define @KWIML@_ABI_SIZEOF_LONG_LONG 8 # endif #endif From 30c02f1bcf9c546d82401526cee697cd82b25443 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 9 Jan 2013 00:01:16 -0500 Subject: [PATCH 094/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 528fa13e6..d1b20971b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130108) +set(CMake_VERSION_TWEAK 20130109) #set(CMake_VERSION_RC 1) From 96c1a1b787155f98265bcac2338b25ad579faca0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 10 Jan 2013 00:01:20 -0500 Subject: [PATCH 095/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d1b20971b..f77d17c3f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130109) +set(CMake_VERSION_TWEAK 20130110) #set(CMake_VERSION_RC 1) From c8ee07d0adade6b838c0ee8e7c2549285a3b6b85 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 31 Dec 2012 00:55:38 +0100 Subject: [PATCH 096/131] FindQt4: Add INTERFACE includes and defines to Qt4 targets --- Modules/FindQt4.cmake | 26 ++++++++++++++++++++++++++ Tests/Qt4Targets/CMakeLists.txt | 11 +++++++++-- Tests/Qt4Targets/main.cpp | 8 ++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index 381141c5f..a9e9d82e7 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -418,6 +418,15 @@ macro (_QT4_ADJUST_LIB_VARS _camelCaseBasename) set_property(TARGET Qt4::${_camelCaseBasename} PROPERTY IMPORTED_LOCATION_DEBUG "${QT_${basename}_LIBRARY_DEBUG}" ) endif() endif () + set_property(TARGET Qt4::${_camelCaseBasename} PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + "${QT_${basename}_INCLUDE_DIR}" + ) + string(REGEX REPLACE "^QT" "" _stemname ${basename}) + set_property(TARGET Qt4::${_camelCaseBasename} PROPERTY + INTERFACE_COMPILE_DEFINITIONS + "QT_${_stemname}_LIB" + ) endif() # If QT_USE_IMPORTED_TARGETS is enabled, the QT_QTFOO_LIBRARY variables are set to point at these @@ -952,6 +961,14 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ${_PROPERTY} "Qt4::Qt${_DEPEND}" ) + set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + "$" + ) + set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS + "$" + ) endforeach() endif() endmacro() @@ -968,6 +985,11 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) # Set QT_xyz_LIBRARY variable and add # library include path to QT_INCLUDES _QT4_ADJUST_LIB_VARS(QtCore) + set_property(TARGET Qt4::QtCore APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + "${QT_MKSPECS_DIR}/default" + ${QT_INCLUDE_DIR} + ) foreach(QT_MODULE ${QT_MODULES}) _QT4_ADJUST_LIB_VARS(${QT_MODULE}) @@ -992,6 +1014,10 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) # headers. # Everything depends on QtCore, but that is covered above already _qt4_add_target_depends(Qt3Support Sql Gui Network) + if (TARGET Qt4::Qt3Support) + # An additional define is required for QT3_SUPPORT + set_property(TARGET Qt4::Qt3Support APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT3_SUPPORT) + endif() _qt4_add_target_depends(QtDeclarative Script Gui) _qt4_add_target_depends(QtDesigner Gui) _qt4_add_target_depends(QtHelp Gui) diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt index 3adff48fd..9bd7a6478 100644 --- a/Tests/Qt4Targets/CMakeLists.txt +++ b/Tests/Qt4Targets/CMakeLists.txt @@ -4,11 +4,18 @@ project(Qt4Targets) find_package(Qt4 REQUIRED) -include_directories(${QT_INCLUDES}) - add_executable(Qt4Targets WIN32 main.cpp) target_link_libraries(Qt4Targets Qt4::QtGui) if (WIN32) target_link_libraries(Qt4Targets Qt4::qtmain) endif() + +set_property(TARGET Qt4Targets APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) +set_property(TARGET Qt4Targets APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) diff --git a/Tests/Qt4Targets/main.cpp b/Tests/Qt4Targets/main.cpp index f4890fa9e..3c98c99f6 100644 --- a/Tests/Qt4Targets/main.cpp +++ b/Tests/Qt4Targets/main.cpp @@ -4,6 +4,14 @@ #include +#ifndef QT_CORE_LIB +#error Expected QT_CORE_LIB +#endif + +#ifndef QT_GUI_LIB +#error Expected QT_GUI_LIB +#endif + int main(int argc, char **argv) { QApplication app(argc, argv); From 8a37ebec784cefe4f04cb8897c23a014c3930052 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 1 Jan 2013 23:20:04 +0100 Subject: [PATCH 097/131] Add the target_include_directories command. This is a convenience API to populate the corresponding properties. --- Source/cmCommands.cxx | 3 + Source/cmTargetIncludeDirectoriesCommand.cxx | 74 +++++++++ Source/cmTargetIncludeDirectoriesCommand.h | 95 ++++++++++++ Source/cmTargetPropCommandBase.cxx | 144 ++++++++++++++++++ Source/cmTargetPropCommandBase.h | 57 +++++++ .../target_include_directories/CMakeLists.txt | 50 ++++++ .../target_include_directories/consumer.cpp | 27 ++++ .../target_include_directories/main.cpp | 22 +++ Tests/CMakeLists.txt | 1 + 9 files changed, 473 insertions(+) create mode 100644 Source/cmTargetIncludeDirectoriesCommand.cxx create mode 100644 Source/cmTargetIncludeDirectoriesCommand.h create mode 100644 Source/cmTargetPropCommandBase.cxx create mode 100644 Source/cmTargetPropCommandBase.h create mode 100644 Tests/CMakeCommands/target_include_directories/CMakeLists.txt create mode 100644 Tests/CMakeCommands/target_include_directories/consumer.cpp create mode 100644 Tests/CMakeCommands/target_include_directories/main.cpp diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 49ed96795..6b315ea81 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -28,6 +28,8 @@ #include "cmRemoveDefinitionsCommand.cxx" #include "cmSourceGroupCommand.cxx" #include "cmSubdirDependsCommand.cxx" +#include "cmTargetIncludeDirectoriesCommand.cxx" +#include "cmTargetPropCommandBase.cxx" #include "cmUseMangledMesaCommand.cxx" #include "cmUtilitySourceCommand.cxx" #include "cmVariableRequiresCommand.cxx" @@ -66,6 +68,7 @@ void GetPredefinedCommands(std::list& commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSourceGroupCommand); commands.push_back(new cmSubdirDependsCommand); + commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmUseMangledMesaCommand); commands.push_back(new cmUtilitySourceCommand); commands.push_back(new cmVariableRequiresCommand); diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx new file mode 100644 index 000000000..18e2cba4e --- /dev/null +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -0,0 +1,74 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetIncludeDirectoriesCommand.h" + +#include "cmMakefileIncludeDirectoriesEntry.h" + +//---------------------------------------------------------------------------- +bool cmTargetIncludeDirectoriesCommand +::InitialPass(std::vector const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE); +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleImportedTargetInvalidScope(const std::string &tgt, + const std::string &scope) +{ + cmOStringStream e; + e << "Cannot specify " << scope << " include directories for imported " + "target \"" << tgt << "\". Include directories can only be " + "specified for an imported target in the INTERFACE mode."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify include directories for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +bool cmTargetIncludeDirectoriesCommand +::HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt) +{ + if (!cmSystemTools::FileIsFullPath(entry.c_str())) + { + cmOStringStream e; + e << "Cannot specify relative include directory \"" << entry << "\" for " + "target \"" << tgt << "\". Only absolute paths are permitted"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + content += sep + entry; + return true; +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleDirectContent(cmTarget *tgt, const std::string &content, + bool prepend) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmMakefileIncludeDirectoriesEntry entry(content, lfbt); + tgt->InsertInclude(entry, prepend); +} diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h new file mode 100644 index 000000000..c1957d6d9 --- /dev/null +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -0,0 +1,95 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetIncludeDirectoriesCommand_h +#define cmTargetIncludeDirectoriesCommand_h + +#include "cmTargetPropCommandBase.h" + +//---------------------------------------------------------------------------- +class cmTargetIncludeDirectoriesCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetIncludeDirectoriesCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_include_directories";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add include directories to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_include_directories( [BEFORE] " + " [items1...]\n" + " [ [items2...] ...])\n" + "Specify include directories or targets to use when compiling a given " + "target. " + "The named must have been created by a command such as " + "add_executable or add_library.\n" + "If BEFORE is specified, the content will be prepended to the property " + "instead of being appended.\n" + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the INCLUDE_DIRECTORIES property of . PUBLIC and " + "INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES " + "property of . " + "The non-scope arguments specify either include directories or targets " + "to use INTERFACE_INCLUDE_DIRECTORIES from. Any specified include " + "directories must be absolute paths, not relative paths. " + "Repeated calls for the same append items in the order called." + "\n" + ; + } + + cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand); + +private: + virtual void HandleImportedTargetInvalidScope(const std::string &tgt, + const std::string &scope); + virtual void HandleMissingTarget(const std::string &name); + + virtual bool HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt); + + virtual void HandleDirectContent(cmTarget *tgt, const std::string &content, + bool prepend); +}; + +#endif diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx new file mode 100644 index 000000000..69aaf1777 --- /dev/null +++ b/Source/cmTargetPropCommandBase.cxx @@ -0,0 +1,144 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetPropCommandBase.h" + +#include "cmGlobalGenerator.h" + +//---------------------------------------------------------------------------- +bool cmTargetPropCommandBase +::HandleArguments(std::vector const& args, const char *prop, + ArgumentFlags flags) +{ + if(args.size() < 3) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + // Lookup the target for which libraries are specified. + this->Target = + this->Makefile->GetCMakeInstance() + ->GetGlobalGenerator()->FindTarget(0, args[0].c_str()); + if(!this->Target) + { + this->Target = this->Makefile->FindTargetToUse(args[0].c_str()); + } + if(!this->Target) + { + this->HandleMissingTarget(args[0]); + return false; + } + + unsigned int argIndex = 1; + + bool prepend = false; + if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") + { + if (args.size() < 4) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + prepend = true; + ++argIndex; + } + + this->Property = prop; + + while (argIndex < args.size()) + { + if (!this->ProcessContentArgs(args, argIndex, prepend)) + { + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmTargetPropCommandBase +::ProcessContentArgs(std::vector const& args, + unsigned int &argIndex, bool prepend) +{ + const std::string scope = args[argIndex]; + + if(scope != "PUBLIC" + && scope != "PRIVATE" + && scope != "INTERFACE" ) + { + this->SetError("called with invalid arguments"); + return false; + } + + if(this->Target->IsImported() && scope != "INTERFACE") + { + this->HandleImportedTargetInvalidScope(args[0], scope); + return false; + } + + ++argIndex; + + std::string content; + + std::string sep; + for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex) + { + if(args[i] == "PUBLIC" + || args[i] == "PRIVATE" + || args[i] == "INTERFACE" ) + { + this->PopulateTargetProperies(scope, content, prepend); + return true; + } + if (this->Makefile->FindTargetToUse(args[i].c_str())) + { + content += sep + "$Property + ">"; + } + else if (!this->HandleNonTargetArg(content, sep, args[i], args[0])) + { + return false; + } + sep = ";"; + } + this->PopulateTargetProperies(scope, content, prepend); + return true; +} + +//---------------------------------------------------------------------------- +void cmTargetPropCommandBase +::PopulateTargetProperies(const std::string &scope, + const std::string &content, bool prepend) +{ + if (scope == "PRIVATE" || scope == "PUBLIC") + { + this->HandleDirectContent(this->Target, content, prepend); + } + if (scope == "INTERFACE" || scope == "PUBLIC") + { + if (prepend) + { + const std::string propName = std::string("INTERFACE_") + this->Property; + const char *propValue = this->Target->GetProperty(propName.c_str()); + const std::string totalContent = content + (propValue + ? std::string(";") + propValue + : std::string()); + this->Target->SetProperty(propName.c_str(), totalContent.c_str()); + } + else + { + this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(), + content.c_str()); + } + } +} diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h new file mode 100644 index 000000000..90e3bbb7f --- /dev/null +++ b/Source/cmTargetPropCommandBase.h @@ -0,0 +1,57 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetPropCommandBase_h +#define cmTargetPropCommandBase_h + +#include "cmCommand.h" + +class cmTarget; + +//---------------------------------------------------------------------------- +class cmTargetPropCommandBase : public cmCommand +{ +public: + + enum ArgumentFlags { + NO_FLAGS = 0, + PROCESS_BEFORE = 1 + }; + + bool HandleArguments(std::vector const& args, + const char *prop, ArgumentFlags flags = NO_FLAGS); + +private: + virtual void HandleImportedTargetInvalidScope(const std::string &tgt, + const std::string &scope) = 0; + virtual void HandleMissingTarget(const std::string &name) = 0; + + virtual bool HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt) = 0; + + virtual void HandleDirectContent(cmTarget *tgt, + const std::string &content, + bool prepend) = 0; + + bool ProcessContentArgs(std::vector const& args, + unsigned int &argIndex, bool prepend); + void PopulateTargetProperies(const std::string &scope, + const std::string &content, bool prepend); + +private: + cmTarget *Target; + std::string Property; +}; + +#endif diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt new file mode 100644 index 000000000..a0f2ee08c --- /dev/null +++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 2.8) + +project(target_include_directories) + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/privateinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/privateinclude/privateinclude.h" "#define PRIVATEINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/publicinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicinclude/publicinclude.h" "#define PUBLICINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude/interfaceinclude.h" "#define INTERFACEINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude/importedinterfaceinclude.h" "#define IMPORTEDINTERFACEINCLUDE_DEFINE\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/poison") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be included\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cure") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cure/common.h" "#define CURE_DEFINE\n") + +add_executable(target_include_directories + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_include_directories(target_include_directories + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/privateinclude" + PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/publicinclude" + INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude" +) + +target_include_directories(target_include_directories + PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/poison" +) +target_include_directories(target_include_directories + BEFORE PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cure" +) + +add_library(importedlib UNKNOWN IMPORTED) +target_include_directories(importedlib + INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude" +) + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_include_directories(consumer + PRIVATE target_include_directories importedlib +) diff --git a/Tests/CMakeCommands/target_include_directories/consumer.cpp b/Tests/CMakeCommands/target_include_directories/consumer.cpp new file mode 100644 index 000000000..6fd61d5b7 --- /dev/null +++ b/Tests/CMakeCommands/target_include_directories/consumer.cpp @@ -0,0 +1,27 @@ + +#include "common.h" +#include "publicinclude.h" +#include "interfaceinclude.h" +#include "importedinterfaceinclude.h" + +#ifdef PRIVATEINCLUDE_DEFINE +#error Unexpected PRIVATEINCLUDE_DEFINE +#endif + +#ifndef PUBLICINCLUDE_DEFINE +#error Expected PUBLICINCLUDE_DEFINE +#endif + +#ifndef INTERFACEINCLUDE_DEFINE +#error Expected INTERFACEINCLUDE_DEFINE +#endif + +#ifndef IMPORTEDINTERFACEINCLUDE_DEFINE +#error Expected IMPORTEDINTERFACEINCLUDE_DEFINE +#endif + +#ifndef CURE_DEFINE +#error Expected CURE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_include_directories/main.cpp b/Tests/CMakeCommands/target_include_directories/main.cpp new file mode 100644 index 000000000..8434b97d8 --- /dev/null +++ b/Tests/CMakeCommands/target_include_directories/main.cpp @@ -0,0 +1,22 @@ + +#include "common.h" +#include "privateinclude.h" +#include "publicinclude.h" + +#ifndef PRIVATEINCLUDE_DEFINE +#error Expected PRIVATEINCLUDE_DEFINE +#endif + +#ifndef PUBLICINCLUDE_DEFINE +#error Expected PUBLICINCLUDE_DEFINE +#endif + +#ifdef INTERFACEINCLUDE_DEFINE +#error Unexpected INTERFACEINCLUDE_DEFINE +#endif + +#ifndef CURE_DEFINE +#error Expected CURE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index ade6a012a..2dced5fae 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1930,6 +1930,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ) ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) + ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories) configure_file( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in" From fc61a7a746c3c899d42ccff3014686365c36ee11 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 8 Jan 2013 00:34:41 +0100 Subject: [PATCH 098/131] Add the target_compile_definitions command. This is a convenience API to populate the corresponding properties. --- Source/cmCommands.cxx | 2 + Source/cmTargetCompileDefinitionsCommand.cxx | 57 ++++++++++++ Source/cmTargetCompileDefinitionsCommand.h | 91 +++++++++++++++++++ .../target_compile_definitions/CMakeLists.txt | 26 ++++++ .../target_compile_definitions/consumer.cpp | 18 ++++ .../target_compile_definitions/main.cpp | 14 +++ Tests/CMakeLists.txt | 1 + 7 files changed, 209 insertions(+) create mode 100644 Source/cmTargetCompileDefinitionsCommand.cxx create mode 100644 Source/cmTargetCompileDefinitionsCommand.h create mode 100644 Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt create mode 100644 Tests/CMakeCommands/target_compile_definitions/consumer.cpp create mode 100644 Tests/CMakeCommands/target_compile_definitions/main.cpp diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 6b315ea81..227b22678 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -28,6 +28,7 @@ #include "cmRemoveDefinitionsCommand.cxx" #include "cmSourceGroupCommand.cxx" #include "cmSubdirDependsCommand.cxx" +#include "cmTargetCompileDefinitionsCommand.cxx" #include "cmTargetIncludeDirectoriesCommand.cxx" #include "cmTargetPropCommandBase.cxx" #include "cmUseMangledMesaCommand.cxx" @@ -69,6 +70,7 @@ void GetPredefinedCommands(std::list& commands.push_back(new cmSourceGroupCommand); commands.push_back(new cmSubdirDependsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); + commands.push_back(new cmTargetCompileDefinitionsCommand); commands.push_back(new cmUseMangledMesaCommand); commands.push_back(new cmUtilitySourceCommand); commands.push_back(new cmVariableRequiresCommand); diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx new file mode 100644 index 000000000..492a1b7d0 --- /dev/null +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -0,0 +1,57 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 "cmTargetCompileDefinitionsCommand.h" + +#include "cmMakefileIncludeDirectoriesEntry.h" + +bool cmTargetCompileDefinitionsCommand +::InitialPass(std::vector const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "COMPILE_DEFINITIONS"); +} + +void cmTargetCompileDefinitionsCommand +::HandleImportedTargetInvalidScope(const std::string &scope, + const std::string &tgt) +{ + cmOStringStream e; + e << "Cannot specify " << scope << " compile definitions for imported " + "target \"" << tgt << "\". Compile definitions can only be " + "specified for an imported target in the INTERFACE mode."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +void cmTargetCompileDefinitionsCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify compile definitions for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +bool cmTargetCompileDefinitionsCommand +::HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &) +{ + content += sep + entry; + return true; +} + +void cmTargetCompileDefinitionsCommand +::HandleDirectContent(cmTarget *tgt, const std::string &content, + bool) +{ + tgt->AppendProperty("COMPILE_DEFINITIONS", content.c_str()); +} diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h new file mode 100644 index 000000000..707610e3e --- /dev/null +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -0,0 +1,91 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + 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 cmTargetCompileDefinitionsCommand_h +#define cmTargetCompileDefinitionsCommand_h + +#include "cmTargetPropCommandBase.h" + +class cmTargetCompileDefinitionsCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetCompileDefinitionsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_compile_definitions";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add compile definitions to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_compile_definitions( " + " [items1...]\n" + " [ [items2...] ...])\n" + "Specify compile definitions or targets to use when compiling a given " + "target. " + "The named must have been created by a command such as " + "add_executable or add_library. " + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the COMPILE_DEFINITIONS property of . PUBLIC and " + "INTERFACE items will populate the INTERFACE_COMPILE_DEFINITIONS " + "property of . " + "The non-scope arguments specify compile definitions or targets to use " + "INTERFACE_COMPILE_DEFINITIONS from. " + "Repeated calls for the same append items in the order called." + "\n" + ; + } + + cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand); + +private: + virtual void HandleImportedTargetInvalidScope(const std::string &scope, + const std::string &tgt); + virtual void HandleMissingTarget(const std::string &name); + + virtual bool HandleNonTargetArg(std::string &content, + const std::string &sep, + const std::string &entry, + const std::string &tgt); + + virtual void HandleDirectContent(cmTarget *tgt, const std::string &content, + bool prepend); +}; + +#endif diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt new file mode 100644 index 000000000..84a23efc3 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt @@ -0,0 +1,26 @@ + +cmake_minimum_required(VERSION 2.8) + +project(target_compile_definitions) + +add_executable(target_compile_definitions + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_compile_definitions(target_compile_definitions + PRIVATE MY_PRIVATE_DEFINE + PUBLIC MY_PUBLIC_DEFINE + INTERFACE MY_INTERFACE_DEFINE +) + +add_library(importedlib UNKNOWN IMPORTED) +target_compile_definitions(importedlib + INTERFACE MY_IMPORTEDINTERFACE_DEFINE +) + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_compile_definitions(consumer + PRIVATE target_compile_definitions importedlib +) diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp new file mode 100644 index 000000000..e3788ddb2 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp @@ -0,0 +1,18 @@ + +#ifdef MY_PRIVATE_DEFINE +#error Unexpected MY_PRIVATE_DEFINE +#endif + +#ifndef MY_PUBLIC_DEFINE +#error Expected MY_PUBLIC_DEFINE +#endif + +#ifndef MY_INTERFACE_DEFINE +#error Expected MY_INTERFACE_DEFINE +#endif + +#ifndef MY_IMPORTEDINTERFACE_DEFINE +#error Expected MY_IMPORTEDINTERFACE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_compile_definitions/main.cpp b/Tests/CMakeCommands/target_compile_definitions/main.cpp new file mode 100644 index 000000000..addb33cf9 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_definitions/main.cpp @@ -0,0 +1,14 @@ + +#ifndef MY_PRIVATE_DEFINE +#error Expected MY_PRIVATE_DEFINE +#endif + +#ifndef MY_PUBLIC_DEFINE +#error Expected MY_PUBLIC_DEFINE +#endif + +#ifdef MY_INTERFACE_DEFINE +#error Unexpected MY_INTERFACE_DEFINE +#endif + +int main() { return 0; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 2dced5fae..2f7df01cf 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1931,6 +1931,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories) + ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions) configure_file( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in" From 3581b96caa1d7bd6c02e85baf72ce28b5128e5e7 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 5 Nov 2012 12:46:26 +0100 Subject: [PATCH 099/131] Process the INTERFACE_PIC property from linked dependencies This allows a dependee to inform a target that it should have its POSITION_INDEPENDENT_CODE property set to ON, or OFF. The value of the POSITION_INDEPENDENT_CODE property, if set, must be consistent with any INTERFACE_POSITION_INDEPENDENT_CODE properties on dependees. Add a test covering the consistency checks on platforms where they run. --- Source/cmGlobalXCodeGenerator.cxx | 6 ++++-- Source/cmLocalGenerator.cxx | 17 ++++++++++++++--- Source/cmLocalGenerator.h | 2 +- Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cmNinjaTargetGenerator.cxx | 3 ++- Source/cmTarget.cxx | 14 ++++++++++++++ Tests/RunCMake/CMakeLists.txt | 3 +++ .../PositionIndependentCode/CMakeLists.txt | 8 ++++++++ .../Conflict1-result.txt | 1 + .../Conflict1-stderr.txt | 3 +++ .../PositionIndependentCode/Conflict1.cmake | 7 +++++++ .../Conflict2-result.txt | 1 + .../Conflict2-stderr.txt | 3 +++ .../PositionIndependentCode/Conflict2.cmake | 9 +++++++++ .../Conflict3-result.txt | 1 + .../Conflict3-stderr.txt | 4 ++++ .../PositionIndependentCode/Conflict3.cmake | 12 ++++++++++++ .../PositionIndependentCode/RunCMakeTest.cmake | 5 +++++ Tests/RunCMake/PositionIndependentCode/main.cpp | 5 +++++ 19 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 Tests/RunCMake/PositionIndependentCode/CMakeLists.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict1.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict2.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Conflict3.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/main.cpp diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 4c26b829b..2cfe4daba 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1639,14 +1639,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, if(strcmp(lang, "CXX") == 0) { this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName); - this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C"); + this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, + "C", configName); } // Add language-specific flags. this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName); // Add shared-library flags if needed. - this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang); + this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, + lang, configName); } else if(binary) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index b557ca19b..ecf6b413a 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1984,7 +1984,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, //---------------------------------------------------------------------------- void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, - std::string const& lang) + std::string const& lang, + const char *config) { int targetType = target->GetType(); @@ -1997,8 +1998,18 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, } else { - // Add position independendent flags, if needed. - if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) + if (target->GetType() == cmTarget::OBJECT_LIBRARY) + { + if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) + { + this->AddPositionIndependentFlags(flags, lang, targetType); + } + return; + } + + if (target->GetLinkInterfaceDependentBoolProperty( + "POSITION_INDEPENDENT_CODE", + config)) { this->AddPositionIndependentFlags(flags, lang, targetType); } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 63559d750..b2ff0c48f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -142,7 +142,7 @@ public: void AddLanguageFlags(std::string& flags, const char* lang, const char* config); void AddCMP0018Flags(std::string &flags, cmTarget* target, - std::string const& lang); + std::string const& lang, const char *config); void AddConfigVariableFlags(std::string& flags, const char* var, const char* config); ///! Append flags to a string. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 9bf6b7d9e..64fcfcefa 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -268,7 +268,8 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) this->AddFortranFlags(flags); } - this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang); + this->LocalGenerator->AddCMP0018Flags(flags, this->Target, + lang, this->ConfigName); // Add include directory flags. this->AddIncludeFlags(flags, lang); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 15842e44f..0f484da4c 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -147,7 +147,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, // Add shared-library flags if needed. this->LocalGenerator->AddCMP0018Flags(flags, this->Target, - language.c_str()); + language.c_str(), + this->GetConfigName()); // Add include directory flags. { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c8f9c1ddb..2cfb1bfd5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -877,6 +877,20 @@ void cmTarget::DefineProperties(cmake *cm) "CMAKE_POSITION_INDEPENDENT_CODE if it is set when a target is " "created."); + cm->DefineProperty + ("INTERFACE_POSITION_INDEPENDENT_CODE", cmProperty::TARGET, + "Whether consumers need to create a position-independent target", + "The INTERFACE_POSITION_INDEPENDENT_CODE property informs consumers of " + "this target whether they must set their POSITION_INDEPENDENT_CODE " + "property to ON. If this property is set to ON, then the " + "POSITION_INDEPENDENT_CODE property on all consumers will be set to " + "ON. Similarly, if this property is set to OFF, then the " + "POSITION_INDEPENDENT_CODE property on all consumers will be set to " + "OFF. If this property is undefined, then consumers will determine " + "their POSITION_INDEPENDENT_CODE property by other means. Consumers " + "must ensure that the targets that they link to have a consistent " + "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property."); + cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index fec64b57c..9b133b299 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -50,6 +50,9 @@ add_RunCMake_test(GeneratorExpression) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(ObjectLibrary) +if(NOT WIN32) + add_RunCMake_test(PositionIndependentCode) +endif() add_RunCMake_test(build_command) add_RunCMake_test(find_package) diff --git a/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt new file mode 100644 index 000000000..22577da4a --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt @@ -0,0 +1,8 @@ + +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} CXX) + +# MSVC creates extra targets which pollute the stderr unless we set this. +set(CMAKE_SUPPRESS_REGENERATION TRUE) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt new file mode 100644 index 000000000..cb0710986 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict1-stderr.txt @@ -0,0 +1,3 @@ +CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict" does +not match the INTERFACE_POSITION_INDEPENDENT_CODE property requirement +of dependency "piciface". diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict1.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict1.cmake new file mode 100644 index 000000000..242bec37a --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict1.cmake @@ -0,0 +1,7 @@ + +add_library(piciface UNKNOWN IMPORTED) +set_property(TARGET piciface PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) + +add_executable(conflict "main.cpp") +set_property(TARGET conflict PROPERTY POSITION_INDEPENDENT_CODE OFF) +target_link_libraries(conflict piciface) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt new file mode 100644 index 000000000..ecd04928d --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict2-stderr.txt @@ -0,0 +1,3 @@ +CMake Error: The INTERFACE_POSITION_INDEPENDENT_CODE property of "picoff" does +not agree with the value of POSITION_INDEPENDENT_CODE already determined +for "conflict". diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict2.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict2.cmake new file mode 100644 index 000000000..215d08dae --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict2.cmake @@ -0,0 +1,9 @@ + +add_library(picon UNKNOWN IMPORTED) +set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) + +add_library(picoff UNKNOWN IMPORTED) +set_property(TARGET picoff PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF) + +add_executable(conflict "main.cpp") +target_link_libraries(conflict picon picoff) diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt b/Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt new file mode 100644 index 000000000..0254e5557 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict3-stderr.txt @@ -0,0 +1,4 @@ +Property POSITION_INDEPENDENT_CODE on target "conflict" is +implied to be FALSE because it was used to determine the link libraries +already. The INTERFACE_POSITION_INDEPENDENT_CODE property on +dependency "picon" is in conflict. diff --git a/Tests/RunCMake/PositionIndependentCode/Conflict3.cmake b/Tests/RunCMake/PositionIndependentCode/Conflict3.cmake new file mode 100644 index 000000000..bf669bf4f --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Conflict3.cmake @@ -0,0 +1,12 @@ + +add_library(picoff UNKNOWN IMPORTED) + +add_library(picon UNKNOWN IMPORTED) +set_property(TARGET picon PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) + +add_executable(conflict "main.cpp") +target_link_libraries(conflict picon) +set_property(TARGET conflict APPEND PROPERTY + LINK_LIBRARIES + $<$>>:picoff> +) diff --git a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake new file mode 100644 index 000000000..64a340c9c --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(Conflict1) +run_cmake(Conflict2) +run_cmake(Conflict3) diff --git a/Tests/RunCMake/PositionIndependentCode/main.cpp b/Tests/RunCMake/PositionIndependentCode/main.cpp new file mode 100644 index 000000000..31ba48280 --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/main.cpp @@ -0,0 +1,5 @@ + +int main(int,char**) +{ + return 0; +} From 93034a8350102e308fa5bca8d89bf3f6fae12771 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 10 Jan 2013 17:11:12 +0100 Subject: [PATCH 100/131] Fix linking to imported libraries test. Make a C executable instead of attempting to make a C++ static library (and not really succeeding). This was introduced in commit 894f52f3 (Handle INTERFACE properties transitively for includes and defines., 2012-09-23). --- Tests/ExportImport/Import/A/CMakeLists.txt | 4 ++-- Tests/ExportImport/Import/A/{deps_iface.cpp => deps_iface.c} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename Tests/ExportImport/Import/A/{deps_iface.cpp => deps_iface.c} (94%) diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index b77562ee6..56cfea031 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -157,8 +157,8 @@ endif() # Test that dependent imported targets have usable # INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES -add_library(deps_iface deps_iface.cpp) -target_link_libraries(deps_iface testLibsDepends) +add_executable(deps_iface deps_iface.c) +target_link_libraries(deps_iface testLibDepends) set_property(TARGET deps_iface APPEND PROPERTY COMPILE_DEFINITIONS $ diff --git a/Tests/ExportImport/Import/A/deps_iface.cpp b/Tests/ExportImport/Import/A/deps_iface.c similarity index 94% rename from Tests/ExportImport/Import/A/deps_iface.cpp rename to Tests/ExportImport/Import/A/deps_iface.c index 7190b9242..e73ca26bf 100644 --- a/Tests/ExportImport/Import/A/deps_iface.cpp +++ b/Tests/ExportImport/Import/A/deps_iface.c @@ -18,7 +18,7 @@ extern int testLibDepends(void); -int main(int,char **) +int main() { return testLibDepends(); } From f99196dc0cde6e5868cc74c603a78b10f1ba324a Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 10 Dec 2012 12:00:34 +0100 Subject: [PATCH 101/131] Add cmGeneratorExpression::Split() API. It can split a string like "A;$<1:B>;$<1:C>;D;E;$<1:F;G;H>;$<1:I>;J" into "A" "$<1:B>" "$<1:C>" "D" "E" "$<1:F;G;H>" "$<1:I>" "J" --- Source/cmGeneratorExpression.cxx | 61 ++++++++++++++++++++++++++++++++ Source/cmGeneratorExpression.h | 3 ++ 2 files changed, 64 insertions(+) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 4063697cd..d306dee6d 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -250,6 +250,67 @@ static std::string stripExportInterface(const std::string &input, return result; } +//---------------------------------------------------------------------------- +void cmGeneratorExpression::Split(const std::string &input, + std::vector &output) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + while((pos = input.find("$<", lastPos)) != input.npos) + { + std::string part = input.substr(lastPos, pos - lastPos); + std::string preGenex; + if (!part.empty()) + { + std::string::size_type startPos = input.rfind(";", pos); + if (startPos != pos - 1 && startPos >= lastPos) + { + part = input.substr(lastPos, startPos - lastPos); + preGenex = input.substr(startPos + 1, pos - startPos - 1); + } + cmSystemTools::ExpandListArgument(part.c_str(), output); + } + 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; + } + } + } + for ( ; *c; ++c) + { + // Capture the part after the genex and before the next ';' + if(c[0] == ';') + { + --c; + break; + } + } + const std::string::size_type traversed = (c - cStart) + 1; + output.push_back(preGenex + "$<" + input.substr(pos, traversed)); + pos += traversed; + lastPos = pos; + } + if (lastPos < input.size()) + { + cmSystemTools::ExpandListArgument(input.substr(lastPos), output); + } +} + //---------------------------------------------------------------------------- std::string cmGeneratorExpression::Preprocess(const std::string &input, PreprocessContext context) diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index b58dde52b..8f1aef677 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -59,6 +59,9 @@ public: static std::string Preprocess(const std::string &input, PreprocessContext context); + static void Split(const std::string &input, + std::vector &output); + private: cmGeneratorExpression(const cmGeneratorExpression &); void operator=(const cmGeneratorExpression &); From cb1afbf466d126f233e93b2cdfa3f5c5dfe5b8f7 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 8 Jan 2013 21:06:24 +0100 Subject: [PATCH 102/131] Don't pass a position when determining if a target name is a literal. The lastPos refers to a position in a different string. --- Source/cmExportFileGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 90c0c4111..56b088e83 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -270,7 +270,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( } const std::string targetName = input.substr(nameStartPos, endPos - nameStartPos); - if(targetName.find("$<", lastPos) != input.npos) + if(targetName.find("$<") != input.npos) { errorString = "$ requires its parameter to be a " "literal."; From b6036d104a95156e8524dbfeb5533d3a579d8837 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 8 Jan 2013 20:58:33 +0100 Subject: [PATCH 103/131] Extract the AddTargetNamespace method. --- Source/cmExportFileGenerator.cxx | 143 +++++++++++-------------------- Source/cmExportFileGenerator.h | 4 + 2 files changed, 52 insertions(+), 95 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 56b088e83..da1885668 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -183,6 +183,41 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, } } +//---------------------------------------------------------------------------- +bool +cmExportFileGenerator::AddTargetNamespace(std::string &input, + cmTarget* target, + std::vector &missingTargets) +{ + cmMakefile *mf = target->GetMakefile(); + + cmTarget *tgt = mf->FindTargetToUse(input.c_str()); + if (!tgt) + { + return false; + } + + if(tgt->IsImported()) + { + return true; + } + if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) + { + input = this->Namespace + input; + } + else + { + std::string namespacedTarget; + this->HandleMissingTarget(namespacedTarget, missingTargets, + mf, target, tgt); + if (!namespacedTarget.empty()) + { + input = namespacedTarget; + } + } + return true; +} + //---------------------------------------------------------------------------- void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( @@ -212,45 +247,17 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( continue; } - const std::string targetName = input.substr(nameStartPos, + std::string targetName = input.substr(nameStartPos, commaPos - nameStartPos); - pos = nameStartPos; // We're not going to replace the entire expression, - // but only the target parameter. - if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) - { - if(tgt->IsImported()) - { - pos += targetName.size(); - } - else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) - { - input.replace(pos, targetName.size(), - this->Namespace + targetName); - pos += this->Namespace.size() + targetName.size(); - } - else - { - std::string namespacedTarget; - this->HandleMissingTarget(namespacedTarget, missingTargets, - mf, target, tgt); - if (!namespacedTarget.empty()) - { - input.replace(pos, targetName.size(), namespacedTarget); - pos += namespacedTarget.size(); - } - } - } - else + if (!this->AddTargetNamespace(targetName, target, missingTargets)) { errorString = "$ requires " "its first parameter to be a reachable target."; - } - lastPos = pos; - if (!errorString.empty()) - { break; } + input.replace(nameStartPos, commaPos - nameStartPos, targetName); + lastPos = pos + targetName.size(); } if (!errorString.empty()) { @@ -267,51 +274,24 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( if (endPos == input.npos) { errorString = "$ expression incomplete"; + break; } - const std::string targetName = input.substr(nameStartPos, + std::string targetName = input.substr(nameStartPos, endPos - nameStartPos); if(targetName.find("$<") != input.npos) { errorString = "$ requires its parameter to be a " "literal."; + break; } - if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) - { - if(tgt->IsImported()) - { - input.replace(pos, sizeof("$ExportedTargets.find(tgt) != this->ExportedTargets.end()) - { - input.replace(pos, sizeof("$Namespace + targetName); - pos += sizeof("$HandleMissingTarget(namespacedTarget, missingTargets, - mf, target, tgt); - if (!namespacedTarget.empty()) - { - input.replace(pos, sizeof("$AddTargetNamespace(targetName, target, missingTargets)) { errorString = "$ requires its parameter to be a " "reachable target."; - } - lastPos = pos; - if (!errorString.empty()) - { break; } + input.replace(pos, endPos - pos + 1, targetName); + lastPos = endPos; } if (!errorString.empty()) { @@ -397,9 +377,6 @@ cmExportFileGenerator return; } - // Get the makefile in which to lookup target information. - cmMakefile* mf = target->GetMakefile(); - // Construct the property value. std::string link_libs; const char* sep = ""; @@ -410,33 +387,9 @@ cmExportFileGenerator link_libs += sep; sep = ";"; - // Append this entry. - if(cmTarget* tgt = mf->FindTargetToUse(li->c_str())) - { - // This is a target. - if(tgt->IsImported()) - { - // The target is imported (and therefore is not in the - // export). Append the raw name. - link_libs += *li; - } - else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) - { - // The target is in the export. Append it with the export - // namespace. - link_libs += this->Namespace; - link_libs += *li; - } - else - { - this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt); - } - } - else - { - // Append the raw name. - link_libs += *li; - } + std::string temp = *li; + this->AddTargetNamespace(temp, target, missingTargets); + link_libs += temp; } // Store the property. diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 7c58ad8b4..a5b25f49c 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -128,6 +128,10 @@ private: cmGeneratorExpression::PreprocessContext, ImportPropertyMap &properties, std::vector &missingTargets); + + bool AddTargetNamespace(std::string &input, cmTarget* target, + std::vector &missingTargets); + }; #endif From a3aedb8152ad6fcdb42fd04e45307eea6ce0043e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 4 Jan 2013 15:56:13 +0100 Subject: [PATCH 104/131] Split the generator expression before extracting targets. Now that we're processing a LINK_INTERFACE_LIBRARIES string, it can contain targets. Make sure they are extracted for namespacing purposes. This needs to be restricted to strings which can actually have targets named in them. For example, this is not done for INTERFACE_COMPILE_DEFINITIONS, because even if there is a target named 'foo', the string 'foo' in that property means that '-Dfoo' will be set when compiling. --- Source/cmExportFileGenerator.cxx | 45 ++++++++++++++++++++++++++++++++ Source/cmExportFileGenerator.h | 14 ++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index da1885668..df8f3e8d1 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -218,9 +218,54 @@ cmExportFileGenerator::AddTargetNamespace(std::string &input, return true; } +//---------------------------------------------------------------------------- +static bool isGeneratorExpression(const std::string &lib) +{ + const std::string::size_type openpos = lib.find("$<"); + return (openpos != std::string::npos) + && (lib.find(">", openpos) != std::string::npos); +} + //---------------------------------------------------------------------------- void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( + std::string &input, + cmTarget* target, + std::vector &missingTargets, + FreeTargetsReplace replace) +{ + if (replace == NoReplaceFreeTargets) + { + this->ResolveTargetsInGeneratorExpression(input, target, missingTargets); + return; + } + std::vector parts; + cmGeneratorExpression::Split(input, parts); + + std::string sep; + input = ""; + for(std::vector::iterator li = parts.begin(); + li != parts.end(); ++li) + { + if (!isGeneratorExpression(*li)) + { + this->AddTargetNamespace(*li, target, missingTargets); + } + else + { + this->ResolveTargetsInGeneratorExpression( + *li, + target, + missingTargets); + } + input += sep + *li; + sep = ";"; + } +} + +//---------------------------------------------------------------------------- +void +cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string &input, cmTarget* target, std::vector &missingTargets) diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index a5b25f49c..866806b66 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -102,9 +102,16 @@ protected: void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, const ImportPropertyMap &properties); + + enum FreeTargetsReplace { + ReplaceFreeTargets, + NoReplaceFreeTargets + }; + void ResolveTargetsInGeneratorExpressions(std::string &input, - cmTarget* target, - std::vector &missingTargets); + cmTarget* target, + std::vector &missingTargets, + FreeTargetsReplace replace = NoReplaceFreeTargets); // The namespace in which the exports are placed in the generated file. std::string Namespace; @@ -132,6 +139,9 @@ private: bool AddTargetNamespace(std::string &input, cmTarget* target, std::vector &missingTargets); + void ResolveTargetsInGeneratorExpression(std::string &input, + cmTarget* target, + std::vector &missingTargets); }; #endif From 94aeaf72c714eb184ec61bf6e7bc573bd1bc15c9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 4 Jan 2013 15:58:16 +0100 Subject: [PATCH 105/131] Split LINK_INTERFACE_LIBRARIES export handling into dedicated method. --- Source/cmExportBuildFileGenerator.cxx | 4 ++++ Source/cmExportFileGenerator.cxx | 24 +++++++++++++++++++++--- Source/cmExportFileGenerator.h | 4 ++++ Source/cmExportInstallFileGenerator.cxx | 4 ++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 9533319e9..29f67436f 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -107,6 +107,10 @@ cmExportBuildFileGenerator std::vector missingTargets; this->SetImportDetailProperties(config, suffix, target, properties, missingTargets); + this->SetImportLinkInterface(config, suffix, + cmGeneratorExpression::BuildInterface, + target, properties, missingTargets); + // TOOD: PUBLIC_HEADER_LOCATION // This should wait until the build feature propagation stuff diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index df8f3e8d1..5e5f45509 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -344,6 +344,26 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression( } } +//---------------------------------------------------------------------------- +void +cmExportFileGenerator +::SetImportLinkInterface(const char* config, std::string const& suffix, + cmGeneratorExpression::PreprocessContext preprocessRule, + cmTarget* target, ImportPropertyMap& properties, + std::vector& missingTargets) +{ + // Add the transitive link dependencies for this configuration. + cmTarget::LinkInterface const* iface = target->GetLinkInterface(config, + target); + if (!iface) + { + return; + } + this->SetImportLinkProperty(suffix, target, + "IMPORTED_LINK_INTERFACE_LIBRARIES", + iface->Libraries, properties, missingTargets); +} + //---------------------------------------------------------------------------- void cmExportFileGenerator @@ -388,9 +408,7 @@ cmExportFileGenerator this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", iface->Languages, properties, missingTargets); - this->SetImportLinkProperty(suffix, target, - "IMPORTED_LINK_INTERFACE_LIBRARIES", - iface->Libraries, properties, missingTargets); + this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, properties, missingTargets); diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 866806b66..4d97a6338 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -102,6 +102,10 @@ protected: void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, const ImportPropertyMap &properties); + void SetImportLinkInterface(const char* config, std::string const& suffix, + cmGeneratorExpression::PreprocessContext preprocessRule, + cmTarget* target, ImportPropertyMap& properties, + std::vector& missingTargets); enum FreeTargetsReplace { ReplaceFreeTargets, diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index bc953c9c1..68881a168 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -229,6 +229,10 @@ cmExportInstallFileGenerator this->SetImportDetailProperties(config, suffix, te->Target, properties, missingTargets); + this->SetImportLinkInterface(config, suffix, + cmGeneratorExpression::InstallInterface, + te->Target, properties, missingTargets); + // TOOD: PUBLIC_HEADER_LOCATION // This should wait until the build feature propagation stuff // is done. Then this can be a propagated include directory. From 77d26467848fd689fbbffbaa302d041aa2365b15 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 4 Jan 2013 13:36:18 +0100 Subject: [PATCH 106/131] Allow generator expressions in LINK_INTERFACE_LIBRARIES. The Config and IMPORTED_ variants may also contain generator expressions. If 'the implementation is the interface', then the result of evaluating the expressions at generate time is used to populate the IMPORTED_LINK_INTERFACE_LIBRARIES property. 1) In the case of non-static libraries, this is fine because the user still has the option to populate the LINK_INTERFACE_LIBRARIES with generator expressions if that is what is wanted. 2) In the case of static libraries, this prevents a footgun, enforcing that the interface and the implementation are really the same. Otherwise, the LINK_LIBRARIES could contain a generator expression which is evaluated with a different context at build time, and when used as an imported target. That would mean that the result of evaluating the INTERFACE_LINK_LIBRARIES property for a static library would not necessarily be the 'link implementation'. For example: add_library(libone STATIC libone.cpp) add_library(libtwo STATIC libtwo.cpp) add_library(libthree STATIC libthree.cpp) target_link_libraries(libtwo $<$,STATIC_LIBRARY>:libone>) target_link_libraries(libthree libtwo) If the LINK_LIBRARIES content was simply copied to the IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but executables linking to libthree will not link to libone. 3) As the 'implementation is the interface' concept is to be deprecated in the future anyway, this should be fine. --- Source/cmExportFileGenerator.cxx | 44 ++++++++++++++-- Source/cmTarget.cxx | 50 ++++++++++++++----- Source/cmTarget.h | 4 +- .../target_link_libraries/CMakeLists.txt | 10 ++++ .../target_link_libraries/depD.cpp | 13 +++++ .../target_link_libraries/depD.h | 11 ++++ .../target_link_libraries/targetB.cpp | 10 ++++ Tests/ExportImport/Export/CMakeLists.txt | 33 +++++++++++- .../Export/testSharedLibDepends.cpp | 8 +++ .../Export/testSharedLibDepends.h | 14 ++++++ .../Export/testSharedLibRequired.cpp | 7 +++ .../Export/testSharedLibRequired.h | 12 +++++ Tests/ExportImport/Import/A/CMakeLists.txt | 11 ++++ .../Import/A/deps_shared_iface.cpp | 11 ++++ 14 files changed, 221 insertions(+), 17 deletions(-) create mode 100644 Tests/CMakeCommands/target_link_libraries/depD.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/depD.h create mode 100644 Tests/CMakeCommands/target_link_libraries/targetB.cpp create mode 100644 Tests/ExportImport/Export/testSharedLibDepends.cpp create mode 100644 Tests/ExportImport/Export/testSharedLibDepends.h create mode 100644 Tests/ExportImport/Export/testSharedLibRequired.cpp create mode 100644 Tests/ExportImport/Export/testSharedLibRequired.h create mode 100644 Tests/ExportImport/Import/A/deps_shared_iface.cpp diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 5e5f45509..94e24c7a0 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -359,9 +359,47 @@ cmExportFileGenerator { return; } - this->SetImportLinkProperty(suffix, target, - "IMPORTED_LINK_INTERFACE_LIBRARIES", - iface->Libraries, properties, missingTargets); + + if (iface->ImplementationIsInterface) + { + this->SetImportLinkProperty(suffix, target, + "IMPORTED_LINK_INTERFACE_LIBRARIES", + iface->Libraries, properties, missingTargets); + return; + } + + const char *propContent; + + if (const char *prop_suffixed = target->GetProperty( + ("LINK_INTERFACE_LIBRARIES" + suffix).c_str())) + { + propContent = prop_suffixed; + } + else if (const char *prop = target->GetProperty( + "LINK_INTERFACE_LIBRARIES")) + { + propContent = prop; + } + else + { + return; + } + + if (!*propContent) + { + properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = ""; + return; + } + + std::string prepro = cmGeneratorExpression::Preprocess(propContent, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets, + ReplaceFreeTargets); + properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro; + } } //---------------------------------------------------------------------------- diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2cfb1bfd5..9b50b8e52 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4896,16 +4896,30 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, { std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; linkProp += suffix; - if(const char* config_libs = this->GetProperty(linkProp.c_str())) + + const char *propertyLibs = this->GetProperty(linkProp.c_str()); + + if(!propertyLibs) { - cmSystemTools::ExpandListArgument(config_libs, - info.LinkInterface.Libraries); + linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; + propertyLibs = this->GetProperty(linkProp.c_str()); } - else if(const char* libs = - this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES")) + if(propertyLibs) { - cmSystemTools::ExpandListArgument(libs, - info.LinkInterface.Libraries); + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + linkProp, 0, 0); + cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs) + ->Evaluate(this->Makefile, + desired_config.c_str(), + false, + headTarget, + this, + &dagChecker), + info.LinkInterface.Libraries); } } @@ -5019,18 +5033,20 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, // An explicit list of interface libraries may be set for shared // libraries and executables that export symbols. const char* explicitLibraries = 0; + std::string linkIfaceProp; if(this->GetType() == cmTarget::SHARED_LIBRARY || this->IsExecutableWithExports()) { // Lookup the per-configuration property. - std::string propName = "LINK_INTERFACE_LIBRARIES"; - propName += suffix; - explicitLibraries = this->GetProperty(propName.c_str()); + linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; + linkIfaceProp += suffix; + explicitLibraries = this->GetProperty(linkIfaceProp.c_str()); // If not set, try the generic property. if(!explicitLibraries) { - explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES"); + linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; + explicitLibraries = this->GetProperty(linkIfaceProp.c_str()); } } @@ -5048,7 +5064,16 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, if(explicitLibraries) { // The interface libraries have been explicitly set. - cmSystemTools::ExpandListArgument(explicitLibraries, iface.Libraries); + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), + linkIfaceProp, 0, 0); + cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate( + this->Makefile, + config, + false, + headTarget, + this, &dagChecker), iface.Libraries); if(this->GetType() == cmTarget::SHARED_LIBRARY) { @@ -5091,6 +5116,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, // The link implementation is the default link interface. LinkImplementation const* impl = this->GetLinkImplementation(config, headTarget); + iface.ImplementationIsInterface = true; iface.Libraries = impl->Libraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries; if(this->GetType() == cmTarget::STATIC_LIBRARY) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 1188a6a6a..b4d053d84 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -258,7 +258,9 @@ public: // Needed only for OLD behavior of CMP0003. std::vector WrongConfigLibraries; - LinkInterface(): Multiplicity(0) {} + bool ImplementationIsInterface; + + LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {} }; /** Get the link interface for the given configuration. Returns 0 diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 746d30c27..1551c5055 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -80,3 +80,13 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "") add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp) generate_export_header(depIfaceOnly) set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly) + +add_library(depD SHARED depD.cpp) +generate_export_header(depD) +set_property(TARGET depD APPEND PROPERTY + LINK_INTERFACE_LIBRARIES + $<$,EXECUTABLE>:depA> +) + +add_executable(targetB targetB.cpp) +target_link_libraries(targetB depD) diff --git a/Tests/CMakeCommands/target_link_libraries/depD.cpp b/Tests/CMakeCommands/target_link_libraries/depD.cpp new file mode 100644 index 000000000..b02c76cf3 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depD.cpp @@ -0,0 +1,13 @@ + +#include "depD.h" + +int DepD::foo() +{ + return 0; +} + +DepA DepD::getA() +{ + DepA a; + return a; +} diff --git a/Tests/CMakeCommands/target_link_libraries/depD.h b/Tests/CMakeCommands/target_link_libraries/depD.h new file mode 100644 index 000000000..d24ff5f7c --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depD.h @@ -0,0 +1,11 @@ + +#include "depd_export.h" + +#include "depA.h" + +struct DEPD_EXPORT DepD +{ + int foo(); + + DepA getA(); +}; diff --git a/Tests/CMakeCommands/target_link_libraries/targetB.cpp b/Tests/CMakeCommands/target_link_libraries/targetB.cpp new file mode 100644 index 000000000..063d63a32 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/targetB.cpp @@ -0,0 +1,10 @@ + +#include "depD.h" + +int main(int argc, char **argv) +{ + DepD d; + DepA a = d.getA(); + + return d.foo() + a.foo(); +} diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 569845a71..779d88958 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -158,6 +158,36 @@ set_property(TARGET testLibRequired APPEND PROPERTY $ ) +include(GenerateExportHeader) + +add_library(testSharedLibRequired SHARED testSharedLibRequired.cpp) +generate_export_header(testSharedLibRequired) +set_property(TARGET testSharedLibRequired APPEND PROPERTY + INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}" +) +set_property(TARGET testSharedLibRequired APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}" +) + +add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp) +set_property(TARGET testSharedLibDepends APPEND PROPERTY + INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}" +) +generate_export_header(testSharedLibDepends) + +set_property(TARGET testSharedLibDepends APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES + $ +) +set_property(TARGET testSharedLibDepends APPEND PROPERTY + LINK_INTERFACE_LIBRARIES + $<1:$> +) + +# LINK_PRIVATE because the LINK_INTERFACE_LIBRARIES is specified above. +target_link_libraries(testSharedLibDepends LINK_PRIVATE testSharedLibRequired) + install(TARGETS testLibRequired testLibIncludeRequired1 testLibIncludeRequired2 @@ -165,10 +195,11 @@ install(TARGETS testLibRequired testLibIncludeRequired4 testLibIncludeRequired5 testLibIncludeRequired6 + testSharedLibRequired EXPORT RequiredExp DESTINATION lib ) install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired) -install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib ) +install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib ) install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends) diff --git a/Tests/ExportImport/Export/testSharedLibDepends.cpp b/Tests/ExportImport/Export/testSharedLibDepends.cpp new file mode 100644 index 000000000..e27920725 --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibDepends.cpp @@ -0,0 +1,8 @@ + +#include "testSharedLibDepends.h" + +int TestSharedLibDepends::foo() +{ + TestSharedLibRequired req; + return req.foo(); +} diff --git a/Tests/ExportImport/Export/testSharedLibDepends.h b/Tests/ExportImport/Export/testSharedLibDepends.h new file mode 100644 index 000000000..b93143a5c --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibDepends.h @@ -0,0 +1,14 @@ + +#ifndef TESTSHAREDLIBDEPENDS_H +#define TESTSHAREDLIBDEPENDS_H + +#include "testsharedlibdepends_export.h" + +#include "testSharedLibRequired.h" + +struct TESTSHAREDLIBDEPENDS_EXPORT TestSharedLibDepends +{ + int foo(); +}; + +#endif diff --git a/Tests/ExportImport/Export/testSharedLibRequired.cpp b/Tests/ExportImport/Export/testSharedLibRequired.cpp new file mode 100644 index 000000000..1ac34aaef --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibRequired.cpp @@ -0,0 +1,7 @@ + +#include "testSharedLibRequired.h" + +int TestSharedLibRequired::foo() +{ + return 0; +} diff --git a/Tests/ExportImport/Export/testSharedLibRequired.h b/Tests/ExportImport/Export/testSharedLibRequired.h new file mode 100644 index 000000000..edaddd485 --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibRequired.h @@ -0,0 +1,12 @@ + +#ifndef TESTSHAREDLIBREQUIRED_H +#define TESTSHAREDLIBREQUIRED_H + +#include "testsharedlibrequired_export.h" + +struct TESTSHAREDLIBREQUIRED_EXPORT TestSharedLibRequired +{ + int foo(); +}; + +#endif diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 56cfea031..abb2ab01d 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -167,3 +167,14 @@ set_property(TARGET deps_iface APPEND PROPERTY INCLUDE_DIRECTORIES $ ) + +add_executable(deps_shared_iface deps_shared_iface.cpp) +target_link_libraries(deps_shared_iface testSharedLibDepends) +set_property(TARGET deps_shared_iface APPEND PROPERTY + COMPILE_DEFINITIONS + $ +) +set_property(TARGET deps_shared_iface APPEND PROPERTY + INCLUDE_DIRECTORIES + $ +) diff --git a/Tests/ExportImport/Import/A/deps_shared_iface.cpp b/Tests/ExportImport/Import/A/deps_shared_iface.cpp new file mode 100644 index 000000000..4f7eb234a --- /dev/null +++ b/Tests/ExportImport/Import/A/deps_shared_iface.cpp @@ -0,0 +1,11 @@ + + +#include "testSharedLibDepends.h" + +int main(int,char **) +{ + TestSharedLibDepends dep; + TestSharedLibRequired req; + + return dep.foo() + req.foo(); +} From 5929086634e362d03d02124eea5ee14919ae5a0f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 11 Jan 2013 00:01:18 -0500 Subject: [PATCH 107/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f77d17c3f..c71ba2134 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130110) +set(CMake_VERSION_TWEAK 20130111) #set(CMake_VERSION_RC 1) From 8ff1d4714fb7cd42eb3cd8db041b529e433eb7c8 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jan 2013 10:57:39 -0500 Subject: [PATCH 108/131] CMake: Skip empty link.txt lines (#13845) In the implementation of "cmake -E cmake_link_script", skip lines from the input file that are empty or contain only whitespace. Do not try to run a child with no command line. --- Source/cmake.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a44c825f7..0acd2fce8 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3299,6 +3299,12 @@ int cmake::ExecuteLinkScript(std::vector& args) int result = 0; while(result == 0 && cmSystemTools::GetLineFromStream(fin, command)) { + // Skip empty command lines. + if(command.find_first_not_of(" \t") == command.npos) + { + continue; + } + // Setup this command line. const char* cmd[2] = {command.c_str(), 0}; cmsysProcess_SetCommand(cp, cmd); From 6318834b95fb4e666f9c135a883bb953579c3c8a Mon Sep 17 00:00:00 2001 From: KWSys Robot Date: Thu, 10 Jan 2013 18:34:34 +0100 Subject: [PATCH 109/131] KWSys 2013-01-10 (608d6b47) Extract upstream KWSys using the following shell commands. $ git archive --prefix=upstream-kwsys/ 608d6b47 | tar x $ git shortlog --no-merges --abbrev=8 --format='%h %s' fc60c8b8..608d6b47 Rolf Eike Beer (6): 297758a5 SystemInformation: fix conversion warning 79ef34ef SystemInformation: fix calling kwsysProcess_WaitForData() f1068caf SystemInformation: speed up copying process data 7dfc27d5 SystemInformation: check CPU vendor and SSE support on OpenBSD 494d9d7a SystemInformation: get stepping code on Intel Macs 608d6b47 SystemInformation: determine processor features on Intel Macs Change-Id: I7f5bc5b7af2bf7d4e5c1ee291c286add0f17a7d5 --- CMakeLists.txt | 7 +++ SystemInformation.cxx | 129 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 130 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bfcab040..5df5a740d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -603,6 +603,13 @@ IF(KWSYS_USE_SystemInformation) COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1) ENDIF() ENDIF() + IF(CMAKE_SYSTEM MATCHES "BSD") + CHECK_INCLUDE_FILES("machine/cpu.h" KWSYS_SYS_HAS_MACHINE_CPU_H) + IF(KWSYS_SYS_HAS_MACHINE_CPU_H) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1) + ENDIF() + ENDIF() IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE) SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1) ENDIF() diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 0460b2906..59a9abe6b 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -91,6 +91,10 @@ typedef int siginfo_t; # include #endif +#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H) +# include +#endif + #if defined(__DragonFly__) # include #endif @@ -3026,7 +3030,7 @@ bool SystemInformationImplementation::QueryProcessor() return false; } - this->NumberOfPhysicalCPU = c; + this->NumberOfPhysicalCPU = static_cast(c); this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; return true; @@ -4000,6 +4004,81 @@ bool SystemInformationImplementation::ParseSysCtl() len = sizeof(value); err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0); this->ChipID.Model = static_cast< int >( value ); + + // Chip Stepping + len = sizeof(value); + value = 0; + err = sysctlbyname("machdep.cpu.stepping", &value, &len, NULL, 0); + if (!err) + { + this->ChipID.Revision = static_cast< int >( value ); + } + + // feature string + char *buf = 0; + size_t allocSize = 128; + + err = 0; + len = 0; + + // sysctlbyname() will return with err==0 && len==0 if the buffer is too small + while (err == 0 && len == 0) + { + delete[] buf; + allocSize *= 2; + buf = new char[allocSize]; + if (!buf) + { + break; + } + buf[0] = ' '; + len = allocSize - 2; // keep space for leading and trailing space + err = sysctlbyname("machdep.cpu.features", buf + 1, &len, NULL, 0); + } + if (!err && buf && len) + { + // now we can match every flags as space + flag + space + buf[len + 1] = ' '; + kwsys_stl::string cpuflags(buf, len + 2); + + if ((cpuflags.find(" FPU ")!=kwsys_stl::string::npos)) + { + this->Features.HasFPU = true; + } + if ((cpuflags.find(" TSC ")!=kwsys_stl::string::npos)) + { + this->Features.HasTSC = true; + } + if ((cpuflags.find(" MMX ")!=kwsys_stl::string::npos)) + { + this->Features.HasMMX = true; + } + if ((cpuflags.find(" SSE ")!=kwsys_stl::string::npos)) + { + this->Features.HasSSE = true; + } + if ((cpuflags.find(" SSE2 ")!=kwsys_stl::string::npos)) + { + this->Features.HasSSE2 = true; + } + if ((cpuflags.find(" APIC ")!=kwsys_stl::string::npos)) + { + this->Features.HasAPIC = true; + } + if ((cpuflags.find(" CMOV ")!=kwsys_stl::string::npos)) + { + this->Features.HasCMOV = true; + } + if ((cpuflags.find(" MTRR ")!=kwsys_stl::string::npos)) + { + this->Features.HasMTRR = true; + } + if ((cpuflags.find(" ACPI ")!=kwsys_stl::string::npos)) + { + this->Features.HasACPI = true; + } + } + delete[] buf; } // brand string @@ -4059,13 +4138,12 @@ kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector< char* data = NULL; int length; double timeout = 255; + int pipe; // pipe id as returned by kwsysProcess_WaitForData() - while(kwsysProcess_WaitForData(gp,&data,&length,&timeout)) // wait for 1s + while( ( pipe = kwsysProcess_WaitForData(gp,&data,&length,&timeout), + (pipe == kwsysProcess_Pipe_STDOUT || pipe == kwsysProcess_Pipe_STDERR) ) ) // wait for 1s { - for(int i=0;iCPUSpeedInMHz = (float) k; #endif +#if defined(CPU_SSE) + ctrl[0] = CTL_MACHDEP; + ctrl[1] = CPU_SSE; + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->Features.HasSSE = (k > 0); +#endif + +#if defined(CPU_SSE2) + ctrl[0] = CTL_MACHDEP; + ctrl[1] = CPU_SSE2; + + if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) + { + return false; + } + + this->Features.HasSSE2 = (k > 0); +#endif + +#if defined(CPU_CPUVENDOR) + ctrl[0] = CTL_MACHDEP; + ctrl[1] = CPU_CPUVENDOR; + char vbuf[25]; + ::memset(vbuf, 0, sizeof(vbuf)); + sz = sizeof(vbuf) - 1; + if (sysctl(ctrl, 2, vbuf, &sz, NULL, 0) != 0) + { + return false; + } + + this->ChipID.Vendor = vbuf; + this->FindManufacturer(); +#endif + return true; #else return false; From 3367d0cc7fe50e6b6fc06c85c8c38c683c1d3805 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 12 Jan 2013 00:01:19 -0500 Subject: [PATCH 110/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c71ba2134..36a32044a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130111) +set(CMake_VERSION_TWEAK 20130112) #set(CMake_VERSION_RC 1) From 9822f8c931c39b28a587cf48b5314431386d50ea Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 13 Jan 2013 00:01:16 -0500 Subject: [PATCH 111/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 36a32044a..14514c401 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130112) +set(CMake_VERSION_TWEAK 20130113) #set(CMake_VERSION_RC 1) From 1da75022bbe3239e028fe73d94dfae724ad25a7f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 23 Dec 2012 19:00:18 +0100 Subject: [PATCH 112/131] Don't include generator expressions in old-style link handling. Don't add generator expressions to variables which are used for CMP0003, CMP0004, and the old-style _LIB_DEPENDS content. They will not be evaluated when read anyway and would probably confuse the code reading them. This makes it legitimate to use target_link_libraries with generator expressions as arguments. --- Source/cmTarget.cxx | 13 +++++++++++++ Source/cmTargetLinkLibrariesCommand.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9b50b8e52..51512de26 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2232,6 +2232,14 @@ static std::string targetNameGenex(const char *lib) return std::string("$"; } +//---------------------------------------------------------------------------- +static bool isGeneratorExpression(const std::string &lib) +{ + const std::string::size_type openpos = lib.find("$<"); + return (openpos != std::string::npos) + && (lib.find(">", openpos) != std::string::npos); +} + //---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, @@ -2254,6 +2262,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, llt).c_str()); } + if (isGeneratorExpression(lib)) + { + return; + } + cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 8e5823c10..34fe54c34 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -13,6 +13,7 @@ #define cmTargetLinkLibrariesCommand_h #include "cmCommand.h" +#include "cmDocumentGeneratorExpressions.h" /** \class cmTargetLinkLibrariesCommand * \brief Specify a list of libraries to link into executables. @@ -141,6 +142,12 @@ public: "However, if two archives are really so interdependent they should " "probably be combined into a single archive." ")" + "\n" + "Arguments to target_link_libraries may use \"generator expressions\" " + "with the syntax \"$<...>\". Note however, that generator expressions " + "will not be used in OLD handling of CMP0003 or CMP0004." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS ; } From 7c7b94f21ffa6f3bda054d5e11bd09b13155c04e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Jan 2013 10:04:40 +0100 Subject: [PATCH 113/131] Document the use of generator expressions in new commands. --- Source/cmTargetCompileDefinitionsCommand.h | 3 +++ Source/cmTargetIncludeDirectoriesCommand.h | 3 +++ Source/cmTargetPropCommandBase.h | 1 + 3 files changed, 7 insertions(+) diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index 707610e3e..4b066b7a0 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -69,6 +69,9 @@ public: "INTERFACE_COMPILE_DEFINITIONS from. " "Repeated calls for the same append items in the order called." "\n" + "Arguments to target_compile_definitions may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS ; } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index c1957d6d9..90e039c4d 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -73,6 +73,9 @@ public: "directories must be absolute paths, not relative paths. " "Repeated calls for the same append items in the order called." "\n" + "Arguments to target_include_directories may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS ; } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 90e3bbb7f..e757f9da1 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -14,6 +14,7 @@ #define cmTargetPropCommandBase_h #include "cmCommand.h" +#include "cmDocumentGeneratorExpressions.h" class cmTarget; From 2bee6f5ba5b3f33817cc00e056a7df60d05c9399 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 19 Nov 2012 23:56:12 +0100 Subject: [PATCH 114/131] Add the TARGET_DEFINED generator expression This tests whether the parameter is a usable target. --- Source/cmDocumentGeneratorExpressions.h | 1 + Source/cmGeneratorExpressionEvaluator.cxx | 18 ++++++++++++++++++ .../target_compile_definitions/CMakeLists.txt | 2 ++ .../target_compile_definitions/consumer.cpp | 8 ++++++++ 4 files changed, 29 insertions(+) diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index b8889ac20..fa2190717 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -37,6 +37,7 @@ "target in the same buildsystem. Expands to the empty string " \ "otherwise.\n" \ " $ = main file (.exe, .so.1.2, .a)\n" \ + " $ = '1' if tgt is a target, else '0'\n" \ " $ = file used to link (.a, .lib, .so)\n" \ " $ = file with soname (.so.3)\n" \ "where \"tgt\" is the name of a target. " \ diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index f4e413123..8e40815af 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -289,6 +289,22 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode } configurationTestNode; +static const struct TargetDefinedNode : public cmGeneratorExpressionNode +{ + TargetDefinedNode() {} + + virtual int NumExpectedParameters() const { return 1; } + + std::string Evaluate(const std::vector ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return context->Makefile->FindTargetToUse(parameters.front().c_str()) + ? "1" : "0"; + } +} targetDefinedNode; + //---------------------------------------------------------------------------- static const char* targetPropertyTransitiveWhitelist[] = { "INTERFACE_INCLUDE_DIRECTORIES" @@ -702,6 +718,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &buildInterfaceNode; else if (identifier == "INSTALL_INTERFACE") return &installInterfaceNode; + else if (identifier == "TARGET_DEFINED") + return &targetDefinedNode; return 0; } diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt index 84a23efc3..a37c59708 100644 --- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt +++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt @@ -23,4 +23,6 @@ add_executable(consumer target_compile_definitions(consumer PRIVATE target_compile_definitions importedlib + $<$:SHOULD_NOT_BE_DEFINED> + $<$:SHOULD_BE_DEFINED> ) diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp index e3788ddb2..1ef657d5a 100644 --- a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp +++ b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp @@ -15,4 +15,12 @@ #error Expected MY_IMPORTEDINTERFACE_DEFINE #endif +#ifdef SHOULD_NOT_BE_DEFINED +#error Unexpected SHOULD_NOT_BE_DEFINED +#endif + +#ifndef SHOULD_BE_DEFINED +#error Expected SHOULD_BE_DEFINED +#endif + int main() { return 0; } From 36480eaf5c08c6f594f53d290df72ab42c29ba69 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 14 Jan 2013 00:01:23 -0500 Subject: [PATCH 115/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 14514c401..1660680e4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130113) +set(CMake_VERSION_TWEAK 20130114) #set(CMake_VERSION_RC 1) From 4ba0ac7be4bbe38a7cb3334504e69db039288ad8 Mon Sep 17 00:00:00 2001 From: KWSys Robot Date: Mon, 14 Jan 2013 09:26:01 -0500 Subject: [PATCH 116/131] KWSys 2013-01-14 (6fa1c99f) Extract upstream KWSys using the following shell commands. $ git archive --prefix=upstream-kwsys/ 6fa1c99f | tar x $ git shortlog --no-merges --abbrev=8 --format='%h %s' 608d6b47..6fa1c99f Brad King (1): 84827cc1 Process: Avoid argv[0]==NULL from parsing empty command line Rolf Eike Beer (8): e041cd66 SystemInformation: factor out QueryMemoryBySysconf() ea850fa0 SystemInformation: factor out QueryProcessorBySysconf() 57f06d49 SystemInformation: count processors with sysconf() on Solaris c6057a06 SystemInformation: fix "Multi-character character constant" 5a27bd4f SystemInformation: make IsHyperThreadingSupported() return bool 342c0ad2 SystemInformation: query memory size with sysconf() on Solaris f0b857c1 SystemInformation: cache result of IsHyperThreadingSupported() ab0c2a09 SystemInformation: try using assembler with BorlandC Change-Id: I072371ed35eed892a5ef62a9e9e6cad734e961d9 --- CMakeLists.txt | 16 ++++++ ProcessUNIX.c | 5 +- SystemInformation.cxx | 118 +++++++++++++++++++++++++++----------- kwsysPlatformTestsCXX.cxx | 27 +++++++++ 4 files changed, 129 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5df5a740d..124b8aca0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -574,6 +574,8 @@ IF(KWSYS_USE_SystemTools) ENDIF() IF(KWSYS_USE_SystemInformation) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P}) IF(NOT CYGWIN) INCLUDE(CheckIncludeFiles) CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H) @@ -638,6 +640,20 @@ IF(KWSYS_USE_SystemInformation) SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1) ENDIF() + IF(BORLAND) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM + "Checking whether Borland CXX compiler supports assembler instructions" DIRECT) + IF(KWSYS_CXX_HAS_BORLAND_ASM) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM=1) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM_CPUID + "Checking whether Borland CXX compiler supports CPUID assembler instruction" DIRECT) + IF(KWSYS_CXX_HAS_BORLAND_ASM_CPUID) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM_CPUID=1) + ENDIF() + ENDIF() + ENDIF() IF(KWSYS_USE___INT64) SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_USE___INT64=1) diff --git a/ProcessUNIX.c b/ProcessUNIX.c index 83838affc..2db12544c 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -418,9 +418,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) parse it. */ newCommands[cp->NumberOfCommands] = kwsysSystem_Parse_CommandForUnix(*command, 0); - if(!newCommands[cp->NumberOfCommands]) + if(!newCommands[cp->NumberOfCommands] || + !newCommands[cp->NumberOfCommands][0]) { - /* Out of memory. */ + /* Out of memory or no command parsed. */ free(newCommands); return 0; } diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 59a9abe6b..b20d72458 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -202,7 +202,7 @@ typedef struct rlimit ResourceLimitType; #define USE_CPUID_INTRINSICS 0 #endif -#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS +#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID) # define USE_CPUID 1 #else # define USE_CPUID 0 @@ -224,6 +224,7 @@ static bool call_cpuid(int select, int result[4]) return true; #else int tmp[4]; +#if defined(_MSC_VER) // Use SEH to determine CPUID presence __try { _asm { @@ -262,7 +263,24 @@ static bool call_cpuid(int select, int result[4]) return false; } - memcpy(result, tmp, sizeof(tmp)); + memcpy(result, tmp, sizeof(tmp)); +#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID) + unsigned int a, b, c, d; + __asm { + mov EAX, select; + cpuid + mov a, EAX; + mov b, EBX; + mov c, ECX; + mov d, EDX; + } + + result[0] = a; + result[1] = b; + result[2] = c; + result[3] = d; +#endif + // The cpuid instruction succeeded. return true; #endif @@ -432,7 +450,7 @@ protected: int CPUCount(); unsigned char LogicalCPUPerPhysicalCPU(); unsigned char GetAPICId(); - unsigned int IsHyperThreadingSupported(); + bool IsHyperThreadingSupported(); static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For Linux and Cygwin, /proc/cpuinfo formats are slightly different @@ -456,7 +474,8 @@ protected: kwsys_stl::string SysCtlBuffer; // For Solaris - bool QuerySolarisInfo(); + bool QuerySolarisMemory(); + bool QuerySolarisProcessor(); kwsys_stl::string ParseValueFromKStat(const char* arguments); kwsys_stl::string RunProcess(kwsys_stl::vector args); @@ -481,9 +500,11 @@ protected: //For AIX bool QueryAIXMemory(); + bool QueryProcessorBySysconf(); bool QueryProcessor(); // Evaluate the memory information. + bool QueryMemoryBySysconf(); bool QueryMemory(); size_t TotalVirtualMemory; size_t AvailableVirtualMemory; @@ -1287,7 +1308,7 @@ void SystemInformationImplementation::RunCPUCheck() #elif defined(__APPLE__) this->ParseSysCtl(); #elif defined (__SVR4) && defined (__sun) - this->QuerySolarisInfo(); + this->QuerySolarisProcessor(); #elif defined(__HAIKU__) this->QueryHaikuInfo(); #elif defined(__QNX__) @@ -1313,7 +1334,7 @@ void SystemInformationImplementation::RunMemoryCheck() #if defined(__APPLE__) this->ParseSysCtl(); #elif defined (__SVR4) && defined (__sun) - this->QuerySolarisInfo(); + this->QuerySolarisMemory(); #elif defined(__HAIKU__) this->QueryHaikuInfo(); #elif defined(__QNX__) @@ -3016,7 +3037,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() return true; } -bool SystemInformationImplementation::QueryProcessor() +bool SystemInformationImplementation::QueryProcessorBySysconf() { #if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) // IRIX names this slightly different @@ -3039,6 +3060,11 @@ bool SystemInformationImplementation::QueryProcessor() #endif } +bool SystemInformationImplementation::QueryProcessor() +{ + return this->QueryProcessorBySysconf(); +} + /** Get total system RAM in units of KiB. */ @@ -3559,8 +3585,7 @@ bool SystemInformationImplementation::QueryAIXMemory() #endif } -/** Query for the memory status */ -bool SystemInformationImplementation::QueryMemory() +bool SystemInformationImplementation::QueryMemoryBySysconf() { #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) // Assume the mmap() granularity as returned by _SC_PAGESIZE is also @@ -3597,6 +3622,12 @@ bool SystemInformationImplementation::QueryMemory() #endif } +/** Query for the memory status */ +bool SystemInformationImplementation::QueryMemory() +{ + return this->QueryMemoryBySysconf(); +} + /** */ size_t SystemInformationImplementation::GetTotalVirtualMemory() { @@ -3729,8 +3760,13 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) /** Works only for windows */ -unsigned int SystemInformationImplementation::IsHyperThreadingSupported() +bool SystemInformationImplementation::IsHyperThreadingSupported() { + if (this->Features.ExtendedFeatures.SupportsHyperthreading) + { + return true; + } + #if USE_CPUID int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 }; @@ -3748,13 +3784,15 @@ unsigned int SystemInformationImplementation::IsHyperThreadingSupported() if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { - if (VendorId[1] == 'uneG') + if (VendorId[1] == 0x756e6547) // 'uneG' { - if (VendorId[3] == 'Ieni') + if (VendorId[3] == 0x49656e69) // 'Ieni' { - if (VendorId[2] == 'letn') + if (VendorId[2] == 0x6c65746e) // 'letn' { - return(Regs[3] & HT_BIT); // Genuine Intel with hyper-Threading technology + // Genuine Intel with hyper-Threading technology + this->Features.ExtendedFeatures.SupportsHyperthreading = ((Regs[3] & HT_BIT) != 0); + return this->Features.ExtendedFeatures.SupportsHyperthreading; } } } @@ -4251,16 +4289,40 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha return value; } - /** Querying for system information from Solaris */ -bool SystemInformationImplementation::QuerySolarisInfo() +bool SystemInformationImplementation::QuerySolarisMemory() { - // Parse values - this->NumberOfPhysicalCPU = static_cast( - atoi(this->ParseValueFromKStat("-n syste_misc -s ncpus").c_str())); - this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = 1; +#if defined (__SVR4) && defined (__sun) + // Solaris allows querying this value by sysconf, but if this is + // a 32 bit process on a 64 bit host the returned memory will be + // limited to 4GiB. So if this is a 32 bit process or if the sysconf + // method fails use the kstat interface. +#if SIZEOF_VOID_P == 8 + if (this->QueryMemoryBySysconf()) + { + return true; + } +#endif + char* tail; + unsigned long totalMemory = + strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0); + this->TotalPhysicalMemory = totalMemory/128; + + return true; +#else + return false; +#endif +} + +bool SystemInformationImplementation::QuerySolarisProcessor() +{ + if (!this->QueryProcessorBySysconf()) + { + return false; + } + + // Parse values this->CPUSpeedInMHz = static_cast(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str())); // Chip family @@ -4277,20 +4339,6 @@ bool SystemInformationImplementation::QuerySolarisInfo() this->FindManufacturer(); } - // Cache size - this->Features.L1CacheSize = 0; - this->Features.L2CacheSize = 0; - - char* tail; - unsigned long totalMemory = - strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0); - this->TotalPhysicalMemory = totalMemory/128; - - // Undefined values (for now at least) - this->TotalVirtualMemory = 0; - this->AvailablePhysicalMemory = 0; - this->AvailableVirtualMemory = 0; - return true; } diff --git a/kwsysPlatformTestsCXX.cxx b/kwsysPlatformTestsCXX.cxx index ae5870342..48976c442 100644 --- a/kwsysPlatformTestsCXX.cxx +++ b/kwsysPlatformTestsCXX.cxx @@ -580,3 +580,30 @@ int main() } } #endif + +#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM +int main() +{ + int a = 1; + __asm { + xor EBX, EBX; + mov a, EBX; + } + + return a; +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM_CPUID +int main() +{ + int a = 0; + __asm { + xor EAX, EAX; + cpuid; + mov a, EAX; + } + + return a; +} +#endif From 3a40a8adf36c25321895c0ba12484d1e2989be6b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 15 Jan 2013 00:01:13 -0500 Subject: [PATCH 117/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1660680e4..1e7fe5070 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130114) +set(CMake_VERSION_TWEAK 20130115) #set(CMake_VERSION_RC 1) From 7171fd0a903e71486e1d1cebc36aeaa2d2c71e8c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 5 Dec 2012 14:59:39 +0100 Subject: [PATCH 118/131] Add a way to check INTERFACE user property compatibility. --- Source/cmTarget.cxx | 70 +++++++++++++++++++++++++++++++++++++++++++++ Source/cmTarget.h | 2 ++ Source/cmake.cxx | 7 +++++ Source/cmake.h | 2 ++ 4 files changed, 81 insertions(+) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9b50b8e52..6f3f63819 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -891,6 +891,19 @@ void cmTarget::DefineProperties(cmake *cm) "must ensure that the targets that they link to have a consistent " "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property."); + cm->DefineProperty + ("COMPATIBLE_INTERFACE_BOOL", cmProperty::TARGET, + "Properties which must be compatible with their link interface", + "The COMPATIBLE_INTERFACE_BOOL property may contain a list of properties" + "for this target which must be consistent when evaluated as a boolean " + "in the INTERFACE of all linked dependencies. For example, if a " + "property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" " + "property content in all dependencies must be consistent with each " + "other, and with the \"FOO\" property in this target. " + "Consistency in this sense has the meaning that if the property is set," + "then it must have the same boolean value as all others, and if the " + "property is not set, then it is ignored."); + cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", @@ -5298,6 +5311,58 @@ std::string cmTarget::CheckCMP0004(std::string const& item) return lib; } +//---------------------------------------------------------------------------- +void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, + const char* config) +{ + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + + std::set emitted; + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + if (!li->Target) + { + continue; + } + const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL"); + if (!prop) + { + continue; + } + + std::vector props; + cmSystemTools::ExpandListArgument(prop, props); + + for(std::vector::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + if (this->Makefile->GetCMakeInstance() + ->GetIsPropertyDefined(pi->c_str(), + cmProperty::TARGET)) + { + cmOStringStream e; + e << "Target \"" << li->Target->GetName() << "\" has property \"" + << *pi << "\" listed in its COMPATIBLE_INTERFACE_BOOL property. " + "This is not allowed. Only user-defined properties may appear " + "listed in the COMPATIBLE_INTERFACE_BOOL property."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if(emitted.insert(*pi).second) + { + this->GetLinkInterfaceDependentBoolProperty(*pi, config); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + } + } +} + //---------------------------------------------------------------------------- cmComputeLinkInformation* cmTarget::GetLinkInformation(const char* config, cmTarget *head) @@ -5319,6 +5384,11 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head) info = 0; } + if (info) + { + this->CheckPropertyCompatibility(info, config); + } + // Store the information for this configuration. cmTargetLinkInformationMap::value_type entry(key, info); i = this->LinkInformation.insert(entry).first; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b4d053d84..0963c5cf6 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -626,6 +626,8 @@ private: cmTarget *head); cmTargetLinkInformationMap LinkInformation; + void CheckPropertyCompatibility(cmComputeLinkInformation *info, + const char* config); bool ComputeLinkInterface(const char* config, LinkInterface& iface, cmTarget *head); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a44c825f7..bbc7f1ff5 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3552,6 +3552,13 @@ void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope, chained); } +bool cmake::GetIsPropertyDefined(const char *name, + cmProperty::ScopeType scope) +{ + return this->PropertyDefinitions[scope].find(name) != + this->PropertyDefinitions[scope].end(); +} + cmPropertyDefinition *cmake ::GetPropertyDefinition(const char *name, cmProperty::ScopeType scope) diff --git a/Source/cmake.h b/Source/cmake.h index e5aa07656..f6fe0d696 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -341,6 +341,8 @@ class cmake bool chain = false, const char *variableGroup = 0); + bool GetIsPropertyDefined(const char *name, cmProperty::ScopeType scope); + // get property definition cmPropertyDefinition *GetPropertyDefinition (const char *name, cmProperty::ScopeType scope); From b279f2b43180b6c55dd3361c2380f7ed3c998109 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Jan 2013 09:39:29 +0100 Subject: [PATCH 119/131] Strip consecutive semicolons when preprocessing genex strings. --- Source/cmGeneratorExpression.cxx | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index d306dee6d..78ae8f258 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -147,6 +147,38 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() } } +//---------------------------------------------------------------------------- +static std::string stripEmptyListElements(const std::string &input) +{ + std::string result; + + const char *c = input.c_str(); + bool skipSemiColons = true; + for ( ; *c; ++c) + { + if(c[0] == ';') + { + if(skipSemiColons) + { + continue; + } + skipSemiColons = true; + } + else + { + skipSemiColons = false; + } + result += *c; + } + + if (!result.empty() && *(result.end() - 1) == ';') + { + result.resize(result.size() - 1); + } + + return result; +} + //---------------------------------------------------------------------------- static std::string stripAllGeneratorExpressions(const std::string &input) { @@ -186,7 +218,7 @@ static std::string stripAllGeneratorExpressions(const std::string &input) lastPos = pos; } result += input.substr(lastPos); - return result; + return stripEmptyListElements(result); } //---------------------------------------------------------------------------- @@ -247,7 +279,7 @@ static std::string stripExportInterface(const std::string &input, } result += input.substr(lastPos); - return result; + return stripEmptyListElements(result); } //---------------------------------------------------------------------------- From f623d37a9558336af208a4fb5db232b28b56cb82 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Jan 2013 09:42:07 +0100 Subject: [PATCH 120/131] Don't write a comment in the export file without the code. --- Source/cmExportFileGenerator.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 94e24c7a0..91de20004 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -665,6 +665,10 @@ cmExportFileGenerator void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os, const std::vector& missingTargets) { + if (missingTargets.empty()) + { + return; + } os << "# Make sure the targets which have been exported in some other \n" "# export set exist.\n"; for(unsigned int i=0; i Date: Sun, 13 Jan 2013 09:42:47 +0100 Subject: [PATCH 121/131] Only generate one check per missing target. --- Source/cmExportFileGenerator.cxx | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 91de20004..a2d6961b8 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -671,19 +671,23 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os, } os << "# Make sure the targets which have been exported in some other \n" "# export set exist.\n"; + std::set emitted; for(unsigned int i=0; i Date: Sun, 13 Jan 2013 09:44:52 +0100 Subject: [PATCH 122/131] Move the exported check for dependencies of targets Check only once, in the Config.cmake file, instead of once in each Config-.cmake file. --- Source/cmExportBuildFileGenerator.cxx | 11 +++++------ Source/cmExportBuildFileGenerator.h | 3 ++- Source/cmExportFileGenerator.cxx | 5 +++-- Source/cmExportFileGenerator.h | 6 ++++-- Source/cmExportInstallFileGenerator.cxx | 16 +++++++++------- Source/cmExportInstallFileGenerator.h | 6 ++++-- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 29f67436f..ad6180311 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -74,16 +74,16 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateInterfaceProperties(te, os, properties); } - this->GenerateMissingTargetsCheckCode(os, missingTargets); - // Generate import file content for each configuration. for(std::vector::const_iterator ci = this->Configurations.begin(); ci != this->Configurations.end(); ++ci) { - this->GenerateImportConfig(os, ci->c_str()); + this->GenerateImportConfig(os, ci->c_str(), missingTargets); } + this->GenerateMissingTargetsCheckCode(os, missingTargets); + return true; } @@ -91,7 +91,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) void cmExportBuildFileGenerator ::GenerateImportTargetsConfig(std::ostream& os, - const char* config, std::string const& suffix) + const char* config, std::string const& suffix, + std::vector &missingTargets) { for(std::vector::const_iterator tei = this->Exports->begin(); @@ -104,7 +105,6 @@ cmExportBuildFileGenerator if(!properties.empty()) { // Get the rest of the target details. - std::vector missingTargets; this->SetImportDetailProperties(config, suffix, target, properties, missingTargets); this->SetImportLinkInterface(config, suffix, @@ -119,7 +119,6 @@ cmExportBuildFileGenerator // properties); // Generate code in the export file. - this->GenerateMissingTargetsCheckCode(os, missingTargets); this->GenerateImportPropertyCode(os, config, target, properties); } } diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 726537bfc..5e1be1648 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -44,7 +44,8 @@ protected: virtual bool GenerateMainFile(std::ostream& os); virtual void GenerateImportTargetsConfig(std::ostream& os, const char* config, - std::string const& suffix); + std::string const& suffix, + std::vector &missingTargets); virtual void HandleMissingTarget(std::string& link_libs, std::vector& missingTargets, cmMakefile* mf, diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index a2d6961b8..fc78eeb69 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -107,7 +107,8 @@ bool cmExportFileGenerator::GenerateImportFile() //---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, - const char* config) + const char* config, + std::vector &missingTargets) { // Construct the property configuration suffix. std::string suffix = "_"; @@ -121,7 +122,7 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, } // Generate the per-config target information. - this->GenerateImportTargetsConfig(os, config, suffix); + this->GenerateImportTargetsConfig(os, config, suffix, missingTargets); } //---------------------------------------------------------------------------- diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 4d97a6338..8620dd1c6 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -47,7 +47,8 @@ protected: // Generate per-configuration target information to the given output // stream. - void GenerateImportConfig(std::ostream& os, const char* config); + void GenerateImportConfig(std::ostream& os, const char* config, + std::vector &missingTargets); // Methods to implement export file code generation. void GenerateImportHeaderCode(std::ostream& os, const char* config = 0); @@ -85,7 +86,8 @@ protected: /** Each subclass knows where the target files are located. */ virtual void GenerateImportTargetsConfig(std::ostream& os, const char* config, - std::string const& suffix) = 0; + std::string const& suffix, + std::vector &missingTargets) = 0; /** Each subclass knows how to deal with a target that is missing from an * export set. */ diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 68881a168..bffa2b605 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -93,7 +93,6 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateInterfaceProperties(te, os, properties); } - this->GenerateMissingTargetsCheckCode(os, missingTargets); // Now load per-configuration properties for them. os << "# Load information for each installed configuration.\n" @@ -111,17 +110,21 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) ci = this->Configurations.begin(); ci != this->Configurations.end(); ++ci) { - if(!this->GenerateImportFileConfig(ci->c_str())) + if(!this->GenerateImportFileConfig(ci->c_str(), missingTargets)) { result = false; } } + + this->GenerateMissingTargetsCheckCode(os, missingTargets); + return result; } //---------------------------------------------------------------------------- bool -cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config) +cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config, + std::vector &missingTargets) { // Skip configurations not enabled for this export. if(!this->IEGen->InstallsForConfig(config)) @@ -161,7 +164,7 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config) this->GenerateImportHeaderCode(os, config); // Generate the per-config target information. - this->GenerateImportConfig(os, config); + this->GenerateImportConfig(os, config, missingTargets); // End with the import file footer. this->GenerateImportFooterCode(os); @@ -176,7 +179,8 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config) void cmExportInstallFileGenerator ::GenerateImportTargetsConfig(std::ostream& os, - const char* config, std::string const& suffix) + const char* config, std::string const& suffix, + std::vector &missingTargets) { // Add code to compute the installation prefix relative to the // import file location. @@ -225,7 +229,6 @@ cmExportInstallFileGenerator if(!properties.empty()) { // Get the rest of the target details. - std::vector missingTargets; this->SetImportDetailProperties(config, suffix, te->Target, properties, missingTargets); @@ -240,7 +243,6 @@ 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); diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index e719eccd5..e1877499d 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -56,7 +56,8 @@ protected: virtual bool GenerateMainFile(std::ostream& os); virtual void GenerateImportTargetsConfig(std::ostream& os, const char* config, - std::string const& suffix); + std::string const& suffix, + std::vector &missingTargets); virtual void HandleMissingTarget(std::string& link_libs, std::vector& missingTargets, cmMakefile* mf, @@ -72,7 +73,8 @@ protected: /** Generate a per-configuration file for the targets. */ - bool GenerateImportFileConfig(const char* config); + bool GenerateImportFileConfig(const char* config, + std::vector &missingTargets); /** Fill in properties indicating installed file locations. */ void SetImportLocationProperty(const char* config, From 6c828f9126453d27c45e1ca6113602fe9df8cbe2 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Jan 2013 09:48:45 +0100 Subject: [PATCH 123/131] Move the exported check for file existence. Check only once, in the Config.cmake file, instead of once in each Config-.cmake file. --- Source/cmExportInstallFileGenerator.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index bffa2b605..7eed5abf6 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -104,6 +104,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) << "ENDFOREACH(f)\n" << "\n"; + this->GenerateImportedFileCheckLoop(os); + // Generate an import file for each configuration. bool result = true; for(std::vector::const_iterator @@ -249,8 +251,6 @@ cmExportInstallFileGenerator } } - this->GenerateImportedFileCheckLoop(os); - // Cleanup the import prefix variable. if(!this->ImportPrefix.empty()) { From 1d47cd94f3748d287f676f3847d42f3674062dcd Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 12 Jan 2013 00:00:42 +0100 Subject: [PATCH 124/131] Add a test for the interfaces in targets exported from the build tree. --- Tests/ExportImport/Export/CMakeLists.txt | 1 + Tests/ExportImport/Import/A/CMakeLists.txt | 29 ++++++++++------------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 779d88958..4f6ccd66d 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -250,6 +250,7 @@ endif() # Export from build tree. export(TARGETS testExe1 testLib1 testLib2 testLib3 testExe2libImp testLib3Imp testLib3ImpDep + testSharedLibRequired testSharedLibDepends NAMESPACE bld_ FILE ExportBuildTree.cmake ) diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index abb2ab01d..6a2e54c8c 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -159,22 +159,19 @@ endif() add_executable(deps_iface deps_iface.c) target_link_libraries(deps_iface testLibDepends) -set_property(TARGET deps_iface APPEND PROPERTY - COMPILE_DEFINITIONS - $ -) -set_property(TARGET deps_iface APPEND PROPERTY - INCLUDE_DIRECTORIES - $ -) +target_include_directories(deps_iface PRIVATE testLibDepends) +target_compile_definitions(deps_iface PRIVATE testLibDepends) add_executable(deps_shared_iface deps_shared_iface.cpp) target_link_libraries(deps_shared_iface testSharedLibDepends) -set_property(TARGET deps_shared_iface APPEND PROPERTY - COMPILE_DEFINITIONS - $ -) -set_property(TARGET deps_shared_iface APPEND PROPERTY - INCLUDE_DIRECTORIES - $ -) +target_include_directories(deps_shared_iface PRIVATE testSharedLibDepends) +target_compile_definitions(deps_shared_iface PRIVATE testSharedLibDepends) + +#----------------------------------------------------------------------------- +# Test that targets imported from the build tree have their dependencies +# evaluated correctly. The above already tests the same for the install tree. + +add_executable(deps_shared_iface2 deps_shared_iface.cpp) +target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends) +target_include_directories(deps_shared_iface2 PRIVATE bld_testSharedLibDepends) +target_compile_definitions(deps_shared_iface2 PRIVATE bld_testSharedLibDepends) From 4ee872cb99f49ac5a95768da454f3313ba87182f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 12 Jan 2013 12:11:29 +0100 Subject: [PATCH 125/131] Make the BUILD_INTERFACE of export()ed targets work. The existing BUILD_INTERFACE code is executed at generate time, which is too late for export(). --- Source/cmExportBuildFileGenerator.cxx | 2 ++ Source/cmGlobalGenerator.cxx | 14 +---------- Source/cmTarget.cxx | 25 +++++++++++++++++++ Source/cmTarget.h | 3 +++ Tests/ExportImport/Export/CMakeLists.txt | 4 ++- .../ExportImport/Export/sublib/CMakeLists.txt | 6 +++++ Tests/ExportImport/Export/sublib/subdir.cpp | 7 ++++++ Tests/ExportImport/Export/sublib/subdir.h | 12 +++++++++ Tests/ExportImport/Import/A/CMakeLists.txt | 8 +++--- .../Import/A/deps_shared_iface.cpp | 14 ++++++++++- 10 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 Tests/ExportImport/Export/sublib/CMakeLists.txt create mode 100644 Tests/ExportImport/Export/sublib/subdir.cpp create mode 100644 Tests/ExportImport/Export/sublib/subdir.h diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index ad6180311..36c53dc6f 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -62,6 +62,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) cmTarget* te = *tei; this->GenerateImportTargetCode(os, te); + te->AppendBuildInterfaceIncludes(); + ImportPropertyMap properties; this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te, diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index d030aa7ba..d2baf535c 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -941,19 +941,7 @@ void cmGlobalGenerator::Generate() for ( tit = targets->begin(); tit != targets->end(); ++ tit ) { - if (mf->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES")) - { - const char *binDir = mf->GetStartOutputDirectory(); - const char *srcDir = mf->GetStartDirectory(); - const std::string dirs = std::string(binDir ? binDir : "") - + std::string(binDir ? ";" : "") - + std::string(srcDir ? srcDir : ""); - if (!dirs.empty()) - { - tit->second.AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", - ("$").c_str()); - } - } + tit->second.AppendBuildInterfaceIncludes(); } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9b50b8e52..cf01f9fa3 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -150,6 +150,7 @@ cmTarget::cmTarget() this->DLLPlatform = false; this->IsApple = false; this->IsImportedTarget = false; + this->BuildInterfaceIncludesAppended = false; } //---------------------------------------------------------------------------- @@ -2654,6 +2655,30 @@ void cmTarget::AppendProperty(const char* prop, const char* value, this->MaybeInvalidatePropertyCache(prop); } +//---------------------------------------------------------------------------- +void cmTarget::AppendBuildInterfaceIncludes() +{ + if (this->BuildInterfaceIncludesAppended) + { + return; + } + this->BuildInterfaceIncludesAppended = true; + + if (this->Makefile->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES")) + { + const char *binDir = this->Makefile->GetStartOutputDirectory(); + const char *srcDir = this->Makefile->GetStartDirectory(); + const std::string dirs = std::string(binDir ? binDir : "") + + std::string(binDir ? ";" : "") + + std::string(srcDir ? srcDir : ""); + if (!dirs.empty()) + { + this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", + ("$").c_str()); + } + } +} + //---------------------------------------------------------------------------- void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, bool before) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b4d053d84..48dde0a2a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -490,6 +490,8 @@ public: void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, bool before = false); + void AppendBuildInterfaceIncludes(); + void GetLinkDependentTargetsForProperty(const std::string &p, std::set &targets); bool IsNullImpliedByLinkLibraries(const std::string &p); @@ -611,6 +613,7 @@ private: mutable std::map > LinkDependentProperties; mutable std::set LinkImplicitNullProperties; + bool BuildInterfaceIncludesAppended; // Cache target output paths for each configuration. struct OutputInfo; diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 4f6ccd66d..e92dcd8e0 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -247,9 +247,11 @@ if(WIN32) install(TARGETS testLib5 RUNTIME DESTINATION bin) endif() +add_subdirectory(sublib) # For CMAKE_BUILD_INTERFACE_INCLUDES test. + # Export from build tree. export(TARGETS testExe1 testLib1 testLib2 testLib3 - testExe2libImp testLib3Imp testLib3ImpDep + testExe2libImp testLib3Imp testLib3ImpDep subdirlib testSharedLibRequired testSharedLibDepends NAMESPACE bld_ FILE ExportBuildTree.cmake diff --git a/Tests/ExportImport/Export/sublib/CMakeLists.txt b/Tests/ExportImport/Export/sublib/CMakeLists.txt new file mode 100644 index 000000000..2d11040a9 --- /dev/null +++ b/Tests/ExportImport/Export/sublib/CMakeLists.txt @@ -0,0 +1,6 @@ + +set(CMAKE_BUILD_INTERFACE_INCLUDES ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_library(subdirlib SHARED subdir.cpp) +generate_export_header(subdirlib) diff --git a/Tests/ExportImport/Export/sublib/subdir.cpp b/Tests/ExportImport/Export/sublib/subdir.cpp new file mode 100644 index 000000000..35b074368 --- /dev/null +++ b/Tests/ExportImport/Export/sublib/subdir.cpp @@ -0,0 +1,7 @@ + +#include "subdir.h" + +int SubDirObject::foo() +{ + return 0; +} diff --git a/Tests/ExportImport/Export/sublib/subdir.h b/Tests/ExportImport/Export/sublib/subdir.h new file mode 100644 index 000000000..3a4b73d73 --- /dev/null +++ b/Tests/ExportImport/Export/sublib/subdir.h @@ -0,0 +1,12 @@ + +#ifndef SUBDIR_H +#define SUBDIR_H + +#include "subdirlib_export.h" + +struct SUBDIRLIB_EXPORT SubDirObject +{ + int foo(); +}; + +#endif diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 6a2e54c8c..72d11b613 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -172,6 +172,8 @@ target_compile_definitions(deps_shared_iface PRIVATE testSharedLibDepends) # evaluated correctly. The above already tests the same for the install tree. add_executable(deps_shared_iface2 deps_shared_iface.cpp) -target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends) -target_include_directories(deps_shared_iface2 PRIVATE bld_testSharedLibDepends) -target_compile_definitions(deps_shared_iface2 PRIVATE bld_testSharedLibDepends) +target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib) +target_include_directories(deps_shared_iface2 PRIVATE bld_testSharedLibDepends bld_subdirlib) +target_compile_definitions(deps_shared_iface2 + PRIVATE bld_testSharedLibDepends TEST_SUBDIR_LIB +) diff --git a/Tests/ExportImport/Import/A/deps_shared_iface.cpp b/Tests/ExportImport/Import/A/deps_shared_iface.cpp index 4f7eb234a..14aac0a43 100644 --- a/Tests/ExportImport/Import/A/deps_shared_iface.cpp +++ b/Tests/ExportImport/Import/A/deps_shared_iface.cpp @@ -2,10 +2,22 @@ #include "testSharedLibDepends.h" +#ifdef TEST_SUBDIR_LIB +#include "subdir.h" +#endif + int main(int,char **) { TestSharedLibDepends dep; TestSharedLibRequired req; - return dep.foo() + req.foo(); +#ifdef TEST_SUBDIR_LIB + SubDirObject sdo; +#endif + + return dep.foo() + req.foo() +#ifdef TEST_SUBDIR_LIB + + sdo.foo() +#endif + ; } From 522bdac14963acf7c147f5518ea51382b042bf96 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 12 Jan 2013 12:13:19 +0100 Subject: [PATCH 126/131] Export the INTERFACE_PIC property. --- Source/cmExportBuildFileGenerator.cxx | 2 ++ Source/cmExportFileGenerator.cxx | 12 ++++++++++++ Source/cmExportFileGenerator.h | 2 ++ Source/cmExportInstallFileGenerator.cxx | 2 ++ Tests/ExportImport/Export/CMakeLists.txt | 4 ++++ Tests/ExportImport/Import/A/CMakeLists.txt | 18 ++++++++++++++++++ .../Import/A/deps_shared_iface.cpp | 6 ++++++ 7 files changed, 46 insertions(+) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 36c53dc6f..61e130d52 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -72,6 +72,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", + te, properties); this->GenerateInterfaceProperties(te, os, properties); } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index fc78eeb69..4a7c6f929 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -125,6 +125,18 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, this->GenerateImportTargetsConfig(os, config, suffix, missingTargets); } +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, + cmTarget *target, + ImportPropertyMap &properties) +{ + const char *input = target->GetProperty(propName); + if (input) + { + properties[propName] = input; + } +} + //---------------------------------------------------------------------------- void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, const char *outputName, diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 8620dd1c6..eb3f3c34c 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -101,6 +101,8 @@ protected: cmGeneratorExpression::PreprocessContext, ImportPropertyMap &properties, std::vector &missingTargets); + void PopulateInterfaceProperty(const char *propName, cmTarget *target, + ImportPropertyMap &properties); void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, const ImportPropertyMap &properties); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 7eed5abf6..965f63d09 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -89,6 +89,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", + te, properties); this->GenerateInterfaceProperties(te, os, properties); } diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index e92dcd8e0..fd7a1a6db 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -162,6 +162,10 @@ include(GenerateExportHeader) add_library(testSharedLibRequired SHARED testSharedLibRequired.cpp) generate_export_header(testSharedLibRequired) +set_property(TARGET testSharedLibRequired + PROPERTY + INTERFACE_POSITION_INDEPENDENT_CODE ON +) set_property(TARGET testSharedLibRequired APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}" ) diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 72d11b613..4812e7e1f 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -167,6 +167,24 @@ target_link_libraries(deps_shared_iface testSharedLibDepends) target_include_directories(deps_shared_iface PRIVATE testSharedLibDepends) target_compile_definitions(deps_shared_iface PRIVATE testSharedLibDepends) +if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-fPIE run_pic_test) +else() + if (CMAKE_CXX_COMPILER_ID MATCHES "PGI" + OR CMAKE_CXX_COMPILER_ID MATCHES "PathScale" + OR CMAKE_SYSTEM_NAME MATCHES "IRIX64" + OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") + set(run_pic_test 0) + else() + set(run_pic_test 1) + endif() +endif() + +if (run_pic_test) + target_compile_definitions(deps_shared_iface PRIVATE CHECK_PIC_WORKS) +endif() + #----------------------------------------------------------------------------- # Test that targets imported from the build tree have their dependencies # evaluated correctly. The above already tests the same for the install tree. diff --git a/Tests/ExportImport/Import/A/deps_shared_iface.cpp b/Tests/ExportImport/Import/A/deps_shared_iface.cpp index 14aac0a43..43f832a1e 100644 --- a/Tests/ExportImport/Import/A/deps_shared_iface.cpp +++ b/Tests/ExportImport/Import/A/deps_shared_iface.cpp @@ -2,6 +2,12 @@ #include "testSharedLibDepends.h" +#ifdef CHECK_PIC_WORKS +#if defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__) +#error Expected by INTERFACE_POSITION_INDEPENDENT_CODE property of dependency +#endif +#endif + #ifdef TEST_SUBDIR_LIB #include "subdir.h" #endif From 1d74ba21f6ee70936191c94448c88fd10eb1e81c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 12 Jan 2013 12:13:44 +0100 Subject: [PATCH 127/131] Test evaluation target via export for generator expressions --- Tests/ExportImport/Export/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index fd7a1a6db..dd615d135 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -186,7 +186,7 @@ set_property(TARGET testSharedLibDepends APPEND PROPERTY ) set_property(TARGET testSharedLibDepends APPEND PROPERTY LINK_INTERFACE_LIBRARIES - $<1:$> + $<$,EXECUTABLE>:$> ) # LINK_PRIVATE because the LINK_INTERFACE_LIBRARIES is specified above. From c2ab74acb9230d9218091d3fb5e87b6065f98e0b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 16 Jan 2013 00:01:30 -0500 Subject: [PATCH 128/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1e7fe5070..e724067b4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130115) +set(CMake_VERSION_TWEAK 20130116) #set(CMake_VERSION_RC 1) From 2b5459cd1a4f39ceeecd895583423ce737beb919 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 17 Jan 2013 00:01:19 -0500 Subject: [PATCH 129/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e724067b4..d1d2160db 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130116) +set(CMake_VERSION_TWEAK 20130117) #set(CMake_VERSION_RC 1) From c482dd8c976847ac89ed5e8752924a2c0ed386fa Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 18 Jan 2013 00:01:03 -0500 Subject: [PATCH 130/131] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d1d2160db..73e99dff2 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130117) +set(CMake_VERSION_TWEAK 20130118) #set(CMake_VERSION_RC 1) From f447db7f102519e09258f0bd06668a9ae572ec68 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Fri, 18 Jan 2013 11:29:22 -0500 Subject: [PATCH 131/131] XCode generator won't infinitely parse compiler flags (bug #13354). When parsing the compiler flag list we reduce the search space on each iteration to be the subset of the string we hadn't searched before. --- Source/cmGlobalXCodeGenerator.cxx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 2cfe4daba..0681ce53a 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1367,16 +1367,18 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, } //---------------------------------------------------------------------------- -// This function removes each occurence of the flag and returns the last one +// This function removes each occurrence of the flag and returns the last one // (i.e., the dominant flag in GCC) std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag, std::string& flags) { std::string retFlag; - std::string::size_type pos = flags.rfind(flag); + std::string::size_type lastOccurancePos = flags.rfind(flag); bool saved = false; - while(pos != flags.npos) + while(lastOccurancePos != flags.npos) { + //increment pos, we use lastOccurancePos to reduce search space on next inc + std::string::size_type pos = lastOccurancePos; if(pos == 0 || flags[pos-1]==' ') { while(pos < flags.size() && flags[pos] != ' ') @@ -1388,9 +1390,12 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag, flags[pos] = ' '; pos++; } - } saved = true; - pos = flags.rfind(flag); + } + //decrement lastOccurancePos while making sure we don't loop around + //and become a very large positive number since size_type is unsigned + lastOccurancePos = lastOccurancePos == 0 ? 0 : lastOccurancePos-1; + lastOccurancePos = flags.rfind(flag,lastOccurancePos); } return retFlag; }