diff options
Diffstat (limited to 'Source')
56 files changed, 1425 insertions, 471 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 73e99df..8a54237 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 20130118) +set(CMake_VERSION_TWEAK 20130205) #set(CMake_VERSION_RC 1) diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index fa21907..3993f7d 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -47,9 +47,24 @@ " $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \ " $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \ "\n" \ - " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \ - "on the target tgt. Note that tgt is not added as a dependency of\n" \ - "the target this expression is evaluated on.\n" \ + " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop " \ + "on the target tgt.\n" \ + "Note that tgt is not added as a dependency of the target this " \ + "expression is evaluated on.\n" \ + " $<LINKED:item> = An empty string if item is not a " \ + "target. If item is a target then the " \ + "INTERFACE_INCLUDE_DIRECTORIES or INTERFACE_COMPILE_DEFINITIONS " \ + "content is read from the target. " \ + "This generator expression can only be used in evaluation of the " \ + "INCLUDE_DIRECTORIES or COMPILE_DEFINITIONS property. Note that " \ + "this expression is for internal use and may be changed or removed " \ + "in the future.\n" \ + " $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \ + "the 'head' target was created, else '0'. If the policy was not " \ + "set, the warning message for the policy will be emitted. This " \ + "generator expression only works for a subset of policies.\n" \ + " $<INSTALL_PREFIX> = Content of the install prefix when " \ + "the target is exported via INSTALL(EXPORT) and empty otherwise.\n" \ "Boolean expressions:\n" \ " $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \ " $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \ @@ -60,7 +75,7 @@ #define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \ CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \ "Expressions with an implicit 'this' target:\n" \ - " $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \ + " $<TARGET_PROPERTY:prop> = The value of the property prop on " \ "the target on which the generator expression is evaluated.\n" \ "" diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 61e130d..7147f86 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -74,6 +74,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); + this->PopulateCompatibleInterfaceProperties(te, properties); this->GenerateInterfaceProperties(te, os, properties); } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 4a7c6f9..7e4c3df 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -21,9 +21,12 @@ #include "cmTarget.h" #include "cmTargetExport.h" #include "cmVersion.h" +#include "cmComputeLinkInformation.h" #include <cmsys/auto_ptr.hxx> +#include "assert.h" + //---------------------------------------------------------------------------- cmExportFileGenerator::cmExportFileGenerator() { @@ -81,16 +84,16 @@ bool cmExportFileGenerator::GenerateImportFile() // Protect that file against use with older CMake versions. os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n"; - os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n" - << " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n" - << "ENDIF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"; + os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n" + << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n" + << "endif()\n"; // Isolate the file policy level. // We use 2.6 here instead of the current version because newer // versions of CMake should be able to export files imported by 2.6 // until the import format changes. - os << "CMAKE_POLICY(PUSH)\n" - << "CMAKE_POLICY(VERSION 2.6)\n"; + os << "cmake_policy(PUSH)\n" + << "cmake_policy(VERSION 2.6)\n"; // Start with the import file header. this->GenerateImportHeaderCode(os); @@ -100,7 +103,7 @@ bool cmExportFileGenerator::GenerateImportFile() // End with the import file footer. this->GenerateImportFooterCode(os); - os << "CMAKE_POLICY(POP)\n"; + os << "cmake_policy(POP)\n"; return result; } @@ -159,7 +162,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, + this->ResolveTargetsInGeneratorExpressions(prepro, target, propName, missingTargets); properties[outputName] = prepro; } @@ -177,6 +180,85 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, properties, missingTargets); } + +//---------------------------------------------------------------------------- +void getPropertyContents(cmTarget *tgt, const char *prop, + std::set<std::string> &ifaceProperties) +{ + const char *p = tgt->GetProperty(prop); + if (!p) + { + return; + } + std::vector<std::string> content; + cmSystemTools::ExpandListArgument(p, content); + for (std::vector<std::string>::const_iterator ci = content.begin(); + ci != content.end(); ++ci) + { + ifaceProperties.insert(*ci); + } +} + +//---------------------------------------------------------------------------- +void getCompatibleInterfaceProperties(cmTarget *target, + std::set<std::string> &ifaceProperties, + const char *config) +{ + cmComputeLinkInformation *info = target->GetLinkInformation(config); + + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + if (!li->Target) + { + continue; + } + getPropertyContents(li->Target, + "COMPATIBLE_INTERFACE_BOOL", + ifaceProperties); + getPropertyContents(li->Target, + "COMPATIBLE_INTERFACE_STRING", + ifaceProperties); + } +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( + cmTarget *target, + ImportPropertyMap &properties) +{ + this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", + target, properties); + this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", + target, properties); + + std::set<std::string> ifaceProperties; + + getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties); + getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties); + + getCompatibleInterfaceProperties(target, ifaceProperties, 0); + + std::vector<std::string> configNames; + target->GetMakefile()->GetConfigurations(configNames); + + for (std::vector<std::string>::const_iterator ci = configNames.begin(); + ci != configNames.end(); ++ci) + { + getCompatibleInterfaceProperties(target, ifaceProperties, ci->c_str()); + } + + for (std::set<std::string>::const_iterator it = ifaceProperties.begin(); + it != ifaceProperties.end(); ++it) + { + this->PopulateInterfaceProperty(("INTERFACE_" + *it).c_str(), + target, properties); + } +} + //---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, std::ostream& os, @@ -184,15 +266,16 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, { if (!properties.empty()) { + os << "if(NOT ${CMAKE_FIND_PACKAGE_NAME}_NO_INTERFACES)\n"; std::string targetName = this->Namespace; targetName += target->GetName(); - os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; + 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 << " " << pi->first << " \"" << pi->second << "\"\n"; } - os << ")\n\n"; + os << " )\nendif()\n\n"; } } @@ -243,13 +326,14 @@ static bool isGeneratorExpression(const std::string &lib) void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets, FreeTargetsReplace replace) { if (replace == NoReplaceFreeTargets) { - this->ResolveTargetsInGeneratorExpression(input, target, missingTargets); + this->ResolveTargetsInGeneratorExpression(input, target, propName, + missingTargets); return; } std::vector<std::string> parts; @@ -268,7 +352,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( { this->ResolveTargetsInGeneratorExpression( *li, - target, + target, propName, missingTargets); } input += sep + *li; @@ -280,14 +364,13 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets) { std::string::size_type pos = 0; std::string::size_type lastPos = pos; cmMakefile *mf = target->GetMakefile(); - std::string errorString; while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos) { @@ -308,14 +391,58 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string targetName = input.substr(nameStartPos, commaPos - nameStartPos); - if (!this->AddTargetNamespace(targetName, target, missingTargets)) + if (this->AddTargetNamespace(targetName, target, missingTargets)) + { + input.replace(nameStartPos, commaPos - nameStartPos, targetName); + } + lastPos = nameStartPos + targetName.size() + 1; + } + + std::string errorString; + pos = 0; + lastPos = pos; + while((pos = input.find("$<LINKED:", lastPos)) != input.npos) + { + std::string::size_type nameStartPos = pos + sizeof("$<LINKED:") - 1; + std::string::size_type endPos = input.find(">", nameStartPos); + if (endPos == input.npos) + { + errorString = "$<LINKED:...> expression incomplete"; + break; + } + std::string targetName = input.substr(nameStartPos, + endPos - nameStartPos); + if(targetName.find("$<") != input.npos) { - errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires " - "its first parameter to be a reachable target."; + errorString = "$<LINKED:...> requires its parameter to be a " + "literal."; break; } - input.replace(nameStartPos, commaPos - nameStartPos, targetName); - lastPos = pos + targetName.size(); + if (this->AddTargetNamespace(targetName, target, missingTargets)) + { + assert(propName); // The link libraries strings will + // never contain $<LINKED> + std::string replacement = "$<TARGET_PROPERTY:" + + targetName + "," + propName; + input.replace(pos, endPos - pos, replacement); + lastPos = pos + replacement.size() + 1; + } + else + { + if (pos != 0) + { + if (input[pos - 1] == ';') + { + --pos; + } + } + else if (input[endPos + 1] == ';') + { + ++endPos; + } + input.replace(pos, endPos - pos + 1, ""); + lastPos = pos; + } } if (!errorString.empty()) { @@ -351,6 +478,9 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression( input.replace(pos, endPos - pos + 1, targetName); lastPos = endPos; } + + this->ReplaceInstallPrefix(input); + if (!errorString.empty()) { mf->IssueMessage(cmake::FATAL_ERROR, errorString); @@ -359,6 +489,13 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression( //---------------------------------------------------------------------------- void +cmExportFileGenerator::ReplaceInstallPrefix(std::string &) +{ + // Do nothing +} + +//---------------------------------------------------------------------------- +void cmExportFileGenerator ::SetImportLinkInterface(const char* config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, @@ -408,7 +545,7 @@ cmExportFileGenerator preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, + this->ResolveTargetsInGeneratorExpressions(prepro, target, 0, missingTargets, ReplaceFreeTargets); properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro; @@ -536,7 +673,7 @@ void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os, void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os) { os << "# Commands beyond this point should not need to know the version.\n" - << "SET(CMAKE_IMPORT_FILE_VERSION)\n"; + << "set(CMAKE_IMPORT_FILE_VERSION)\n"; } //---------------------------------------------------------------------------- @@ -545,7 +682,7 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os) // Store an import file format version. This will let us change the // format later while still allowing old import files to work. os << "# Commands may need to know the format version.\n" - << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n" + << "set(CMAKE_IMPORT_FILE_VERSION 1)\n" << "\n"; } @@ -553,31 +690,31 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os) void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os, const std::string &expectedTargets) { - os << "SET(_targetsDefined)\n" - "SET(_targetsNotDefined)\n" - "SET(_expectedTargets)\n" - "FOREACH(_expectedTarget " << expectedTargets << ")\n" - " LIST(APPEND _expectedTargets ${_expectedTarget})\n" - " IF(NOT TARGET ${_expectedTarget})\n" - " LIST(APPEND _targetsNotDefined ${_expectedTarget})\n" - " ENDIF(NOT TARGET ${_expectedTarget})\n" - " IF(TARGET ${_expectedTarget})\n" - " LIST(APPEND _targetsDefined ${_expectedTarget})\n" - " ENDIF(TARGET ${_expectedTarget})\n" - "ENDFOREACH(_expectedTarget)\n" - "IF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" - " SET(CMAKE_IMPORT_FILE_VERSION)\n" - " CMAKE_POLICY(POP)\n" - " RETURN()\n" - "ENDIF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" - "IF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" - " MESSAGE(FATAL_ERROR \"Some (but not all) targets in this export " + os << "set(_targetsDefined)\n" + "set(_targetsNotDefined)\n" + "set(_expectedTargets)\n" + "foreach(_expectedTarget " << expectedTargets << ")\n" + " list(APPEND _expectedTargets ${_expectedTarget})\n" + " if(NOT TARGET ${_expectedTarget})\n" + " list(APPEND _targetsNotDefined ${_expectedTarget})\n" + " endif()\n" + " if(TARGET ${_expectedTarget})\n" + " list(APPEND _targetsDefined ${_expectedTarget})\n" + " endif()\n" + "endforeach()\n" + "if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" + " set(CMAKE_IMPORT_FILE_VERSION)\n" + " cmake_policy(POP)\n" + " return()\n" + "endif()\n" + "if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" + " message(FATAL_ERROR \"Some (but not all) targets in this export " "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n" "Targets not yet defined: ${_targetsNotDefined}\\n\")\n" - "ENDIF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" - "UNSET(_targetsDefined)\n" - "UNSET(_targetsNotDefined)\n" - "UNSET(_expectedTargets)\n" + "endif()\n" + "unset(_targetsDefined)\n" + "unset(_targetsNotDefined)\n" + "unset(_expectedTargets)\n" "\n\n"; } //---------------------------------------------------------------------------- @@ -594,16 +731,16 @@ cmExportFileGenerator switch(target->GetType()) { case cmTarget::EXECUTABLE: - os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n"; + os << "add_executable(" << targetName << " IMPORTED)\n"; break; case cmTarget::STATIC_LIBRARY: - os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n"; + os << "add_library(" << targetName << " STATIC IMPORTED)\n"; break; case cmTarget::SHARED_LIBRARY: - os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n"; + os << "add_library(" << targetName << " SHARED IMPORTED)\n"; break; case cmTarget::MODULE_LIBRARY: - os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n"; + os << "add_library(" << targetName << " MODULE IMPORTED)\n"; break; default: // should never happen break; @@ -612,27 +749,27 @@ cmExportFileGenerator // Mark the imported executable if it has exports. if(target->IsExecutableWithExports()) { - os << "SET_PROPERTY(TARGET " << targetName + os << "set_property(TARGET " << targetName << " PROPERTY ENABLE_EXPORTS 1)\n"; } // Mark the imported library if it is a framework. if(target->IsFrameworkOnApple()) { - os << "SET_PROPERTY(TARGET " << targetName + os << "set_property(TARGET " << targetName << " PROPERTY FRAMEWORK 1)\n"; } // Mark the imported executable if it is an application bundle. if(target->IsAppBundleOnApple()) { - os << "SET_PROPERTY(TARGET " << targetName + os << "set_property(TARGET " << targetName << " PROPERTY MACOSX_BUNDLE 1)\n"; } if (target->IsCFBundleOnApple()) { - os << "SET_PROPERTY(TARGET " << targetName + os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n"; } os << "\n"; @@ -652,7 +789,7 @@ cmExportFileGenerator // Set the import properties. os << "# Import target \"" << targetName << "\" for configuration \"" << config << "\"\n"; - os << "SET_PROPERTY(TARGET " << targetName + os << "set_property(TARGET " << targetName << " APPEND PROPERTY IMPORTED_CONFIGURATIONS "; if(config && *config) { @@ -663,7 +800,7 @@ cmExportFileGenerator os << "NOCONFIG"; } os << ")\n"; - os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; + os << "set_target_properties(" << targetName << " PROPERTIES\n"; for(ImportPropertyMap::const_iterator pi = properties.begin(); pi != properties.end(); ++pi) { @@ -689,17 +826,17 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os, { if (emitted.insert(missingTargets[i]).second) { - os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n" - << " IF(CMAKE_FIND_PACKAGE_NAME)\n" - << " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n" - << " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE " + os << "if(NOT TARGET \"" << missingTargets[i] << "\" )\n" + << " if(CMAKE_FIND_PACKAGE_NAME)\n" + << " set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n" + << " set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE " << "\"Required imported target \\\"" << missingTargets[i] << "\\\" not found ! \")\n" - << " ELSE()\n" - << " MESSAGE(FATAL_ERROR \"Required imported target \\\"" + << " else()\n" + << " message(FATAL_ERROR \"Required imported target \\\"" << missingTargets[i] << "\\\" not found ! \")\n" - << " ENDIF()\n" - << "ENDIF()\n"; + << " endif()\n" + << "endif()\n"; } } os << "\n"; @@ -718,10 +855,10 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) // on SUSE with a mysql pkg-config file, which claimed everything is fine, // but the development package was not installed.). os << "# Loop over all imported files and verify that they actually exist\n" - "FOREACH(target ${_IMPORT_CHECK_TARGETS} )\n" - " FOREACH(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n" - " IF(NOT EXISTS \"${file}\" )\n" - " MESSAGE(FATAL_ERROR \"The imported target \\\"${target}\\\"" + "foreach(target ${_IMPORT_CHECK_TARGETS} )\n" + " foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n" + " if(NOT EXISTS \"${file}\" )\n" + " message(FATAL_ERROR \"The imported target \\\"${target}\\\"" " references the file\n" " \\\"${file}\\\"\n" "but this file does not exist. Possible reasons include:\n" @@ -731,11 +868,11 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) " \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n" "but not all the files it references.\n" "\")\n" - " ENDIF()\n" - " ENDFOREACH()\n" - " UNSET(_IMPORT_CHECK_FILES_FOR_${target})\n" - "ENDFOREACH()\n" - "UNSET(_IMPORT_CHECK_TARGETS)\n" + " endif()\n" + " endforeach()\n" + " unset(_IMPORT_CHECK_FILES_FOR_${target})\n" + "endforeach()\n" + "unset(_IMPORT_CHECK_TARGETS)\n" "\n"; } @@ -751,8 +888,8 @@ cmExportFileGenerator std::string targetName = this->Namespace; targetName += target->GetName(); - os << "LIST(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n" - "LIST(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " "; + os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n" + "list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " "; for(std::set<std::string>::const_iterator li = importedLocations.begin(); li != importedLocations.end(); diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index eb3f3c3..5ad27bf 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -103,6 +103,8 @@ protected: std::vector<std::string> &missingTargets); void PopulateInterfaceProperty(const char *propName, cmTarget *target, ImportPropertyMap &properties); + void PopulateCompatibleInterfaceProperties(cmTarget *target, + ImportPropertyMap &properties); void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, const ImportPropertyMap &properties); @@ -117,7 +119,7 @@ protected: }; void ResolveTargetsInGeneratorExpressions(std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets, FreeTargetsReplace replace = NoReplaceFreeTargets); @@ -148,8 +150,10 @@ private: std::vector<std::string> &missingTargets); void ResolveTargetsInGeneratorExpression(std::string &input, - cmTarget* target, + cmTarget* target, const char *propName, std::vector<std::string> &missingTargets); + + virtual void ReplaceInstallPrefix(std::string &input); }; #endif diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 965f63d..b6600f0 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -57,7 +57,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) else { cmOStringStream e; - e << "INSTALL(EXPORT \"" + e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName() << "\" ...) " << "includes target \"" << te->Target->GetName() << "\" more than once in the export set."; @@ -69,6 +69,27 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateExpectedTargetsCode(os, expectedTargets); } + // Add code to compute the installation prefix relative to the + // import file location. + const char* installDest = this->IEGen->GetDestination(); + if(!cmSystemTools::FileIsFullPath(installDest)) + { + std::string dest = installDest; + os << "# Compute the installation prefix relative to this file.\n" + << "get_filename_component(_IMPORT_PREFIX " + << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"; + while(!dest.empty()) + { + os << + "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n"; + dest = cmSystemTools::GetFilenamePath(dest); + } + os << "\n"; + + // Import location properties may reference this variable. + this->ImportPrefix = "${_IMPORT_PREFIX}/"; + } + std::vector<std::string> missingTargets; // Create all the imported targets. @@ -91,6 +112,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); + this->PopulateCompatibleInterfaceProperties(te, properties); this->GenerateInterfaceProperties(te, os, properties); } @@ -98,14 +120,21 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) // 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" - << "FILE(GLOB CONFIG_FILES \"${_DIR}/" + << "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n" + << "file(GLOB CONFIG_FILES \"${_DIR}/" << this->GetConfigImportFileGlob() << "\")\n" - << "FOREACH(f ${CONFIG_FILES})\n" - << " INCLUDE(${f})\n" - << "ENDFOREACH(f)\n" + << "foreach(f ${CONFIG_FILES})\n" + << " include(${f})\n" + << "endforeach()\n" << "\n"; + // Cleanup the import prefix variable. + if(!this->ImportPrefix.empty()) + { + os << "# Cleanup temporary variables.\n" + << "set(_IMPORT_PREFIX)\n" + << "\n"; + } this->GenerateImportedFileCheckLoop(os); // Generate an import file for each configuration. @@ -126,6 +155,21 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) } //---------------------------------------------------------------------------- +void +cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string &input) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + while((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != input.npos) + { + std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1; + input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}"); + lastPos = endPos; + } +} + +//---------------------------------------------------------------------------- bool cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config, std::vector<std::string> &missingTargets) @@ -186,27 +230,6 @@ cmExportInstallFileGenerator const char* config, std::string const& suffix, std::vector<std::string> &missingTargets) { - // Add code to compute the installation prefix relative to the - // import file location. - const char* installDest = this->IEGen->GetDestination(); - if(!cmSystemTools::FileIsFullPath(installDest)) - { - std::string dest = installDest; - os << "# Compute the installation prefix relative to this file.\n" - << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX " - << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"; - while(!dest.empty()) - { - os << - "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n"; - dest = cmSystemTools::GetFilenamePath(dest); - } - os << "\n"; - - // Import location properties may reference this variable. - this->ImportPrefix = "${_IMPORT_PREFIX}/"; - } - // Add each target in the set to the export. for(std::vector<cmTargetExport*>::const_iterator tei = this->IEGen->GetExportSet()->GetTargetExports()->begin(); @@ -252,14 +275,6 @@ cmExportInstallFileGenerator importedLocations); } } - - // Cleanup the import prefix variable. - if(!this->ImportPrefix.empty()) - { - os << "# Cleanup temporary variables.\n" - << "SET(_IMPORT_PREFIX)\n" - << "\n"; - } } //---------------------------------------------------------------------------- @@ -427,7 +442,7 @@ cmExportInstallFileGenerator { const char* installDest = this->IEGen->GetDestination(); cmOStringStream e; - e << "INSTALL(EXPORT \"" + e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName() << "\") given absolute " << "DESTINATION \"" << installDest << "\" but the export " @@ -445,7 +460,7 @@ cmExportInstallFileGenerator int occurrences) { cmOStringStream e; - e << "INSTALL(EXPORT \"" + e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName() << "\" ...) " << "includes target \"" << depender->GetName() diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index e187749..7a70431 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -64,6 +64,8 @@ protected: cmTarget* depender, cmTarget* dependee); + virtual void ReplaceInstallPrefix(std::string &input); + void ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee, int occurrences); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 0cf9cbb..6d5d5b5 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -621,7 +621,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, ->GetGeneratorTarget(target); // the compilerdefines for this target - std::string cdefs = gtgt->GetCompileDefinitions(); + std::string cdefs = target->GetCompileDefinitions(); if(!cdefs.empty()) { diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index a4aa75a..b08c335 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -37,9 +37,13 @@ bool cmFLTKWrapUICommand // get the list of GUI files from which .cxx and .h will be generated std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory(); + { // Some of the generated files are *.h so the directory "GUI" // where they are created have to be added to the include path - this->Makefile->AddIncludeDirectory( outputDirectory.c_str() ); + std::vector<std::string> outputDirectories; + outputDirectories.push_back(outputDirectory); + this->Makefile->AddIncludeDirectories( outputDirectories ); + } for(std::vector<std::string>::iterator i = (newArgs.begin() + 1); i != newArgs.end(); i++) diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 470ceca..6e78bd7 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -376,6 +376,26 @@ void cmFindPackageCommand::GenerateDocumentation() "The package configuration file may set <package>_FOUND to false " "to tell find_package that component requirements are not satisfied." "\n" + "A package configuration file may include() a <package>Targets.cmake " + "file, created by install(EXPORT) in the upstream source, to import " + "targets into the downstream consumer. " + "When a new version of the upstream adds INTERFACE properties not " + "present in a previous version it can change behavior for existing " + "downstreams. " + "In order to remain source compatible the upstream package configuration " + "file may set <package>_NO_INTERFACES to disable INTERFACE properties. " + "For example, code of the form:\n" + " if(<package>_FIND_VERSION VERSION_LESS <new-version>\n" + " AND NOT <package>_INTERFACES)\n" + " set(<package>_NO_INTERFACES 1)\n" + " endif()\n" + " include(\"${CMAKE_CURRENT_LIST_DIR}/<package>Targets.cmake\")\n" + "tells <package>Targets.cmake not to provide the INTERFACE properties " + "unless the downstream requests at least <new-version> or sets " + "<package>_INTERFACES to explicitly request them. " + "This allows consumers to decide when to enable the new interfaces when " + "upgrading." + "\n" "See the cmake_policy() command documentation for discussion of the " "NO_POLICY_SCOPE option." ; diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 78ae8f2..7add1bf 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -88,6 +88,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Config = config; context.Quiet = quiet; context.HadError = false; + context.HadContextSensitiveCondition = false; context.HeadTarget = headTarget; context.CurrentTarget = currentTarget ? currentTarget : headTarget; context.Backtrace = this->Backtrace; @@ -109,6 +110,10 @@ const char *cmCompiledGeneratorExpression::Evaluate( break; } } + if (!context.HadError) + { + this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; + } this->Targets = context.Targets; // TODO: Return a std::string from here instead? @@ -118,7 +123,8 @@ const char *cmCompiledGeneratorExpression::Evaluate( cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace const& backtrace, const char *input) - : Backtrace(backtrace), Input(input ? input : "") + : Backtrace(backtrace), Input(input ? input : ""), + HadContextSensitiveCondition(false) { cmGeneratorExpressionLexer l; std::vector<cmGeneratorExpressionToken> tokens = diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 8f1aef6..700fe03 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -100,6 +100,10 @@ public: { return this->Backtrace; } + bool GetHadContextSensitiveCondition() const + { + return this->HadContextSensitiveCondition; + } private: cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, @@ -118,6 +122,7 @@ private: mutable std::set<cmTarget*> Targets; mutable std::map<cmStdString, cmStdString> SeenTargetProperties; mutable std::string Output; + mutable bool HadContextSensitiveCondition; }; #endif diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 2e5b5ae..b9069ef 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -24,7 +24,33 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( : Parent(parent), Target(target), Property(property), Content(content), Backtrace(backtrace) { + const cmGeneratorExpressionDAGChecker *top = this; + const cmGeneratorExpressionDAGChecker *p = this->Parent; + while (p) + { + top = p; + p = p->Parent; + } this->CheckResult = this->checkGraph(); + + if (CheckResult == DAG && (top->Property == "INCLUDE_DIRECTORIES" + || top->Property == "COMPILE_DEFINITIONS") ) + { + std::map<cmStdString, std::set<cmStdString> >::const_iterator it + = top->Seen.find(target); + if (it != top->Seen.end()) + { + const std::set<cmStdString> &propSet = it->second; + const std::set<cmStdString>::const_iterator i = propSet.find(property); + if (i != propSet.end()) + { + this->CheckResult = ALREADY_SEEN; + return; + } + } + const_cast<cmGeneratorExpressionDAGChecker *>(top) + ->Seen[target].insert(property); + } } //---------------------------------------------------------------------------- @@ -106,3 +132,38 @@ cmGeneratorExpressionDAGChecker::checkGraph() const } return DAG; } + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries() +{ + const cmGeneratorExpressionDAGChecker *top = this; + const cmGeneratorExpressionDAGChecker *parent = this->Parent; + while (parent) + { + top = parent; + parent = parent->Parent; + } + + const char *prop = top->Property.c_str(); + return (strcmp(prop, "LINK_LIBRARIES") == 0 + || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 + || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 + || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 26) == 0 + || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 35) == 0); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() +{ + const char *prop = this->Property.c_str(); + return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0 + || strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 ); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() +{ + const char *prop = this->Property.c_str(); + return (strcmp(prop, "COMPILE_DEFINITIONS") == 0 + || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0 ); +} diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 48f26ed..a2e5ce4 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -28,13 +28,19 @@ struct cmGeneratorExpressionDAGChecker enum Result { DAG, SELF_REFERENCE, - CYCLIC_REFERENCE + CYCLIC_REFERENCE, + ALREADY_SEEN }; Result check() const; void reportError(cmGeneratorExpressionContext *context, const std::string &expr); + + bool EvaluatingLinkLibraries(); + bool EvaluatingIncludeDirectories(); + bool EvaluatingCompileDefinitions(); + private: Result checkGraph() const; @@ -42,6 +48,7 @@ private: const cmGeneratorExpressionDAGChecker * const Parent; const std::string Target; const std::string Property; + std::map<cmStdString, std::set<cmStdString> > Seen; const GeneratorExpressionContent * const Content; const cmListFileBacktrace Backtrace; Result CheckResult; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 8e40815a..5d94718 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -238,6 +238,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode const GeneratorExpressionContent *, cmGeneratorExpressionDAGChecker *) const { + context->HadContextSensitiveCondition = true; return context->Config ? context->Config : ""; } } configurationNode; @@ -262,6 +263,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } + context->HadContextSensitiveCondition = true; if (!context->Config) { return parameters.front().empty() ? "1" : "0"; @@ -435,6 +437,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: // No error. We just skip cyclic references. return std::string(); + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We're not going to find anything new here. + return std::string(); case cmGeneratorExpressionDAGChecker::DAG: break; } @@ -442,6 +447,39 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode const char *prop = target->GetProperty(propertyName.c_str()); if (!prop) { + if (target->IsImported()) + { + return std::string(); + } + if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries()) + { + return std::string(); + } + if (propertyName == "POSITION_INDEPENDENT_CODE") + { + context->HadContextSensitiveCondition = true; + return target->GetLinkInterfaceDependentBoolProperty( + "POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0"; + } + if (target->IsLinkInterfaceDependentBoolProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + return target->GetLinkInterfaceDependentBoolProperty( + propertyName, + context->Config) ? "1" : "0"; + } + if (target->IsLinkInterfaceDependentStringProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + const char *propContent = + target->GetLinkInterfaceDependentStringProperty( + propertyName, + context->Config); + return propContent ? propContent : ""; + } + return std::string(); } @@ -453,12 +491,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (targetPropertyTransitiveWhitelist[i] == propertyName) { cmGeneratorExpression ge(context->Backtrace); - return ge.Parse(prop)->Evaluate(context->Makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); + std::string result = cge->Evaluate(context->Makefile, context->Config, context->Quiet, context->HeadTarget, target, &dagChecker); + + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + return result; } } return prop; @@ -488,6 +533,221 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode } targetNameNode; //---------------------------------------------------------------------------- +static const char* targetPolicyWhitelist[] = { + "CMP0003" + , "CMP0004" + , "CMP0008" + , "CMP0020" +}; + +cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy) +{ +#define RETURN_POLICY(POLICY) \ + if (strcmp(policy, #POLICY) == 0) \ + { \ + return tgt->GetPolicyStatus ## POLICY (); \ + } \ + + RETURN_POLICY(CMP0003) + RETURN_POLICY(CMP0004) + RETURN_POLICY(CMP0008) + RETURN_POLICY(CMP0020) + +#undef RETURN_POLICY + + assert("!Unreachable code. Not a valid policy"); + return cmPolicies::WARN; +} + +cmPolicies::PolicyID policyForString(const char *policy_id) +{ +#define RETURN_POLICY_ID(POLICY_ID) \ + if (strcmp(policy_id, #POLICY_ID) == 0) \ + { \ + return cmPolicies:: POLICY_ID; \ + } \ + + RETURN_POLICY_ID(CMP0003) + RETURN_POLICY_ID(CMP0004) + RETURN_POLICY_ID(CMP0008) + RETURN_POLICY_ID(CMP0020) + +#undef RETURN_POLICY_ID + + assert("!Unreachable code. Not a valid policy"); + return cmPolicies::CMP0002; +} + +//---------------------------------------------------------------------------- +static const struct TargetPolicyNode : public cmGeneratorExpressionNode +{ + TargetPolicyNode() {} + + virtual int NumExpectedParameters() const { return 1; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context , + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const + { + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_POLICY:prop> may only be used with targets. It may not " + "be used with add_custom_command."); + return std::string(); + } + + context->HadContextSensitiveCondition = true; + + for (size_t i = 0; + i < (sizeof(targetPolicyWhitelist) / + sizeof(*targetPolicyWhitelist)); + ++i) + { + const char *policy = targetPolicyWhitelist[i]; + if (parameters.front() == policy) + { + cmMakefile *mf = context->HeadTarget->GetMakefile(); + switch(statusForTarget(context->HeadTarget, policy)) + { + case cmPolicies::WARN: + mf->IssueMessage(cmake::AUTHOR_WARNING, + mf->GetPolicies()-> + GetPolicyWarning(policyForString(policy))); + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::OLD: + return "0"; + case cmPolicies::NEW: + return "1"; + } + } + } + reportError(context, content->GetOriginalExpression(), + "$<TARGET_POLICY:prop> may only be used with a limited number of " + "policies. Currently it may be used with policies CMP0003, CMP0004, " + "CMP0008 and CMP0020." + ); + return std::string(); + } + +} targetPolicyNode; + +//---------------------------------------------------------------------------- +static const struct InstallPrefixNode : public cmGeneratorExpressionNode +{ + InstallPrefixNode() {} + + virtual bool GeneratesContent() const { return true; } + virtual int NumExpectedParameters() const { return 0; } + + std::string Evaluate(const std::vector<std::string> &, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const + { + reportError(context, content->GetOriginalExpression(), + "INSTALL_PREFIX is a marker for install(EXPORT) only. It " + "should never be evaluated."); + return std::string(); + } + +} installPrefixNode; + +//---------------------------------------------------------------------------- +static const struct LinkedNode : public cmGeneratorExpressionNode +{ + LinkedNode() {} + + virtual bool GeneratesContent() const { return true; } + virtual int NumExpectedParameters() const { return 1; } + virtual bool RequiresLiteralInput() const { return true; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (dagChecker->EvaluatingIncludeDirectories()) + { + return this->GetInterfaceProperty(parameters.front(), + "INCLUDE_DIRECTORIES", + context, content, dagChecker); + } + if (dagChecker->EvaluatingCompileDefinitions()) + { + return this->GetInterfaceProperty(parameters.front(), + "COMPILE_DEFINITIONS", + context, content, dagChecker); + } + + reportError(context, content->GetOriginalExpression(), + "$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and " + "COMPILE_DEFINITIONS properties."); + + return std::string(); + } + +private: + std::string GetInterfaceProperty(const std::string &item, + const std::string &prop, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagCheckerParent) const + { + cmTarget *target = context->CurrentTarget + ->GetMakefile()->FindTargetToUse(item.c_str()); + if (!target) + { + return std::string(); + } + std::string propertyName = "INTERFACE_" + prop; + const char *propContent = target->GetProperty(propertyName.c_str()); + if (!propContent) + { + return std::string(); + } + + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, + target->GetName(), + propertyName, + content, + dagCheckerParent); + + 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::ALREADY_SEEN: + // No error. We're not going to find anything new here. + return std::string(); + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + cmGeneratorExpression ge(context->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propContent); + std::string result = cge->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + &dagChecker); + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + return result; + } + +} linkedNode; + +//---------------------------------------------------------------------------- template<bool linker, bool soname> struct TargetFilesystemArtifactResultCreator { @@ -714,12 +974,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &targetPropertyNode; else if (identifier == "TARGET_NAME") return &targetNameNode; + else if (identifier == "TARGET_POLICY") + return &targetPolicyNode; else if (identifier == "BUILD_INTERFACE") return &buildInterfaceNode; else if (identifier == "INSTALL_INTERFACE") return &installInterfaceNode; else if (identifier == "TARGET_DEFINED") return &targetDefinedNode; + else if (identifier == "INSTALL_PREFIX") + return &installPrefixNode; + else if (identifier == "LINKED") + return &linkedNode; return 0; } diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index fb6c7ee..37d5c86 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -32,6 +32,7 @@ struct cmGeneratorExpressionContext // directly or indirectly in the property. bool Quiet; bool HadError; + bool HadContextSensitiveCondition; }; struct cmGeneratorExpressionDAGChecker; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 62ee26a..335ba0f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -254,32 +254,3 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories( { return this->Target->GetIncludeDirectories(config); } - -//---------------------------------------------------------------------------- -std::string cmGeneratorTarget::GetCompileDefinitions(const char *config) -{ - std::string defPropName = "COMPILE_DEFINITIONS"; - if (config) - { - defPropName += "_" + cmSystemTools::UpperCase(config); - } - - const char *prop = this->Target->GetProperty(defPropName.c_str()); - - if (!prop) - { - return ""; - } - - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); - - cmGeneratorExpressionDAGChecker dagChecker(lfbt, - this->GetName(), - defPropName, 0, 0); - return ge.Parse(prop)->Evaluate(this->Makefile, - config, - false, - this->Target, - &dagChecker); -} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 6f5ecb7..cbcd8a5 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -68,8 +68,6 @@ public: /** Get the include directories for this target. */ std::vector<std::string> GetIncludeDirectories(const char *config); - std::string GetCompileDefinitions(const char *config = 0); - private: void ClassifySources(); void LookupObjectLibraries(); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index d8afa53..ba29589 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -994,6 +994,7 @@ void cmGlobalGenerator::Generate() // Generate project files for (i = 0; i < this->LocalGenerators.size(); ++i) { + this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem(); this->SetCurrentLocalGenerator(this->LocalGenerators[i]); this->LocalGenerators[i]->Generate(); this->LocalGenerators[i]->GenerateInstallRules(); @@ -1077,7 +1078,8 @@ void cmGlobalGenerator::CreateAutomocTargets() if(target.GetType() == cmTarget::EXECUTABLE || target.GetType() == cmTarget::STATIC_LIBRARY || target.GetType() == cmTarget::SHARED_LIBRARY || - target.GetType() == cmTarget::MODULE_LIBRARY) + target.GetType() == cmTarget::MODULE_LIBRARY || + target.GetType() == cmTarget::OBJECT_LIBRARY) { if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported()) { diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 316ecfd..9600771 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1700,11 +1700,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->AppendDefines(ppDefs, exportMacro); } cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); - this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str()); + this->AppendDefines(ppDefs, target.GetCompileDefinitions().c_str()); if(configName) { this->AppendDefines(ppDefs, - gtgt->GetCompileDefinitions(configName).c_str()); + target.GetCompileDefinitions(configName).c_str()); } buildSettings->AddAttribute ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index ba81849..671e09f 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -36,6 +36,10 @@ bool cmIncludeDirectoryCommand ++i; } + std::vector<std::string> beforeIncludes; + std::vector<std::string> afterIncludes; + std::set<cmStdString> systemIncludes; + for(; i != args.end(); ++i) { if(*i == "SYSTEM") @@ -49,9 +53,37 @@ bool cmIncludeDirectoryCommand return false; } - this->AddDirectory(i->c_str(),before,system); + std::vector<std::string> includes; + + GetIncludes(*i, includes); + if (before) + { + beforeIncludes.insert(beforeIncludes.end(), + includes.begin(), + includes.end()); + } + else + { + afterIncludes.insert(afterIncludes.end(), + includes.begin(), + includes.end()); + } + if (system) + { + for (std::vector<std::string>::const_iterator li = includes.begin(); + li != includes.end(); ++li) + { + systemIncludes.insert(*li); + } + } } + std::reverse(beforeIncludes.begin(), beforeIncludes.end()); + + this->Makefile->AddIncludeDirectories(afterIncludes); + this->Makefile->AddIncludeDirectories(beforeIncludes, before); + this->Makefile->AddSystemIncludeDirectories(systemIncludes); + return true; } @@ -72,57 +104,49 @@ static bool StartsWithGeneratorExpression(const std::string &input) // output from a program and passing it into a command the cleanup doesn't // always happen // -void cmIncludeDirectoryCommand::AddDirectory(const char *i, - bool before, - bool system) +void cmIncludeDirectoryCommand::GetIncludes(const std::string &arg, + std::vector<std::string> &incs) { // break apart any line feed arguments - std::string ret = i; std::string::size_type pos = 0; - if((pos = ret.find('\n', pos)) != std::string::npos) + std::string::size_type lastPos = 0; + while((pos = arg.find('\n', lastPos)) != std::string::npos) { if (pos) { - this->AddDirectory(ret.substr(0,pos).c_str(), before, system); - } - if (ret.size()-pos-1) - { - this->AddDirectory(ret.substr(pos+1,ret.size()-pos-1).c_str(), - before, system); + std::string inc = arg.substr(lastPos,pos); + NormalizeInclude(inc); + incs.push_back(inc); } - return; + lastPos = pos + 1; } + std::string inc = arg.substr(lastPos); + NormalizeInclude(inc); + incs.push_back(inc); +} - // remove any leading or trailing spaces and \r - std::string::size_type b = ret.find_first_not_of(" \r"); - std::string::size_type e = ret.find_last_not_of(" \r"); - if ((b!=ret.npos) && (e!=ret.npos)) - { - ret.assign(ret, b, 1+e-b); // copy the remaining substring - } - else +void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc) +{ + std::string::size_type b = inc.find_first_not_of(" \r"); + std::string::size_type e = inc.find_last_not_of(" \r"); + if ((b!=inc.npos) && (e!=inc.npos)) { - return; // if we get here, we had only whitespace in the string + inc.assign(inc, b, 1+e-b); // copy the remaining substring } - if (!cmSystemTools::IsOff(ret.c_str())) + if (!cmSystemTools::IsOff(inc.c_str())) { - cmSystemTools::ConvertToUnixSlashes(ret); - if(!cmSystemTools::FileIsFullPath(ret.c_str())) + cmSystemTools::ConvertToUnixSlashes(inc); + + if(!cmSystemTools::FileIsFullPath(inc.c_str())) { - if(!StartsWithGeneratorExpression(ret)) + if(!StartsWithGeneratorExpression(inc)) { std::string tmp = this->Makefile->GetStartDirectory(); tmp += "/"; - tmp += ret; - ret = tmp; + tmp += inc; + inc = tmp; } } } - this->Makefile->AddIncludeDirectory(ret.c_str(), before); - if(system) - { - this->Makefile->AddSystemIncludeDirectory(ret.c_str()); - } } - diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h index dd37b82..77a340a 100644 --- a/Source/cmIncludeDirectoryCommand.h +++ b/Source/cmIncludeDirectoryCommand.h @@ -59,8 +59,9 @@ public: return " include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)\n" "Add the given directories to those the compiler uses to search " - "for include files. " - "These directories are added to the directory property " + "for include files. Relative paths are interpreted as relative to " + "the current source directory. \n" + "The include directories are added to the directory property " "INCLUDE_DIRECTORIES for the current CMakeLists file. " "They are also added to the target property INCLUDE_DIRECTORIES " "for each target in the current CMakeLists file. " @@ -84,7 +85,8 @@ public: protected: // used internally - void AddDirectory(const char *arg, bool before, bool system); + void GetIncludes(const std::string &arg, std::vector<std::string> &incs); + void NormalizeInclude(std::string &inc); }; diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h index 889118c..9218f44 100644 --- a/Source/cmLinkDirectoriesCommand.h +++ b/Source/cmLinkDirectoriesCommand.h @@ -62,10 +62,8 @@ public: " link_directories(directory1 directory2 ...)\n" "Specify the paths in which the linker should search for libraries. " "The command will apply only to targets created after it is called. " - "For historical reasons, relative paths given to this command are " - "passed to the linker unchanged " - "(unlike many CMake commands which interpret them relative to the " - "current source directory).\n" + "Relative paths given to this command are interpreted as relative to " + "the current source directory, see CMP0015. \n" "Note that this command is rarely necessary. Library locations " "returned by find_package() and find_library() are absolute paths. " "Pass these absolute library file paths directly to the " diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 6c78ac4..c35288c 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -325,6 +325,9 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout, if(!cmSystemTools::FileExists(source.c_str())) { cmSystemTools::ReplaceString(source, "$(IntDir)/", ""); + // Make sure the path exists for the file + std::string path = cmSystemTools::GetFilenamePath(source); + cmSystemTools::MakeDirectory(path.c_str()); #if defined(_WIN32) || defined(__CYGWIN__) std::ofstream sourceFout(source.c_str(), std::ios::binary | std::ios::out @@ -1697,25 +1700,21 @@ void cmLocalVisualStudio6Generator std::set<std::string> minsizeDefinesSet; std::set<std::string> debugrelDefinesSet; - - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); - this->AppendDefines( definesSet, - gt->GetCompileDefinitions()); + target.GetCompileDefinitions()); this->AppendDefines( debugDefinesSet, - gt->GetCompileDefinitions("DEBUG")); + target.GetCompileDefinitions("DEBUG")); this->AppendDefines( releaseDefinesSet, - gt->GetCompileDefinitions("RELEASE")); + target.GetCompileDefinitions("RELEASE")); this->AppendDefines( minsizeDefinesSet, - gt->GetCompileDefinitions("MINSIZEREL")); + target.GetCompileDefinitions("MINSIZEREL")); this->AppendDefines( debugrelDefinesSet, - gt->GetCompileDefinitions("RELWITHDEBINFO")); + target.GetCompileDefinitions("RELWITHDEBINFO")); std::string defines = " "; std::string debugDefines = " "; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 918b21e..f9df861 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -745,8 +745,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.ParseFinish(); cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(&target); - targetOptions.AddDefines(gt->GetCompileDefinitions().c_str()); - targetOptions.AddDefines(gt->GetCompileDefinitions(configName).c_str()); + targetOptions.AddDefines(target.GetCompileDefinitions().c_str()); + targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str()); targetOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index b45a61c..dbd0c36 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -99,6 +99,7 @@ cmMakefile::cmMakefile(): Internal(new Internals) this->AddDefaultDefinitions(); this->Initialize(); this->PreOrder = false; + this->GeneratingBuildSystem = false; } cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals) @@ -1616,20 +1617,31 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath, } //---------------------------------------------------------------------------- -void cmMakefile::AddIncludeDirectory(const char* inc, bool before) +void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs, + bool before) { - if (!inc) + if (incs.empty()) { return; } + std::string incString; + std::string sep; + + for(std::vector<std::string>::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + incString += sep + *li; + sep = ";"; + } + std::vector<IncludeDirectoriesEntry>::iterator position = - before ? this->IncludeDirectoriesEntries.begin() - : this->IncludeDirectoriesEntries.end(); + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(); cmListFileBacktrace lfbt; this->GetBacktrace(lfbt); - IncludeDirectoriesEntry entry(inc, lfbt); + IncludeDirectoriesEntry entry(incString, lfbt); this->IncludeDirectoriesEntries.insert(position, entry); // Property on each target: @@ -1642,9 +1654,14 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before) } //---------------------------------------------------------------------------- -void cmMakefile::AddSystemIncludeDirectory(const char* dir) +void +cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs) { - this->SystemIncludeDirectories.insert(dir); + for(std::set<cmStdString>::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + this->SystemIncludeDirectories.insert(*li); + } } //---------------------------------------------------------------------------- @@ -2243,7 +2260,7 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName) { return true; } - // If we are doing an in-source build, than the test will always fail + // If we are doing an in-source build, then the test will always fail if ( cmSystemTools::SameFile(this->GetHomeDirectory(), this->GetHomeOutputDirectory()) ) { @@ -2254,8 +2271,8 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName) return true; } - // Check if this is subdirectory of the source tree but not a - // subdirectory of a build tree + // Check if this is a subdirectory of the source tree but not a + // subdirectory of the build tree if ( cmSystemTools::IsSubDirectory(fileName, this->GetHomeDirectory()) && !cmSystemTools::IsSubDirectory(fileName, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index a85015f..a2783f2 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -287,7 +287,8 @@ public: /** * Add an include directory to the build. */ - void AddIncludeDirectory(const char*, bool before = false); + void AddIncludeDirectories(const std::vector<std::string> &incs, + bool before = false); /** * Add a variable definition to the build. This variable @@ -545,7 +546,7 @@ public: /** * Mark include directories as system directories. */ - void AddSystemIncludeDirectory(const char* dir); + void AddSystemIncludeDirectories(const std::set<cmStdString> &incs); bool IsSystemIncludeDirectory(const char* dir); /** Expand out any arguements in the vector that have ; separated @@ -869,6 +870,9 @@ public: return this->IncludeDirectoriesEntries; } + bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; } + void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; } + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -1018,6 +1022,9 @@ private: // Enforce rules about CMakeLists.txt files. void EnforceDirectoryLevelRules(); + + bool GeneratingBuildSystem; + }; //---------------------------------------------------------------------------- diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 64fcfce..d9aa7fe 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -303,10 +303,10 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l) // Add preprocessor definitions for this target and configuration. this->LocalGenerator->AppendDefines - (defines, this->GeneratorTarget->GetCompileDefinitions()); + (defines, this->Target->GetCompileDefinitions()); this->LocalGenerator->AppendDefines - (defines, this->GeneratorTarget->GetCompileDefinitions( + (defines, this->Target->GetCompileDefinitions( this->LocalGenerator->ConfigurationName.c_str())); std::string definesString; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 65967a5..7e48cd7 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -190,7 +190,7 @@ cmNinjaNormalTargetGenerator linkOptionVar += cmTarget::GetTargetTypeName(targetType); const std::string linkOption = GetMakefile()->GetSafeDefinition(linkOptionVar.c_str()); - rspcontent = "$in " + linkOption + " $LINK_PATH $LINK_LIBRARIES"; + rspcontent = "$in_newline "+linkOption+" $LINK_PATH $LINK_LIBRARIES"; vars.Objects = responseFlag.c_str(); vars.LinkLibraries = ""; } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0f484da..f8e4399 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -228,7 +228,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language) // Add preprocessor definitions for this target and configuration. this->LocalGenerator->AppendDefines (defines, - this->GeneratorTarget->GetCompileDefinitions()); + this->Target->GetCompileDefinitions()); this->LocalGenerator->AppendDefines (defines, source->GetProperty("COMPILE_DEFINITIONS")); @@ -237,7 +237,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language) defPropName += cmSystemTools::UpperCase(this->GetConfigName()); this->LocalGenerator->AppendDefines (defines, - this->GeneratorTarget->GetCompileDefinitions(this->GetConfigName())); + this->Target->GetCompileDefinitions(this->GetConfigName())); this->LocalGenerator->AppendDefines (defines, source->GetProperty(defPropName.c_str())); diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index eb7d666..831e92e 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -508,6 +508,27 @@ cmPolicies::cmPolicies() "for strict compatibility. " "The NEW behavior for this policy is to leave the values untouched.", 2,8,11,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0020, "CMP0020", + "Automatically link Qt executables to qtmain target on Windows.", + "CMake 2.8.10 and lower required users of Qt to always specify a link " + "dependency to the qtmain.lib static library manually on Windows. CMake " + "2.8.11 gained the ability to evaluate generator expressions while " + "determining the link dependencies from IMPORTED targets. This allows " + "CMake itself to automatically link executables which link to Qt to the " + "qtmain.lib library when using IMPORTED Qt targets. For applications " + "already linking to qtmain.lib, this should have little impact. For " + "applications which supply their own alternative WinMain implementation " + "and for applications which use the QAxServer library, this automatic " + "linking will need to be disabled as per the documentation." + "\n" + "The OLD behavior for this policy is not to link executables to " + "qtmain.lib automatically when they link to the QtCore IMPORTED" + "target. " + "The NEW behavior for this policy is to link executables to " + "qtmain.lib automatically when they link to QtCore IMPORTED target.", + 2,8,11,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index d7d945c..c11af07 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -69,6 +69,7 @@ public: /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C} /// instead. CMP0019, ///< No variable re-expansion in include and link info + CMP0020, ///< Automatically link Qt executables to qtmain target /** \brief Always the last entry. * diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index bf034cf..cc42175 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -229,7 +229,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) } const char* tmp = target->GetProperty("COMPILE_DEFINITIONS"); - std::string _moc_compile_defs = (tmp!=0 ? tmp : ""); + std::string _moc_compile_defs; + if (tmp) + { + _moc_compile_defs = target->GetCompileDefinitions(); + } tmp = makefile->GetProperty("COMPILE_DEFINITIONS"); if (tmp) { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c2521d9..525efb4 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1180,46 +1180,35 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source, bool cmSystemTools::RenameFile(const char* oldname, const char* newname) { #ifdef _WIN32 - /* On Windows the move functions will not replace existing files. - Check if the destination exists. */ - struct stat newFile; - if(stat(newname, &newFile) == 0) +# ifndef INVALID_FILE_ATTRIBUTES +# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +# endif + /* Windows MoveFileEx may not replace read-only or in-use files. If it + fails then remove the read-only attribute from any existing destination. + Try multiple times since we may be racing against another process + creating/opening the destination file just before our MoveFileEx. */ + int tries = 5; + while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries) { - /* The destination exists. We have to replace it carefully. The - MoveFileEx function does what we need but is not available on - Win9x. */ - OSVERSIONINFO osv; - DWORD attrs; - - /* Make sure the destination is not read only. */ - attrs = GetFileAttributes(newname); - if(attrs & FILE_ATTRIBUTE_READONLY) + // Try again only if failure was due to access permissions. + if(GetLastError() != ERROR_ACCESS_DENIED) { - SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY); + return false; } - - /* Check the windows version number. */ - osv.dwOSVersionInfoSize = sizeof(osv); - GetVersionEx(&osv); - if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + DWORD attrs = GetFileAttributes(newname); + if((attrs != INVALID_FILE_ATTRIBUTES) && + (attrs & FILE_ATTRIBUTE_READONLY)) { - /* This is Win9x. There is no MoveFileEx implementation. We - cannot quite rename the file atomically. Just delete the - destination and then move the file. */ - DeleteFile(newname); - return MoveFile(oldname, newname) != 0; + // Remove the read-only attribute from the destination file. + SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY); } else { - /* This is not Win9x. Use the MoveFileEx implementation. */ - return MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) != 0; + // The file may be temporarily in use so wait a bit. + cmSystemTools::Delay(100); } } - else - { - /* The destination does not exist. Just move the file. */ - return MoveFile(oldname, newname) != 0; - } + return tries > 0; #else /* On UNIX we have an OS-provided call to do this atomically. */ return rename(oldname, newname) == 0; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 815da40..ca0e24b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -134,6 +134,7 @@ public: : ge(cge) {} const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; + std::vector<std::string> CachedIncludes; }; std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries; }; @@ -145,12 +146,14 @@ cmTarget::cmTarget() this->PolicyStatusCMP0003 = cmPolicies::WARN; this->PolicyStatusCMP0004 = cmPolicies::WARN; this->PolicyStatusCMP0008 = cmPolicies::WARN; + this->PolicyStatusCMP0020 = cmPolicies::WARN; this->LinkLibrariesAnalyzed = false; this->HaveInstallRule = false; this->DLLPlatform = false; this->IsApple = false; this->IsImportedTarget = false; this->BuildInterfaceIncludesAppended = false; + this->DebugIncludesDone = false; } //---------------------------------------------------------------------------- @@ -906,6 +909,17 @@ void cmTarget::DefineProperties(cmake *cm) "property is not set, then it is ignored."); cm->DefineProperty + ("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET, + "Properties which must be string-compatible with their link interface", + "The COMPATIBLE_INTERFACE_STRING property may contain a list of " + "properties for this target which must be the same when evaluated as " + "a string 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 equal with each " + "other, and with the \"FOO\" property in this target. If the " + "property is not set, then it is ignored."); + + cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the " @@ -1499,6 +1513,8 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->Makefile->GetPolicyStatus(cmPolicies::CMP0004); this->PolicyStatusCMP0008 = this->Makefile->GetPolicyStatus(cmPolicies::CMP0008); + this->PolicyStatusCMP0020 = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0020); } //---------------------------------------------------------------------------- @@ -1520,6 +1536,13 @@ void cmTarget::ClearLinkMaps() this->Internal->LinkImplMap.clear(); this->Internal->LinkInterfaceMap.clear(); this->Internal->LinkClosureMap.clear(); + for (cmTargetLinkInformationMap::const_iterator it + = this->LinkInformation.begin(); + it != this->LinkInformation.end(); ++it) + { + delete it->second; + } + this->LinkInformation.clear(); } //---------------------------------------------------------------------------- @@ -2269,8 +2292,9 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, cmTarget *tgt = this->Makefile->FindTargetToUse(lib); const bool isNonImportedTarget = tgt && !tgt->IsImported(); - std::string libName = isNonImportedTarget ? targetNameGenex(lib) - : std::string(lib); + const std::string libName = (isNonImportedTarget && llt != GENERAL) + ? targetNameGenex(lib) + : std::string(lib); this->AppendProperty("LINK_LIBRARIES", this->GetDebugGeneratorExpressions(libName, llt).c_str()); @@ -2739,53 +2763,106 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) cmSystemTools::ExpandListArgument(debugProp, debugProperties); } - bool debugIncludes = std::find(debugProperties.begin(), + bool debugIncludes = !this->DebugIncludesDone + && std::find(debugProperties.begin(), debugProperties.end(), "INCLUDE_DIRECTORIES") != debugProperties.end(); + if (this->Makefile->IsGeneratingBuildSystem()) + { + this->DebugIncludesDone = true; + } + for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator it = this->Internal->IncludeDirectoriesEntries.begin(), end = this->Internal->IncludeDirectoriesEntries.end(); it != end; ++it) { - std::vector<std::string> entryIncludes; - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker), - entryIncludes); + + bool testIsOff = true; + bool cacheIncludes = false; + std::vector<std::string> entryIncludes = (*it)->CachedIncludes; + if(!entryIncludes.empty()) + { + testIsOff = false; + } + else + { + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker), + entryIncludes); + if (!(*it)->ge->GetHadContextSensitiveCondition()) + { + cacheIncludes = true; + } + } std::string usedIncludes; - for(std::vector<std::string>::const_iterator + for(std::vector<std::string>::iterator li = entryIncludes.begin(); li != entryIncludes.end(); ++li) { - std::string inc = *li; - if (!cmSystemTools::IsOff(inc.c_str())) + if (testIsOff && !cmSystemTools::IsOff(li->c_str())) { - cmSystemTools::ConvertToUnixSlashes(inc); + cmSystemTools::ConvertToUnixSlashes(*li); } + std::string inc = *li; if(uniqueIncludes.insert(inc).second) { - includes.push_back(*li); + includes.push_back(inc); if (debugIncludes) { - usedIncludes += " * " + *li + "\n"; + usedIncludes += " * " + inc + "\n"; } } } + if (cacheIncludes) + { + (*it)->CachedIncludes = entryIncludes; + } if (!usedIncludes.empty()) { this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, - "Used includes:\n" + usedIncludes, - (*it)->ge->GetBacktrace()); + "Used includes for target " + this->Name + ":\n" + + usedIncludes, (*it)->ge->GetBacktrace()); } } return includes; } //---------------------------------------------------------------------------- +std::string cmTarget::GetCompileDefinitions(const char *config) +{ + std::string defPropName = "COMPILE_DEFINITIONS"; + if (config) + { + defPropName += "_" + cmSystemTools::UpperCase(config); + } + + const char *prop = this->GetProperty(defPropName.c_str()); + + if (!prop) + { + return ""; + } + + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + defPropName, 0, 0); + return ge.Parse(prop)->Evaluate(this->Makefile, + config, + false, + this, + &dagChecker); +} + +//---------------------------------------------------------------------------- void cmTarget::MaybeInvalidatePropertyCache(const char* prop) { // Wipe out maps caching information affected by this property. @@ -4482,22 +4559,69 @@ void cmTarget::AddLinkDependentTargetsForProperties( } //---------------------------------------------------------------------------- -bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, - const char *config) +template<typename PropertyType> +PropertyType getTypedProperty(cmTarget *tgt, const char *prop, + PropertyType *); + +//---------------------------------------------------------------------------- +template<> +bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *) +{ + return tgt->GetPropertyAsBool(prop); +} + +//---------------------------------------------------------------------------- +template<> +const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop, + const char **) { - bool propContent = this->GetPropertyAsBool(p.c_str()); - const bool explicitlySet = this->GetProperties() + return tgt->GetProperty(prop); +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +bool consistentProperty(PropertyType lhs, PropertyType rhs); + +//---------------------------------------------------------------------------- +template<> +bool consistentProperty(bool lhs, bool rhs) +{ + return lhs == rhs; +} + +//---------------------------------------------------------------------------- +template<> +bool consistentProperty(const char *lhs, const char *rhs) +{ + if (!lhs && !rhs) + return true; + if (!lhs || !rhs) + return false; + return strcmp(lhs, rhs) == 0; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, + const std::string &p, + const char *config, + const char *defaultValue, + PropertyType *) +{ + PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(), + 0); + const bool explicitlySet = tgt->GetProperties() .find(p.c_str()) - != this->GetProperties().end(); + != tgt->GetProperties().end(); std::set<std::string> dependentTargets; - this->GetLinkDependentTargetsForProperty(p, + tgt->GetLinkDependentTargetsForProperty(p, dependentTargets); const bool impliedByUse = - this->IsNullImpliedByLinkLibraries(p); + tgt->IsNullImpliedByLinkLibraries(p); assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); - cmComputeLinkInformation *info = this->GetLinkInformation(config); + cmComputeLinkInformation *info = tgt->GetLinkInformation(config); const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); bool propInitialized = explicitlySet; @@ -4519,20 +4643,22 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, const bool ifaceIsSet = li->Target->GetProperties() .find("INTERFACE_" + p) != li->Target->GetProperties().end(); - const bool ifacePropContent = li->Target->GetPropertyAsBool( - ("INTERFACE_" + p).c_str()); + PropertyType ifacePropContent = + getTypedProperty<PropertyType>(li->Target, + ("INTERFACE_" + p).c_str(), 0); if (explicitlySet) { if (ifaceIsSet) { - if (propContent != ifacePropContent) + if (!consistentProperty(propContent, ifacePropContent)) { cmOStringStream e; e << "Property " << p << " on target \"" - << this->GetName() << "\" does\nnot match the " + << tgt->GetName() << "\" does\nnot match the " "INTERFACE_" << p << " property requirement\nof " "dependency \"" << li->Target->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); + break; } else { @@ -4550,15 +4676,16 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, { if (ifaceIsSet) { - if (propContent != ifacePropContent) + if (!consistentProperty(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 \"" + << tgt->GetName() << "\" is\nimplied to be " << defaultValue + << " because it was used to determine the link libraries\n" + "already. The INTERFACE_" << p << " property on\ndependency \"" << li->Target->GetName() << "\" is in conflict.\n"; cmSystemTools::Error(e.str().c_str()); + break; } else { @@ -4578,14 +4705,15 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, { if (propInitialized) { - if (propContent != ifacePropContent) + if (!consistentProperty(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"; + << tgt->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); + break; } else { @@ -4610,6 +4738,80 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, } //---------------------------------------------------------------------------- +bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config) +{ + return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE", + 0); +} + +//---------------------------------------------------------------------------- +const char * cmTarget::GetLinkInterfaceDependentStringProperty( + const std::string &p, + const char *config) +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", 0); +} + +//---------------------------------------------------------------------------- +bool isLinkDependentProperty(cmTarget *tgt, const std::string &p, + const char *interfaceProperty, + const char *config) +{ + cmComputeLinkInformation *info = tgt->GetLinkInformation(config); + + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + if (!li->Target) + { + continue; + } + const char *prop = li->Target->GetProperty(interfaceProperty); + if (!prop) + { + continue; + } + + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(prop, props); + + for(std::vector<std::string>::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + if (*pi == p) + { + return true; + } + } + } + + return false; +} + +//---------------------------------------------------------------------------- +bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config) +{ + return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL", + config); +} + +//---------------------------------------------------------------------------- +bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, + const char *config) +{ + return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING", + config); +} + +//---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set<cmStdString>& languages) const { for(std::vector<cmSourceFile*>::const_iterator @@ -5349,6 +5551,73 @@ std::string cmTarget::CheckCMP0004(std::string const& item) return lib; } +template<typename PropertyType> +PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt, + const std::string prop, + const char *config, + PropertyType *); + +template<> +bool getLinkInterfaceDependentProperty(cmTarget *tgt, + const std::string prop, + const char *config, bool *) +{ + return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); +} + +template<> +const char * getLinkInterfaceDependentProperty(cmTarget *tgt, + const std::string prop, + const char *config, + const char **) +{ + return tgt->GetLinkInterfaceDependentStringProperty(prop, config); +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee, + const char *propName, + std::set<cmStdString> &emitted, + const char *config, + PropertyType *) +{ + const char *prop = dependee->GetProperty(propName); + if (!prop) + { + return; + } + + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(prop, props); + + for(std::vector<std::string>::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + if (depender->GetMakefile()->GetCMakeInstance() + ->GetIsPropertyDefined(pi->c_str(), + cmProperty::TARGET)) + { + cmOStringStream e; + e << "Target \"" << dependee->GetName() << "\" has property \"" + << *pi << "\" listed in its " << propName << " property. " + "This is not allowed. Only user-defined properties may appear " + "listed in the " << propName << " property."; + depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if(emitted.insert(*pi).second) + { + getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, + 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + } +} + //---------------------------------------------------------------------------- void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, const char* config) @@ -5365,38 +5634,20 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, { continue; } - const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL"); - if (!prop) + + checkPropertyConsistency<bool>(this, li->Target, + "COMPATIBLE_INTERFACE_BOOL", + emitted, config, 0); + if (cmSystemTools::GetErrorOccuredFlag()) { - continue; + return; } - - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - - for(std::vector<std::string>::iterator pi = props.begin(); - pi != props.end(); ++pi) + checkPropertyConsistency<const char *>(this, li->Target, + "COMPATIBLE_INTERFACE_STRING", + emitted, config, 0); + if (cmSystemTools::GetErrorOccuredFlag()) { - 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; - } - } + return; } } } @@ -5422,14 +5673,14 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head) info = 0; } + // Store the information for this configuration. + cmTargetLinkInformationMap::value_type entry(key, info); + i = this->LinkInformation.insert(entry).first; + if (info) { this->CheckPropertyCompatibility(info, config); } - - // Store the information for this configuration. - 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 69a00c1..7577a59 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -102,6 +102,10 @@ public: cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const { return this->PolicyStatusCMP0008; } + /** Get the status of policy CMP0020 when the target was created. */ + cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const + { return this->PolicyStatusCMP0020; } + /** * Get the list of the custom commands for this target */ @@ -426,6 +430,8 @@ public: If no macro should be defined null is returned. */ const char* GetExportMacro(); + std::string GetCompileDefinitions(const char *config = 0); + // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change // when source file properties are changed and we do not have enough @@ -495,12 +501,22 @@ public: void GetLinkDependentTargetsForProperty(const std::string &p, std::set<std::string> &targets); bool IsNullImpliedByLinkLibraries(const std::string &p); + bool IsLinkInterfaceDependentBoolProperty(const std::string &p, + const char *config); + bool IsLinkInterfaceDependentStringProperty(const std::string &p, + const char *config); void AddLinkDependentTargetsForProperties( const std::map<cmStdString, cmStdString> &map); bool GetLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); + + const char *GetLinkInterfaceDependentStringProperty(const std::string &p, + const char *config); + + std::string GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -610,6 +626,7 @@ private: bool DLLPlatform; bool IsApple; bool IsImportedTarget; + bool DebugIncludesDone; mutable std::map<cmStdString, std::set<std::string> > LinkDependentProperties; mutable std::set<std::string> LinkImplicitNullProperties; @@ -645,9 +662,6 @@ 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; @@ -656,6 +670,7 @@ private: cmPolicies::PolicyStatus PolicyStatusCMP0003; cmPolicies::PolicyStatus PolicyStatusCMP0004; cmPolicies::PolicyStatus PolicyStatusCMP0008; + cmPolicies::PolicyStatus PolicyStatusCMP0020; // Internal representation details. friend class cmTargetInternals; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index 492a1b7..7645833 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -20,13 +20,11 @@ bool cmTargetCompileDefinitionsCommand } void cmTargetCompileDefinitionsCommand -::HandleImportedTargetInvalidScope(const std::string &scope, - const std::string &tgt) +::HandleImportedTarget(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."; + e << "Cannot specify compile definitions for imported target \"" + << tgt << "\"."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } @@ -39,19 +37,32 @@ void cmTargetCompileDefinitionsCommand 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 &) +//---------------------------------------------------------------------------- +std::string cmTargetCompileDefinitionsCommand +::Join(const std::vector<std::string> &content) { - content += sep + entry; - return true; + std::string defs; + std::string sep; + for(std::vector<std::string>::const_iterator it = content.begin(); + it != content.end(); ++it) + { + if (strncmp(it->c_str(), "-D", 2) == 0) + { + defs += sep + it->substr(2); + } + else + { + defs += sep + *it; + } + sep = ";"; + } + return defs; } +//---------------------------------------------------------------------------- void cmTargetCompileDefinitionsCommand -::HandleDirectContent(cmTarget *tgt, const std::string &content, +::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, bool) { - tgt->AppendProperty("COMPILE_DEFINITIONS", content.c_str()); + tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); } diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index 4b066b7a..c93cacb 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -59,7 +59,7 @@ public: "Specify compile definitions or targets to use when compiling a given " "target. " "The named <target> must have been created by a command such as " - "add_executable or add_library. " + "add_executable or add_library and must not be an IMPORTED target. " "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 <target>. PUBLIC and " @@ -75,20 +75,16 @@ public: ; } - cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand); + cmTypeMacro(cmTargetCompileDefinitionsCommand, cmTargetPropCommandBase); private: - virtual void HandleImportedTargetInvalidScope(const std::string &scope, - const std::string &tgt); + virtual void HandleImportedTarget(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, + virtual void HandleDirectContent(cmTarget *tgt, + const std::vector<std::string> &content, bool prepend); + virtual std::string Join(const std::vector<std::string> &content); }; #endif diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 18e2cba..eaacfa9 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -22,13 +22,11 @@ bool cmTargetIncludeDirectoriesCommand //---------------------------------------------------------------------------- void cmTargetIncludeDirectoriesCommand -::HandleImportedTargetInvalidScope(const std::string &tgt, - const std::string &scope) +::HandleImportedTarget(const std::string &tgt) { 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."; + e << "Cannot specify include directories for imported target \"" + << tgt << "\"."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } @@ -43,32 +41,44 @@ void cmTargetIncludeDirectoriesCommand } //---------------------------------------------------------------------------- -bool cmTargetIncludeDirectoriesCommand -::HandleNonTargetArg(std::string &content, - const std::string &sep, - const std::string &entry, - const std::string &tgt) +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); +} + +//---------------------------------------------------------------------------- +std::string cmTargetIncludeDirectoriesCommand +::Join(const std::vector<std::string> &content) { - if (!cmSystemTools::FileIsFullPath(entry.c_str())) + std::string dirs; + std::string sep; + std::string prefix = this->Makefile->GetStartDirectory() + std::string("/"); + for(std::vector<std::string>::const_iterator it = content.begin(); + it != content.end(); ++it) { - 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; + if (cmSystemTools::FileIsFullPath(it->c_str()) + || isGeneratorExpression(*it)) + { + dirs += sep + *it; + } + else + { + dirs += sep + prefix + *it; + } + sep = ";"; } - - content += sep + entry; - return true; + return dirs; } //---------------------------------------------------------------------------- void cmTargetIncludeDirectoriesCommand -::HandleDirectContent(cmTarget *tgt, const std::string &content, +::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, bool prepend) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); - cmMakefileIncludeDirectoriesEntry entry(content, lfbt); + cmMakefileIncludeDirectoriesEntry entry(this->Join(content), lfbt); tgt->InsertInclude(entry, prepend); } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index 90e039c..2bc7bef 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -60,7 +60,7 @@ public: "Specify include directories or targets to use when compiling a given " "target. " "The named <target> must have been created by a command such as " - "add_executable or add_library.\n" + "add_executable or add_library and must not be an IMPORTED target.\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 " @@ -79,20 +79,16 @@ public: ; } - cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand); + cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmTargetPropCommandBase); private: - virtual void HandleImportedTargetInvalidScope(const std::string &tgt, - const std::string &scope); + virtual void HandleImportedTarget(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, + virtual void HandleDirectContent(cmTarget *tgt, + const std::vector<std::string> &content, bool prepend); + virtual std::string Join(const std::vector<std::string> &content); }; #endif diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 0705fb4..cb913f5 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -35,10 +35,6 @@ bool cmTargetLinkLibrariesCommand ->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 cmOStringStream e; e << "Cannot specify link libraries for target \"" << args[0] << "\" " @@ -254,23 +250,54 @@ cmTargetLinkLibrariesCommand } //---------------------------------------------------------------------------- +static std::string compileProperty(cmTarget *tgt, const std::string &lib, + bool isGenex, + const std::string &property, + cmTarget::LinkLibraryType llt) +{ + std::string value = !isGenex ? "$<LINKED:" + lib + ">" + : "$<$<TARGET_DEFINED:" + lib + ">:" + + "$<TARGET_PROPERTY:" + lib + + ",INTERFACE_" + property + ">" + ">"; + + return tgt->GetDebugGeneratorExpressions(value, llt); +} + +//---------------------------------------------------------------------------- +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 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt) { + const bool isGenex = isGeneratorExpression(lib); + + cmsys::RegularExpression targetNameValidator; + targetNameValidator.compile("^[A-Za-z0-9_.:-]+$"); + const bool potentialTargetName = targetNameValidator.find(lib); + + if (potentialTargetName || isGenex) + { + this->Target->AppendProperty("INCLUDE_DIRECTORIES", + compileProperty(this->Target, lib, + isGenex, + "INCLUDE_DIRECTORIES", llt).c_str()); + this->Target->AppendProperty("COMPILE_DEFINITIONS", + compileProperty(this->Target, lib, + isGenex, + "COMPILE_DEFINITIONS", llt).c_str()); + } + // 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) @@ -280,6 +307,18 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, } } + if (potentialTargetName || isGenex) + { + this->Target->AppendProperty("INTERFACE_COMPILE_DEFINITIONS", + compileProperty(this->Target, lib, + isGenex, + "COMPILE_DEFINITIONS", llt).c_str()); + this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", + compileProperty(this->Target, lib, + isGenex, + "INCLUDE_DIRECTORIES", llt).c_str()); + } + // Get the list of configurations considered to be DEBUG. std::vector<std::string> const& debugConfigs = this->Makefile->GetCMakeInstance()->GetDebugConfigs(); diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 34fe54c..aaabdfa 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -93,7 +93,18 @@ public: "linked to this target will appear on the link line for the other " "target too. " "See the LINK_INTERFACE_LIBRARIES target property to override the " - "set of transitive link dependencies for a target." + "set of transitive link dependencies for a target. " + "Calls to other signatures of this command may set the property " + "making any libraries linked exclusively by this signature private." + "\n" + "Target usage requirements are also consumed by this command. If the " + "<target> is linked to another target which has " + "a populated INTERFACE_INCLUDE_DIRECTORIES, the content of it is " + "appended to the INCLUDE_DIRECTORIES of <target>. Similarly, the " + "INTERFACE_COMPILE_DEFINITONS of a dependee are added to the " + "COMPILE_DEFINITONS of <target>, and the " + "INTERFACE_POSITION_INDEPENDENT_CODE property is used to determine the " + "POSITION_INDEPENDENT_CODE property of <target>." "\n" " target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n" " [[debug|optimized|general] <lib>] ...)\n" diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 69aaf17..18a1d2a 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -80,17 +80,16 @@ bool cmTargetPropCommandBase return false; } - if(this->Target->IsImported() && scope != "INTERFACE") + if(this->Target->IsImported()) { - this->HandleImportedTargetInvalidScope(args[0], scope); + this->HandleImportedTarget(args[0]); return false; } ++argIndex; - std::string content; + std::vector<std::string> content; - std::string sep; for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex) { if(args[i] == "PUBLIC" @@ -100,16 +99,7 @@ bool cmTargetPropCommandBase this->PopulateTargetProperies(scope, content, prepend); return true; } - if (this->Makefile->FindTargetToUse(args[i].c_str())) - { - content += sep + "$<TARGET_PROPERTY:" + args[i] - + ",INTERFACE_" + this->Property + ">"; - } - else if (!this->HandleNonTargetArg(content, sep, args[i], args[0])) - { - return false; - } - sep = ";"; + content.push_back(args[i]); } this->PopulateTargetProperies(scope, content, prepend); return true; @@ -118,7 +108,8 @@ bool cmTargetPropCommandBase //---------------------------------------------------------------------------- void cmTargetPropCommandBase ::PopulateTargetProperies(const std::string &scope, - const std::string &content, bool prepend) + const std::vector<std::string> &content, + bool prepend) { if (scope == "PRIVATE" || scope == "PUBLIC") { @@ -130,7 +121,7 @@ void cmTargetPropCommandBase { const std::string propName = std::string("INTERFACE_") + this->Property; const char *propValue = this->Target->GetProperty(propName.c_str()); - const std::string totalContent = content + (propValue + const std::string totalContent = this->Join(content) + (propValue ? std::string(";") + propValue : std::string()); this->Target->SetProperty(propName.c_str(), totalContent.c_str()); @@ -138,7 +129,7 @@ void cmTargetPropCommandBase else { this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(), - content.c_str()); + this->Join(content).c_str()); } } } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index e757f9d..8047a48 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -31,28 +31,25 @@ public: bool HandleArguments(std::vector<std::string> const& args, const char *prop, ArgumentFlags flags = NO_FLAGS); + cmTypeMacro(cmTargetPropCommandBase, cmCommand); +protected: + std::string Property; + cmTarget *Target; + private: - virtual void HandleImportedTargetInvalidScope(const std::string &tgt, - const std::string &scope) = 0; + virtual void HandleImportedTarget(const std::string &tgt) = 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, + const std::vector<std::string> &content, bool prepend) = 0; + virtual std::string Join(const std::vector<std::string> &content) = 0; bool ProcessContentArgs(std::vector<std::string> 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; + const std::vector<std::string> &content, + bool prepend); }; #endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2596d73..171ed9a 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1221,8 +1221,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); clOptions.AddDefines( - this->GeneratorTarget->GetCompileDefinitions().c_str()); - clOptions.AddDefines(this->GeneratorTarget->GetCompileDefinitions( + this->Target->GetCompileDefinitions().c_str()); + clOptions.AddDefines(this->Target->GetCompileDefinitions( configName.c_str()).c_str()); clOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 18622f3..d57e981 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -4449,6 +4449,10 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, isError = true; msg << "CMake Internal Error (please report a bug)"; } + else if(t == cmake::LOG) + { + msg << "CMake Debug Log"; + } else { msg << "CMake Warning"; diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index c4ee095..fd83752 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -428,6 +428,58 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #endif +#ifdef __MINT__ +#define DYNAMICLOADER_DEFINED 1 +#define _GNU_SOURCE /* for program_invocation_name */ +#include <string.h> +#include <malloc.h> +#include <errno.h> +#include <dld.h> + +namespace KWSYS_NAMESPACE +{ + +//---------------------------------------------------------------------------- +DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname ) +{ + char *name = (char *)calloc(1, strlen(libname) + 1); + dld_init(program_invocation_name); + strncpy(name, libname, strlen(libname)); + dld_link(libname); + return (void *)name; +} + +//---------------------------------------------------------------------------- +int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) +{ + dld_unlink_by_file((char *)lib, 0); + free(lib); + return 0; +} + +//---------------------------------------------------------------------------- +DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( + DynamicLoader::LibraryHandle lib, const char* sym) +{ + // Hack to cast pointer-to-data to pointer-to-function. + union + { + void* pvoid; + DynamicLoader::SymbolPointer psym; + } result; + result.pvoid = dld_get_symbol(sym); + return result.psym; +} + +//---------------------------------------------------------------------------- +const char* DynamicLoader::LastError() +{ + return dld_strerror(dld_errno); +} + +} // namespace KWSYS_NAMESPACE +#endif + // --------------------------------------------------------------- // 6. Implementation for default UNIX machines. // if nothing has been defined then use this diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx index 513eb64..46a7e4f 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -399,7 +399,7 @@ bool Glob::FindFiles(const kwsys_stl::string& inexpr) if ( last_slash > 0 ) { //kwsys_ios::cout << "I can skip: " << fexpr.substr(0, last_slash) - //<< kwsys_ios::endl; + // << kwsys_ios::endl; skip = last_slash; } if ( skip == 0 ) diff --git a/Source/kwsys/IOStream.cxx b/Source/kwsys/IOStream.cxx index 57b696e..a31f8c8 100644 --- a/Source/kwsys/IOStream.cxx +++ b/Source/kwsys/IOStream.cxx @@ -272,6 +272,7 @@ namespace KWSYS_NAMESPACE // Create one public symbol in this object file to avoid warnings from // archivers. +void IOStreamSymbolToAvoidWarning(); void IOStreamSymbolToAvoidWarning() { } diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 2db1254..fc9e8bf 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -102,7 +102,7 @@ static inline void kwsysProcess_usleep(unsigned int msec) * pipes' file handles to be non-blocking and just poll them directly * without select(). */ -#if !defined(__BEOS__) && !defined(__VMS) +#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) # define KWSYSPE_USE_SELECT 1 #endif diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index b20d724..f057e0f 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -2466,7 +2466,9 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement() #endif } -void SystemInformationStripLeadingSpace(kwsys_stl::string& str) +#if USE_CPUID +// Used only in USE_CPUID implementation below. +static void SystemInformationStripLeadingSpace(kwsys_stl::string& str) { // Because some manufacturers have leading white space - we have to post-process the name. kwsys_stl::string::size_type pos = str.find_first_not_of(" "); @@ -2475,6 +2477,7 @@ void SystemInformationStripLeadingSpace(kwsys_stl::string& str) str = str.substr(pos); } } +#endif /** */ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity() diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index b75993e..881c49a 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -3037,7 +3037,7 @@ void SystemTools::CheckTranslationPath(kwsys_stl::string & path) path.erase(path.end()-1, path.end()); } -void +static void SystemToolsAppendComponents( kwsys_stl::vector<kwsys_stl::string>& out_components, kwsys_stl::vector<kwsys_stl::string>::const_iterator first, @@ -4704,7 +4704,7 @@ bool SystemTools::ParseURL( const kwsys_stl::string& URL, // ---------------------------------------------------------------------- // These must NOT be initialized. Default initialization to zero is // necessary. -unsigned int SystemToolsManagerCount; +static unsigned int SystemToolsManagerCount; SystemToolsTranslationMap *SystemTools::TranslationMap; SystemToolsTranslationMap *SystemTools::LongPathMap; #ifdef __CYGWIN__ diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx index e75a87e..72e6544 100644 --- a/Source/kwsys/testCommandLineArguments.cxx +++ b/Source/kwsys/testCommandLineArguments.cxx @@ -24,9 +24,9 @@ #include <stddef.h> /* size_t */ #include <string.h> /* strcmp */ -void* random_ptr = reinterpret_cast<void*>(0x123); +static void* random_ptr = reinterpret_cast<void*>(0x123); -int argument(const char* arg, const char* value, void* call_data) +static int argument(const char* arg, const char* value, void* call_data) { kwsys_ios::cout << "Got argument: \"" << arg << "\" value: \"" << (value?value:"(null)") << "\"" << kwsys_ios::endl; if ( call_data != random_ptr ) @@ -37,7 +37,7 @@ int argument(const char* arg, const char* value, void* call_data) return 1; } -int unknown_argument(const char* argument, void* call_data) +static int unknown_argument(const char* argument, void* call_data) { kwsys_ios::cout << "Got unknown argument: \"" << argument << "\"" << kwsys_ios::endl; if ( call_data != random_ptr ) @@ -48,12 +48,12 @@ int unknown_argument(const char* argument, void* call_data) return 1; } -bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; } -bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; } -bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; } -bool CompareTwoItemsOnList(const char* i1, +static bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; } +static bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; } +static bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; } +static bool CompareTwoItemsOnList(const char* i1, const char* i2) { return strcmp(i1, i2) == 0; } -bool CompareTwoItemsOnList(const kwsys_stl::string& i1, +static bool CompareTwoItemsOnList(const kwsys_stl::string& i1, const kwsys_stl::string& i2) { return i1 == i2; } int testCommandLineArguments(int argc, char* argv[]) diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx index cbfb65b..61c1572 100644 --- a/Source/kwsys/testDynamicLoader.cxx +++ b/Source/kwsys/testDynamicLoader.cxx @@ -35,7 +35,7 @@ // left on disk. #include <testSystemTools.h> -kwsys_stl::string GetLibName(const char* lname) +static kwsys_stl::string GetLibName(const char* lname) { // Construct proper name of lib kwsys_stl::string slname; diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index 269b84b..6d5eb71 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -47,7 +47,7 @@ int runChild(const char* cmd[], int state, int exception, int value, int share, int output, int delay, double timeout, int poll, int repeat, int disown); -int test1(int argc, const char* argv[]) +static int test1(int argc, const char* argv[]) { (void)argc; (void)argv; fprintf(stdout, "Output on stdout from test returning 0.\n"); @@ -55,7 +55,7 @@ int test1(int argc, const char* argv[]) return 0; } -int test2(int argc, const char* argv[]) +static int test2(int argc, const char* argv[]) { (void)argc; (void)argv; fprintf(stdout, "Output on stdout from test returning 123.\n"); @@ -63,7 +63,7 @@ int test2(int argc, const char* argv[]) return 123; } -int test3(int argc, const char* argv[]) +static int test3(int argc, const char* argv[]) { (void)argc; (void)argv; fprintf(stdout, "Output before sleep on stdout from timeout test.\n"); @@ -80,7 +80,7 @@ int test3(int argc, const char* argv[]) return 0; } -int test4(int argc, const char* argv[]) +static 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 @@ -109,7 +109,7 @@ int test4(int argc, const char* argv[]) return 0; } -int test5(int argc, const char* argv[]) +static int test5(int argc, const char* argv[]) { int r; const char* cmd[4]; @@ -132,7 +132,7 @@ int test5(int argc, const char* argv[]) } #define TEST6_SIZE (4096*2) -void test6(int argc, const char* argv[]) +static void test6(int argc, const char* argv[]) { int i; char runaway[TEST6_SIZE+1]; @@ -156,7 +156,7 @@ void test6(int argc, const char* argv[]) delaying 1/10th of a second should ever have to poll. */ #define MINPOLL 5 #define MAXPOLL 20 -int test7(int argc, const char* argv[]) +static int test7(int argc, const char* argv[]) { (void)argc; (void)argv; fprintf(stdout, "Output on stdout before sleep.\n"); @@ -176,7 +176,7 @@ int test7(int argc, const char* argv[]) return 0; } -int test8(int argc, const char* argv[]) +static int test8(int argc, const char* argv[]) { /* Create a disowned grandchild to test handling of processes that exit before their children. */ @@ -200,7 +200,7 @@ int test8(int argc, const char* argv[]) return r; } -int test8_grandchild(int argc, const char* argv[]) +static int test8_grandchild(int argc, const char* argv[]) { (void)argc; (void)argv; fprintf(stdout, "Output on stdout from grandchild before sleep.\n"); @@ -221,7 +221,7 @@ int test8_grandchild(int argc, const char* argv[]) return 0; } -int runChild2(kwsysProcess* kp, +static int runChild2(kwsysProcess* kp, const char* cmd[], int state, int exception, int value, int share, int output, int delay, double timeout, int poll, int disown) @@ -505,7 +505,7 @@ int main(int argc, const char* argv[]) fprintf(stderr, "Output on stderr after test %d.\n", n); fflush(stdout); fflush(stderr); -#if _WIN32 +#if defined(_WIN32) if(argv0) { free(argv0); } #endif return r; diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 3ac0cb3..1690fd5 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -32,7 +32,7 @@ #include <string.h> /* strcmp */ //---------------------------------------------------------------------------- -const char* toUnixPaths[][2] = +static const char* toUnixPaths[][2] = { { "/usr/local/bin/passwd", "/usr/local/bin/passwd" }, { "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" }, @@ -52,8 +52,8 @@ const char* toUnixPaths[][2] = {0, 0} }; -bool CheckConvertToUnixSlashes(kwsys_stl::string input, - kwsys_stl::string output) +static bool CheckConvertToUnixSlashes(kwsys_stl::string input, + kwsys_stl::string output) { kwsys_stl::string result = input; kwsys::SystemTools::ConvertToUnixSlashes(result); @@ -69,17 +69,17 @@ bool CheckConvertToUnixSlashes(kwsys_stl::string input, } //---------------------------------------------------------------------------- -const char* checkEscapeChars[][4] = +static const char* checkEscapeChars[][4] = { { "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2"}, { " {} ", "{}", "#", " #{#} "}, {0, 0, 0, 0} }; -bool CheckEscapeChars(kwsys_stl::string input, - const char *chars_to_escape, - char escape_char, - kwsys_stl::string output) +static bool CheckEscapeChars(kwsys_stl::string input, + const char *chars_to_escape, + char escape_char, + kwsys_stl::string output) { kwsys_stl::string result = kwsys::SystemTools::EscapeChars( input.c_str(), chars_to_escape, escape_char); @@ -95,7 +95,7 @@ bool CheckEscapeChars(kwsys_stl::string input, } //---------------------------------------------------------------------------- -bool CheckFileOperations() +static bool CheckFileOperations() { bool res = true; @@ -129,7 +129,7 @@ bool CheckFileOperations() } //---------------------------------------------------------------------------- -bool CheckStringOperations() +static bool CheckStringOperations() { bool res = true; @@ -329,7 +329,7 @@ bool CheckStringOperations() //---------------------------------------------------------------------------- -bool CheckPutEnv(const char* env, const char* name, const char* value) +static bool CheckPutEnv(const char* env, const char* name, const char* value) { if(!kwsys::SystemTools::PutEnv(env)) { @@ -348,7 +348,7 @@ bool CheckPutEnv(const char* env, const char* name, const char* value) return true; } -bool CheckUnPutEnv(const char* env, const char* name) +static bool CheckUnPutEnv(const char* env, const char* name) { if(!kwsys::SystemTools::UnPutEnv(env)) { @@ -365,7 +365,7 @@ bool CheckUnPutEnv(const char* env, const char* name) return true; } -bool CheckEnvironmentOperations() +static bool CheckEnvironmentOperations() { bool res = true; res &= CheckPutEnv("A=B", "A", "B"); |