diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2008-04-20 20:44:59 -0400 |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2008-04-20 20:44:59 -0400 |
commit | b855e7defc42a210e7908c2abc54535de9265acc (patch) | |
tree | 35c38fbdcd4f2b9346949f401ea9ddc716ca0abc | |
parent | 0d98aada943e23dbf3165fc97d71be3b57310e55 (diff) | |
download | cmake-b855e7defc42a210e7908c2abc54535de9265acc.tar.gz |
ENH: merge in from main tree
31 files changed, 974 insertions, 114 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2298ff210a..6badd627ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,7 +354,7 @@ ENDMACRO (CMAKE_BUILD_UTILITIES) SET(CMake_VERSION_MAJOR 2) SET(CMake_VERSION_MINOR 6) SET(CMake_VERSION_PATCH 0) -SET(CMake_VERSION_RC 8) +SET(CMake_VERSION_RC 81) # CVS versions are odd, if this is an odd minor version # then set the CMake_VERSION_DATE variable IF("${CMake_VERSION_MINOR}" MATCHES "[13579]$") diff --git a/ChangeLog.manual b/ChangeLog.manual index 37b4ff1456..2a640bfe5c 100644 --- a/ChangeLog.manual +++ b/ChangeLog.manual @@ -1,3 +1,18 @@ +Changes in CMake 2.6.0 RC 9 + +- Better message in compiler ABI detect +- Fixes for cpack x11 packages on leopard +- Changes to cpack options names +- Fixes for FindMPI on 64 bit MS MPI +- Fix for -isystem for wxWidgets +- Some fixes to chrpath during installation +- Fix compatibility with CMake 2.4 for installation of MACOSX_BUNDLE (CMP0006) +- Do not use debug postfix when building frameworks on the Mac +- Fix exception handling off/on issue with visual studio IDE generators +- Fix <OBJECT_DIR> to be native path style +- Fix leak in cpack +- Some Qt GUI style changes + Changes in CMake 2.6.0 RC 8 - Fix sun make very poor performance diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 0571dc664f..3fd06a9577 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -5,7 +5,7 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src) IF(NOT DEFINED CMAKE_DETERMINE_${lang}_ABI_COMPILED) - MESSAGE(STATUS "Detecting ${lang} compiler info") + MESSAGE(STATUS "Detecting ${lang} compiler ABI info") # Compile the ABI identification source. SET(BIN "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeDetermineCompilerABI_${lang}.bin") @@ -17,9 +17,9 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src) # Load the resulting information strings. IF(CMAKE_DETERMINE_${lang}_ABI_COMPILED) - MESSAGE(STATUS "Detecting ${lang} compiler info - done") + MESSAGE(STATUS "Detecting ${lang} compiler ABI info - done") FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Detecting ${lang} compiler info compiled with the following output:\n${OUTPUT}\n\n") + "Detecting ${lang} compiler ABI info compiled with the following output:\n${OUTPUT}\n\n") FILE(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 2 REGEX "INFO:[^[]*\\[") FOREACH(info ${ABI_STRINGS}) IF("${info}" MATCHES ".*INFO:sizeof_dptr\\[0*([^]]*)\\].*") @@ -41,9 +41,9 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src) ENDIF(ABI_NAME) ELSE(CMAKE_DETERMINE_${lang}_ABI_COMPILED) - MESSAGE(STATUS "Detecting ${lang} compiler info - failed") + MESSAGE(STATUS "Detecting ${lang} compiler ABI info - failed") FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Detecting ${lang} compiler info failed to compile with the following output:\n${OUTPUT}\n\n") + "Detecting ${lang} compiler ABI info failed to compile with the following output:\n${OUTPUT}\n\n") ENDIF(CMAKE_DETERMINE_${lang}_ABI_COMPILED) ENDIF(NOT DEFINED CMAKE_DETERMINE_${lang}_ABI_COMPILED) ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ABI) diff --git a/Modules/CPack.RuntimeScript.in b/Modules/CPack.RuntimeScript.in index 1ce43bc777..fc3444abfd 100755 --- a/Modules/CPack.RuntimeScript.in +++ b/Modules/CPack.RuntimeScript.in @@ -5,6 +5,26 @@ CWD="`dirname \"$0\"`" TMP=/tmp/$UID/TemporaryItems +version=`sw_vers -productVersion` +if [ "$?" == "0" ]; then + major=${version%%\.*} + rest=${version#*\.} + minor=${rest%%\.*} + build=${rest#*\.} +else + major=10 + minor=4 + build=0 +fi + +echo $version +echo "Major = $major" +echo "Minor = $minor" +echo "Build = $build" + + +# if 10.5 or greater, then all the open-x11 stuff need not occur +if ((( $major < 10 )) || ((( $major == 10)) && (( $minor < 5 )))); then ps -wx -ocommand | grep -e '[X]11.app' > /dev/null if [ "$?" != "0" -a ! -f ~/.xinitrc ]; then echo "rm -f ~/.xinitrc" > ~/.xinitrc @@ -42,4 +62,5 @@ echo "$@" > /tmp/arguments.log if echo $1 | grep -- "^-psn_"; then shift fi +fi exec "$CWD/bin/@CPACK_EXECUTABLE_NAME@" "$@" > /tmp/slicer.output 2>&1 diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 15f46fbba4..59e409fb11 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -111,37 +111,37 @@ endmacro(cpack_optional_append _list _cond _item) if(NOT CPACK_GENERATOR) if(UNIX) if(CYGWIN) - option(CPACK_CYGWIN_BINARY "Enable to build Cygwin binary packages" ON) + option(CPACK_BINARY_CYGWIN "Enable to build Cygwin binary packages" ON) else(CYGWIN) if(APPLE) - option(CPACK_PACKAGEMAKER "Enable to build PackageMaker packages" ON) - option(CPACK_OSXX11 "Enable to build OSX X11 packages" OFF) + option(CPACK_BINARY_PACKAGEMAKER "Enable to build PackageMaker packages" ON) + option(CPACK_BINARY_OSXX11 "Enable to build OSX X11 packages" OFF) else(APPLE) - option(CPACK_TZ "Enable to build TZ packages" ON) + option(CPACK_BINARY_TZ "Enable to build TZ packages" ON) endif(APPLE) - option(CPACK_STGZ "Enable to build STGZ packages" ON) - option(CPACK_TGZ "Enable to build TGZ packages" ON) - option(CPACK_TBZ2 "Enable to build TBZ2 packages" ON) - option(CPACK_DEB "Enable to build Debian packages" OFF) - option(CPACK_RPM "Enable to build RPM packages" OFF) - option(CPACK_NSIS "Enable to build NSIS packages" OFF) + option(CPACK_BINARY_STGZ "Enable to build STGZ packages" ON) + option(CPACK_BINARY_TGZ "Enable to build TGZ packages" ON) + option(CPACK_BINARY_TBZ2 "Enable to build TBZ2 packages" ON) + option(CPACK_BINARY_DEB "Enable to build Debian packages" OFF) + option(CPACK_BINARY_RPM "Enable to build RPM packages" OFF) + option(CPACK_BINARY_NSIS "Enable to build NSIS packages" OFF) endif(CYGWIN) else(UNIX) - option(CPACK_NSIS "Enable to build NSIS packages" ON) - option(CPACK_ZIP "Enable to build ZIP packages" ON) + option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON) + option(CPACK_BINARY_ZIP "Enable to build ZIP packages" ON) endif(UNIX) - cpack_optional_append(CPACK_GENERATOR CPACK_PACKAGEMAKER PackageMaker) - cpack_optional_append(CPACK_GENERATOR CPACK_OSXX11 OSXX11) - cpack_optional_append(CPACK_GENERATOR CPACK_CYGWIN_BINARY CygwinBinary) - cpack_optional_append(CPACK_GENERATOR CPACK_DEB DEB) - cpack_optional_append(CPACK_GENERATOR CPACK_RPM RPM) - cpack_optional_append(CPACK_GENERATOR CPACK_NSIS NSIS) - cpack_optional_append(CPACK_GENERATOR CPACK_STGZ STGZ) - cpack_optional_append(CPACK_GENERATOR CPACK_TGZ TGZ) - cpack_optional_append(CPACK_GENERATOR CPACK_TBZ2 TBZ2) - cpack_optional_append(CPACK_GENERATOR CPACK_TZ TZ) - cpack_optional_append(CPACK_GENERATOR CPACK_ZIP ZIP) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PACKAGEMAKER PackageMaker) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_OSXX11 OSXX11) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_CYGWIN CygwinBinary) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_DEB DEB) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_RPM RPM) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NSIS NSIS) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_STGZ STGZ) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TGZ TGZ) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TBZ2 TBZ2) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_TZ TZ) + cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_ZIP ZIP) endif(NOT CPACK_GENERATOR) @@ -168,9 +168,10 @@ if(NOT CPACK_SOURCE_GENERATOR) endif(NOT CPACK_SOURCE_GENERATOR) # mark the above options as advanced -mark_as_advanced(CPACK_CYGWIN_BINARY CPACK_PACKAGEMAKER CPACK_OSXX11 - CPACK_STGZ CPACK_TGZ CPACK_TBZ2 CPACK_DEB CPACK_RPM - CPACK_TZ CPACK_NSIS CPACK_ZIP +mark_as_advanced(CPACK_BINARY_CYGWIN CPACK_BINARY_PACKAGEMAKER CPACK_BINARY_OSXX11 + CPACK_BINARY_STGZ CPACK_BINARY_TGZ CPACK_BINARY_TBZ2 + CPACK_BINARY_DEB CPACK_BINARY_RPM CPACK_BINARY_TZ + CPACK_BINARY_NSIS CPACK_BINARY_ZIP CPACK_SOURCE_CYGWIN CPACK_SOURCE_TBZ2 CPACK_SOURCE_TGZ CPACK_SOURCE_TZ CPACK_SOURCE_ZIP) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 5e218e7074..0923c00b82 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -216,13 +216,19 @@ else (MPI_COMPILE_CMDLINE) "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Include" ) - # TODO: How do we know whether we're building 32-bit vs. 64-bit for MS-MPI? + # Decide between 32-bit and 64-bit libraries for Microsoft's MPI + if (CMAKE_CL_64) + set(MS_MPI_ARCH_DIR amd64) + else (CMAKE_CL_64) + set(MS_MPI_ARCH_DIR i386) + endif (CMAKE_CL_64) + find_library(MPI_LIBRARY - NAMES mpi mpich + NAMES mpi mpich msmpi PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib "C:/Program Files/MPICH/SDK/Lib" "$ENV{SystemDrive}/Program Files/MPICH/SDK/Lib" - "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Lib/i386" + "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Lib/${MS_MPI_ARCH_DIR}" ) find_library(MPI_LIBRARY NAMES mpich2 diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake index 07dd29f69b..0007ee3cc5 100644 --- a/Modules/FindwxWidgets.cmake +++ b/Modules/FindwxWidgets.cmake @@ -132,6 +132,18 @@ SET(wxWidgets_LIBRARIES "") SET(wxWidgets_LIBRARY_DIRS "") SET(wxWidgets_CXX_FLAGS "") +# Using SYSTEM with INCLUDE_DIRECTORIES in conjunction with wxWidgets on +# the Mac produces compiler errors. Set wxWidgets_INCLUDE_DIRS_NO_SYSTEM +# to prevent UsewxWidgets.cmake from using SYSTEM. +# +# See cmake mailing list discussions for more info: +# http://www.cmake.org/pipermail/cmake/2008-April/021115.html +# http://www.cmake.org/pipermail/cmake/2008-April/021146.html +# +IF(APPLE) + SET(wxWidgets_INCLUDE_DIRS_NO_SYSTEM 1) +ENDIF(APPLE) + # DEPRECATED: This is a patch to support the DEPRECATED use of # wxWidgets_USE_LIBS. # diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index b36e2303bd..ba91a089c6 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -29,6 +29,7 @@ #include "cmCPackLog.h" #include <cmsys/CommandLineArguments.hxx> +#include <memory> // auto_ptr //---------------------------------------------------------------------------- static const char * cmDocumentationName[][3] = @@ -222,7 +223,7 @@ int main (int argc, char *argv[]) cminst.RemoveUnscriptableCommands(); cmGlobalGenerator cmgg; cmgg.SetCMakeInstance(&cminst); - cmLocalGenerator* cmlg = cmgg.CreateLocalGenerator(); + std::auto_ptr<cmLocalGenerator> cmlg(cmgg.CreateLocalGenerator()); cmMakefile* globalMF = cmlg->GetMakefile(); bool cpackConfigFileSpecified = true; diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 1c5e25d475..56ee7ac730 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -138,6 +138,7 @@ CMakeSetupDialog::CMakeSetupDialog() // fixed pitch font in output window QFont outputFont("Courier"); this->Output->setFont(outputFont); + this->ErrorFormat.setForeground(QBrush(Qt::red)); // start the cmake worker thread this->CMakeThread = new QCMakeThread(this); @@ -512,32 +513,17 @@ void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent) { this->ProgressBar->setValue(qRound(percent * 100)); } - + void CMakeSetupDialog::error(const QString& message) { - QStringList messages = message.split('\n'); - foreach(QString m, messages) - { - // make sure we escape html tags in the cmake messages - m.replace(QString("&"), QString("&")); - m.replace(QString("<"), QString("<")); - m.replace(QString(">"), QString(">")); - m.replace(QString(" "), QString(" ")); - this->Output->append(QString("<b><font color=red>%1</font></b>").arg(m)); - } + this->Output->setCurrentCharFormat(this->ErrorFormat); + this->Output->append(message); } void CMakeSetupDialog::message(const QString& message) { - QStringList messages = message.split('\n'); - foreach(QString m, messages) - { - // make sure we escape html tags in the cmake messages - m.replace(QString("&"), QString("&")); - m.replace(QString("<"), QString("<")); - m.replace(QString(">"), QString(">")); - this->Output->append(m); - } + this->Output->setCurrentCharFormat(this->MessageFormat); + this->Output->append(message); } void CMakeSetupDialog::setEnabledState(bool enabled) diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index 211dfcb023..c942d154e1 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -99,6 +99,9 @@ protected: QAction* InstallForCommandLineAction; State CurrentState; + QTextCharFormat ErrorFormat; + QTextCharFormat MessageFormat; + }; // QCMake instance on a thread diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index a6440ed083..2cf6b965d2 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -98,9 +98,18 @@ public: // Forward to the per-class implementation. virtual unsigned int GetNumberOfSections() const = 0; + virtual unsigned int GetDynamicEntryCount() = 0; + virtual unsigned long GetDynamicEntryPosition(int j) = 0; virtual StringEntry const* GetDynamicSectionString(int tag) = 0; virtual void PrintInfo(std::ostream& os) const = 0; + bool ReadBytes(unsigned long pos, unsigned long size, char* buf) + { + this->Stream.seekg(pos); + this->Stream.read(buf, size); + return this->Stream?true:false; + } + // Lookup the SONAME in the DYNAMIC section. StringEntry const* GetSOName() { @@ -201,6 +210,10 @@ public: return static_cast<unsigned int>(this->ELFHeader.e_shnum); } + // Get the file position and size of a dynamic section entry. + virtual unsigned int GetDynamicEntryCount(); + virtual unsigned long GetDynamicEntryPosition(int j); + // Lookup a string from the dynamic section with the given tag. virtual StringEntry const* GetDynamicSectionString(int tag); @@ -552,6 +565,40 @@ bool cmELFInternalImpl<Types>::LoadDynamicSection() //---------------------------------------------------------------------------- template <class Types> +unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount() +{ + if(!this->LoadDynamicSection()) + { + return 0; + } + for(unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i) + { + if(this->DynamicSectionEntries[i].d_tag == DT_NULL) + { + return i; + } + } + return this->DynamicSectionEntries.size(); +} + +//---------------------------------------------------------------------------- +template <class Types> +unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j) +{ + if(!this->LoadDynamicSection()) + { + return 0; + } + if(j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) + { + return 0; + } + ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; + return sec.sh_offset + sec.sh_entsize*j; +} + +//---------------------------------------------------------------------------- +template <class Types> cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(int tag) { @@ -571,6 +618,7 @@ cmELFInternalImpl<Types>::GetDynamicSectionString(int tag) StringEntry& se = this->DynamicSectionStrings[tag]; se.Position = 0; se.Size = 0; + se.IndexInSection = -1; // Try reading the dynamic section. if(!this->LoadDynamicSection()) @@ -641,6 +689,7 @@ cmELFInternalImpl<Types>::GetDynamicSectionString(int tag) // The value has been read successfully. Report it. se.Position = static_cast<unsigned long>(strtab.sh_offset + first); se.Size = last - first; + se.IndexInSection = di - this->DynamicSectionEntries.begin(); return &se; } } @@ -762,6 +811,45 @@ unsigned int cmELF::GetNumberOfSections() const } //---------------------------------------------------------------------------- +unsigned int cmELF::GetDynamicEntryCount() const +{ + if(this->Valid()) + { + return this->Internal->GetDynamicEntryCount(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +unsigned long cmELF::GetDynamicEntryPosition(int index) const +{ + if(this->Valid()) + { + return this->Internal->GetDynamicEntryPosition(index); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const +{ + if(this->Valid()) + { + return this->Internal->ReadBytes(pos, size, buf); + } + else + { + return false; + } +} + +//---------------------------------------------------------------------------- bool cmELF::GetSOName(std::string& soname) { if(StringEntry const* se = this->GetSOName()) diff --git a/Source/cmELF.h b/Source/cmELF.h index 9e4575b5ad..aeb409633a 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -68,6 +68,9 @@ public: // The size of the string table entry. This includes the space // allocated for one or more null terminators. unsigned long Size; + + // The index of the section entry referencing the string. + int IndexInSection; }; /** Get the type of the file opened. */ @@ -76,6 +79,17 @@ public: /** Get the number of ELF sections present. */ unsigned int GetNumberOfSections() const; + /** Get the number of DYNAMIC section entries before the first + DT_NULL. Returns zero on error. */ + unsigned int GetDynamicEntryCount() const; + + /** Get the position of a DYNAMIC section header entry. Returns + zero on error. */ + unsigned long GetDynamicEntryPosition(int index) const; + + /** Read bytes from the file. */ + bool ReadBytes(unsigned long pos, unsigned long size, char* buf) const; + /** Get the SONAME field if any. */ bool GetSOName(std::string& soname); StringEntry const* GetSOName(); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 68ccbb28f9..3cf6c0be68 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -112,9 +112,17 @@ bool cmFileCommand { return this->HandleInstallCommand(args); } - else if ( subCommand == "CHRPATH" ) + else if ( subCommand == "RPATH_CHANGE" || subCommand == "CHRPATH" ) { - return this->HandleChrpathCommand(args); + return this->HandleRPathChangeCommand(args); + } + else if ( subCommand == "RPATH_CHECK" ) + { + return this->HandleRPathCheckCommand(args); + } + else if ( subCommand == "RPATH_REMOVE" ) + { + return this->HandleRPathRemoveCommand(args); } else if ( subCommand == "RELATIVE_PATH" ) { @@ -1332,7 +1340,8 @@ bool cmFileCommand::HandleInstallDestination(cmFileInstaller& installer, } //---------------------------------------------------------------------------- -bool cmFileCommand::HandleChrpathCommand(std::vector<std::string> const& args) +bool +cmFileCommand::HandleRPathChangeCommand(std::vector<std::string> const& args) { // Evaluate arguments. const char* file = 0; @@ -1372,49 +1381,174 @@ bool cmFileCommand::HandleChrpathCommand(std::vector<std::string> const& args) else { cmOStringStream e; - e << "CHRPATH given unknown argument " << args[i]; + e << "RPATH_CHANGE given unknown argument " << args[i]; this->SetError(e.str().c_str()); return false; } } if(!file) { - this->SetError("CHRPATH not given FILE option."); + this->SetError("RPATH_CHANGE not given FILE option."); return false; } if(!oldRPath) { - this->SetError("CHRPATH not given OLD_RPATH option."); + this->SetError("RPATH_CHANGE not given OLD_RPATH option."); return false; } if(!newRPath) { - this->SetError("CHRPATH not given NEW_RPATH option."); + this->SetError("RPATH_CHANGE not given NEW_RPATH option."); return false; } if(!cmSystemTools::FileExists(file, true)) { cmOStringStream e; - e << "CHRPATH given FILE \"" << file << "\" that does not exist."; + e << "RPATH_CHANGE given FILE \"" << file << "\" that does not exist."; this->SetError(e.str().c_str()); return false; } + bool success = true; + cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew(); + bool have_ft = cmSystemTools::FileTimeGet(file, ft); std::string emsg; - if(cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg)) - { - return true; - } - else + if(!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg)) { cmOStringStream e; - e << "CHRPATH could not write new RPATH:\n" + e << "RPATH_CHANGE could not write new RPATH:\n" << " " << newRPath << "\n" << "to the file:\n" << " " << file << "\n" << emsg; this->SetError(e.str().c_str()); + success = false; + } + if(success && have_ft) + { + cmSystemTools::FileTimeSet(file, ft); + } + cmSystemTools::FileTimeDelete(ft); + return success; +} + +//---------------------------------------------------------------------------- +bool +cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args) +{ + // Evaluate arguments. + const char* file = 0; + enum Doing { DoingNone, DoingFile }; + Doing doing = DoingNone; + for(unsigned int i=1; i < args.size(); ++i) + { + if(args[i] == "FILE") + { + doing = DoingFile; + } + else if(doing == DoingFile) + { + file = args[i].c_str(); + doing = DoingNone; + } + else + { + cmOStringStream e; + e << "RPATH_REMOVE given unknown argument " << args[i]; + this->SetError(e.str().c_str()); + return false; + } + } + if(!file) + { + this->SetError("RPATH_REMOVE not given FILE option."); + return false; + } + if(!cmSystemTools::FileExists(file, true)) + { + cmOStringStream e; + e << "RPATH_REMOVE given FILE \"" << file << "\" that does not exist."; + this->SetError(e.str().c_str()); + return false; + } + bool success = true; + cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew(); + bool have_ft = cmSystemTools::FileTimeGet(file, ft); + std::string emsg; + if(!cmSystemTools::RemoveRPath(file, &emsg)) + { + cmOStringStream e; + e << "RPATH_REMOVE could not remove RPATH from file:\n" + << " " << file << "\n" + << emsg; + this->SetError(e.str().c_str()); + success = false; + } + if(success && have_ft) + { + cmSystemTools::FileTimeSet(file, ft); + } + cmSystemTools::FileTimeDelete(ft); + return success; +} + +//---------------------------------------------------------------------------- +bool +cmFileCommand::HandleRPathCheckCommand(std::vector<std::string> const& args) +{ + // Evaluate arguments. + const char* file = 0; + const char* rpath = 0; + enum Doing { DoingNone, DoingFile, DoingRPath }; + Doing doing = DoingNone; + for(unsigned int i=1; i < args.size(); ++i) + { + if(args[i] == "RPATH") + { + doing = DoingRPath; + } + else if(args[i] == "FILE") + { + doing = DoingFile; + } + else if(doing == DoingFile) + { + file = args[i].c_str(); + doing = DoingNone; + } + else if(doing == DoingRPath) + { + rpath = args[i].c_str(); + doing = DoingNone; + } + else + { + cmOStringStream e; + e << "RPATH_CHECK given unknown argument " << args[i]; + this->SetError(e.str().c_str()); + return false; + } + } + if(!file) + { + this->SetError("RPATH_CHECK not given FILE option."); + return false; + } + if(!rpath) + { + this->SetError("RPATH_CHECK not given RPATH option."); return false; } + + // If the file exists but does not have the desired RPath then + // delete it. This is used during installation to re-install a file + // if its RPath will change. + if(cmSystemTools::FileExists(file, true) && + !cmSystemTools::CheckRPath(file, rpath)) + { + cmSystemTools::RemoveFile(file); + } + + return true; } //---------------------------------------------------------------------------- diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 85bdc32484..3f72cd2867 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -171,7 +171,9 @@ protected: bool HandleRelativePathCommand(std::vector<std::string> const& args); bool HandleCMakePathCommand(std::vector<std::string> const& args, bool nativePath); - bool HandleChrpathCommand(std::vector<std::string> const& args); + bool HandleRPathChangeCommand(std::vector<std::string> const& args); + bool HandleRPathCheckCommand(std::vector<std::string> const& args); + bool HandleRPathRemoveCommand(std::vector<std::string> const& args); // file(INSTALL ...) related functions bool HandleInstallCommand(std::vector<std::string> const& args); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 80dcdfc666..03bd15928d 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -536,7 +536,22 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs, false); } - else + if(!runtimeArgs.GetDestination().empty()) + { + bool failure = false; + if(this->CheckCMP0006(failure)) + { + // For CMake 2.4 compatibility fallback to the RUNTIME + // properties. + bundleGenerator = + CreateInstallTargetGenerator(target, runtimeArgs, false); + } + else if(failure) + { + return false; + } + } + if(!bundleGenerator) { cmOStringStream e; e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE " @@ -1284,3 +1299,34 @@ bool cmInstallCommand::MakeFilesFullPath(const char* modeName, } return true; } + +//---------------------------------------------------------------------------- +bool cmInstallCommand::CheckCMP0006(bool& failure) +{ + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) + { + case cmPolicies::WARN: + { + this->Makefile->IssueMessage( + cmake::AUTHOR_WARNING, + this->Makefile->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0006) + ); + } + case cmPolicies::OLD: + // OLD behavior is to allow compatibility + return true; + case cmPolicies::NEW: + // NEW behavior is to disallow compatibility + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + failure = true; + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + this->Makefile->GetPolicies() + ->GetRequiredPolicyError(cmPolicies::CMP0006) + ); + break; + } + return false; +} diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 4978059b15..0b7ae7a3e8 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -109,19 +109,19 @@ public: " ] [...])\n" "The TARGETS form specifies rules for installing targets from a " "project. There are five kinds of target files that may be " - "installed: archive, library, runtime, framework, and bundle. " + "installed: ARCHIVE, LIBRARY, RUNTIME, FRAMEWORK, and BUNDLE. " - "Executables are treated as runtime targets, except that those " - "marked with the MACOSX_BUNDLE property are treated as bundle " + "Executables are treated as RUNTIME targets, except that those " + "marked with the MACOSX_BUNDLE property are treated as BUNDLE " "targets on OS X. " - "Static libraries are always treated as archive targets. " - "Module libraries are always treated as library targets. " - "For non-DLL platforms shared libraries are treated as library " + "Static libraries are always treated as ARCHIVE targets. " + "Module libraries are always treated as LIBRARY targets. " + "For non-DLL platforms shared libraries are treated as LIBRARY " "targets, except that those marked with the FRAMEWORK property " - "are treated as framework targets on OS X. " + "are treated as FRAMEWORK targets on OS X. " "For DLL platforms the DLL part of a shared library is treated as " - "a runtime target and the corresponding import library is treated as " - "an archive target. " + "a RUNTIME target and the corresponding import library is treated as " + "an ARCHIVE target. " "All Windows-based systems including Cygwin are DLL platforms. " "The ARCHIVE, LIBRARY, RUNTIME, and FRAMEWORK " "arguments change the type of target to which the subsequent " @@ -346,6 +346,7 @@ private: bool MakeFilesFullPath(const char* modeName, const std::vector<std::string>& relFiles, std::vector<std::string>& absFiles); + bool CheckCMP0006(bool& failure); }; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 5fd408e366..8db09575a2 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -333,6 +333,32 @@ cmInstallTargetGenerator return; } + // Construct the path of the file on disk after installation on + // which tweaks may be performed. + std::string toDestDirPath = "$ENV{DESTDIR}"; + if(toInstallPath[0] != '/' && toInstallPath[0] != '$') + { + toDestDirPath += "/"; + } + toDestDirPath += toInstallPath; + + // Add pre-installation tweaks. + if(tweakInstalledFile) + { + // Collect tweaking rules. + cmOStringStream tw; + this->AddRPathCheckRule(tw, indent.Next(), config, toDestDirPath); + std::string tws = tw.str(); + + // Add the rules, if any. + if(!tws.empty()) + { + os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n"; + os << tws; + os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n"; + } + } + // Write code to install the target file. const char* no_dir_permissions = 0; const char* no_rename = 0; @@ -344,25 +370,24 @@ cmInstallTargetGenerator no_rename, literal_args.c_str(), indent); - // Construct the path of the file on disk after installation on - // which tweaks may be performed. - std::string toDestDirPath = "$ENV{DESTDIR}"; - if(toInstallPath[0] != '/' && toInstallPath[0] != '$') - { - toDestDirPath += "/"; - } - toDestDirPath += toInstallPath; - - // TODO: - // - Skip IF(EXISTS) checks if nothing is done with the installed file + // Add post-installation tweaks. if(tweakInstalledFile) { - os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n"; - this->AddInstallNamePatchRule(os, indent.Next(), config, toDestDirPath); - this->AddChrpathPatchRule(os, indent.Next(), config, toDestDirPath); - this->AddRanlibRule(os, indent.Next(), type, toDestDirPath); - this->AddStripRule(os, indent.Next(), type, toDestDirPath); - os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n"; + // Collect tweaking rules. + cmOStringStream tw; + this->AddInstallNamePatchRule(tw, indent.Next(), config, toDestDirPath); + this->AddChrpathPatchRule(tw, indent.Next(), config, toDestDirPath); + this->AddRanlibRule(tw, indent.Next(), type, toDestDirPath); + this->AddStripRule(tw, indent.Next(), type, toDestDirPath); + std::string tws = tw.str(); + + // Add the rules, if any. + if(!tws.empty()) + { + os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n"; + os << tws; + os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n"; + } } } @@ -550,6 +575,37 @@ cmInstallTargetGenerator //---------------------------------------------------------------------------- void cmInstallTargetGenerator +::AddRPathCheckRule(std::ostream& os, Indent const& indent, + const char* config, std::string const& toDestDirPath) +{ + // Skip the chrpath if the target does not need it. + if(this->ImportLibrary || !this->Target->IsChrpathUsed()) + { + return; + } + + // Get the link information for this target. + // It can provide the RPATH. + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); + if(!cli) + { + return; + } + + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + + // Write a rule to remove the installed file if its rpath is not the + // new rpath. This is needed for existing build/install trees when + // the installed rpath changes but the file is not rebuilt. + os << indent << "FILE(RPATH_CHECK\n" + << indent << " FILE \"" << toDestDirPath << "\"\n" + << indent << " RPATH \"" << newRpath << "\")\n"; +} + +//---------------------------------------------------------------------------- +void +cmInstallTargetGenerator ::AddChrpathPatchRule(std::ostream& os, Indent const& indent, const char* config, std::string const& toDestDirPath) { @@ -580,9 +636,18 @@ cmInstallTargetGenerator } // Write a rule to run chrpath to set the install-tree RPATH - os << indent << "FILE(CHRPATH FILE \"" << toDestDirPath << "\"\n" - << indent << " OLD_RPATH \"" << oldRpath << "\"\n" - << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + if(newRpath.empty()) + { + os << indent << "FILE(RPATH_REMOVE\n" + << indent << " FILE \"" << toDestDirPath << "\")\n"; + } + else + { + os << indent << "FILE(RPATH_CHANGE\n" + << indent << " FILE \"" << toDestDirPath << "\"\n" + << indent << " OLD_RPATH \"" << oldRpath << "\"\n" + << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + } } //---------------------------------------------------------------------------- diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 95c255d223..61357b3825 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -80,6 +80,9 @@ protected: void AddChrpathPatchRule(std::ostream& os, Indent const& indent, const char* config, std::string const& toDestDirPath); + void AddRPathCheckRule(std::ostream& os, Indent const& indent, + const char* config, + std::string const& toDestDirPath); void AddStripRule(std::ostream& os, Indent const& indent, cmTarget::TargetType type, diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index e16af18e4c..8c5b87f874 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -407,6 +407,7 @@ public: Linker }; cmLocalVisualStudio7GeneratorOptions(cmLocalVisualStudio7Generator* lg, + int version, Tool tool, cmVS7FlagTable const* extraTable = 0); @@ -439,6 +440,7 @@ public: private: cmLocalVisualStudio7Generator* LocalGenerator; + int Version; // create a map of xml tags to the values they should have in the output // for example, "BufferSecurityCheck" = "TRUE" @@ -551,7 +553,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, std::string defineFlags = this->Makefile->GetDefineFlags(); // Construct a set of build options for this target. - Options targetOptions(this, Options::Compiler, this->ExtraFlagTable); + Options targetOptions(this, this->Version, Options::Compiler, this->ExtraFlagTable); targetOptions.FixExceptionHandlingDefault(); targetOptions.Parse(flags.c_str()); targetOptions.Parse(defineFlags.c_str()); @@ -745,7 +747,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, extraLinkOptions += " "; extraLinkOptions += targetLinkFlags; } - Options linkOptions(this, Options::Linker); + Options linkOptions(this, this->Version, Options::Linker); linkOptions.Parse(extraLinkOptions.c_str()); switch(target.GetType()) { @@ -1289,7 +1291,7 @@ void cmLocalVisualStudio7Generator !fc.CompileDefs.empty() || !fc.CompileDefsConfig.empty()) { - Options fileOptions(this, Options::Compiler, + Options fileOptions(this, this->Version, Options::Compiler, this->ExtraFlagTable); fileOptions.Parse(fc.CompileFlags.c_str()); fileOptions.AddDefines(fc.CompileDefs.c_str()); @@ -1762,9 +1764,10 @@ std::string cmLocalVisualStudio7Generator //---------------------------------------------------------------------------- cmLocalVisualStudio7GeneratorOptions ::cmLocalVisualStudio7GeneratorOptions(cmLocalVisualStudio7Generator* lg, + int version, Tool tool, cmVS7FlagTable const* extraTable): - LocalGenerator(lg), CurrentTool(tool), + LocalGenerator(lg), Version(version), CurrentTool(tool), DoingDefine(false), FlagTable(0), ExtraFlagTable(extraTable) { // Choose the flag table for the requested tool. @@ -1786,7 +1789,17 @@ void cmLocalVisualStudio7GeneratorOptions::FixExceptionHandlingDefault() // initialization to off, but the user has the option of removing // the flag to disable exception handling. When the user does // remove the flag we need to override the IDE default of on. - this->FlagMap["ExceptionHandling"] = "FALSE"; + switch (this->Version) + { + case 7: + case 71: + this->FlagMap["ExceptionHandling"] = "FALSE"; + break; + + default: + this->FlagMap["ExceptionHandling"] = "0"; + break; + } } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 70978c3272..a881391c4e 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -724,7 +724,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash(); objdir += this->Target->GetName(); objdir += ".dir"; - vars.ObjectDir = objdir.c_str(); + objdir = this->Convert(objdir.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + vars.ObjectDir = objdir.c_str(); vars.Target = targetOutPathReal.c_str(); std::string linkString = linklibs.str(); vars.LinkLibraries = linkString.c_str(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index cd08bdb1e9..28a6105f2c 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -334,8 +334,13 @@ void cmMakefileTargetGenerator::WriteMacOSXContentRules(cmSourceFile& source, macdir += pkgloc; cmSystemTools::MakeDirectory(macdir.c_str()); - // Record use of this content location. - this->MacContentFolders.insert(pkgloc); + // Record use of this content location. Only the first level + // directory is needed. + { + std::string loc = pkgloc; + loc = loc.substr(0, loc.find('/')); + this->MacContentFolders.insert(loc); + } // Get the input file location. std::string input = source.GetFullPath(); @@ -614,6 +619,9 @@ cmMakefileTargetGenerator cmLocalGenerator::SHELL).c_str(); vars.Object = shellObj.c_str(); std::string objectDir = cmSystemTools::GetFilenamePath(obj); + objectDir = this->Convert(objectDir.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); vars.ObjectDir = objectDir.c_str(); vars.Flags = flags.c_str(); vars.Defines = defines.c_str(); diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 26d9012b89..a6f5808b6f 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -60,7 +60,7 @@ bool cmMessageCommand if (send_error || fatal_error) { - cmSystemTools::Error(message.c_str()); + this->Makefile->IssueMessage(cmake::FATAL_ERROR, message.c_str()); } else { diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index b69a7198e5..4e1b857d92 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -251,6 +251,24 @@ cmPolicies::cmPolicies() "See documentation of the COMPILE_DEFINITIONS target property for " "limitations of the escaping implementation.", 2,6,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0006, "CMP0006", + "Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION.", + "This policy determines whether the install(TARGETS) command must be " + "given a BUNDLE DESTINATION when asked to install a target with the " + "MACOSX_BUNDLE property set. " + "CMake 2.4 and below did not distinguish application bundles from " + "normal executables when installing targets. " + "CMake 2.6 provides a BUNDLE option to the install(TARGETS) command " + "that specifies rules specific to application bundles on the Mac. " + "Projects should use this option when installing a target with the " + "MACOSX_BUNDLE property set.\n" + "The OLD behavior for this policy is to fall back to the RUNTIME " + "DESTINATION if a BUNDLE DESTINATION is not given. " + "The NEW behavior for this policy is to produce an error if a bundle " + "target is installed without a BUNDLE DESTINATION.", + 2,6,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 5adfbfa28a..fed9d3194a 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -46,6 +46,7 @@ public: CMP0003, // Linking does not include extra -L paths CMP0004, // Libraries linked may not have leading or trailing whitespace CMP0005, // Definition value escaping + CMP0006, // BUNDLE install rules needed for MACOSX_BUNDLE targets // Always the last entry. Useful mostly to avoid adding a comma // the last policy when adding a new one. diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 6091ab546d..4d25944d4a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -56,6 +56,18 @@ # include "cmELF.h" #endif +class cmSystemToolsFileTime +{ +public: +#if defined(_WIN32) && !defined(__CYGWIN__) + FILETIME timeCreation; + FILETIME timeLastAccess; + FILETIME timeLastWrite; +#else + struct utimbuf timeBuf; +#endif +}; + #if defined(__sgi) && !defined(__GNUC__) # pragma set woff 1375 /* base class destructor not virtual */ #endif @@ -2111,6 +2123,67 @@ bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile) } //---------------------------------------------------------------------------- +cmSystemToolsFileTime* cmSystemTools::FileTimeNew() +{ + return new cmSystemToolsFileTime; +} + +//---------------------------------------------------------------------------- +void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime* t) +{ + delete t; +} + +//---------------------------------------------------------------------------- +bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + cmSystemToolsWindowsHandle h = + CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if(!h) + { + return false; + } + if(!GetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite)) + { + return false; + } +#else + struct stat st; + if(stat(fname, &st) < 0) + { + return false; + } + t->timeBuf.actime = st.st_atime; + t->timeBuf.modtime = st.st_mtime; +#endif + return true; +} + +//---------------------------------------------------------------------------- +bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + cmSystemToolsWindowsHandle h = + CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + if(!h) + { + return false; + } + if(!SetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite)) + { + return false; + } +#else + if(utime(fname, &t->timeBuf) < 0) + { + return false; + } +#endif + return true; +} + +//---------------------------------------------------------------------------- static std::string cmSystemToolsExecutableDirectory; void cmSystemTools::FindExecutableDirectory(const char* argv0) { @@ -2390,3 +2463,173 @@ bool cmSystemTools::ChangeRPath(std::string const& file, return false; #endif } + +//---------------------------------------------------------------------------- +bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg) +{ +#if defined(CMAKE_USE_ELF_PARSER) + unsigned long rpathPosition = 0; + unsigned long rpathSize = 0; + unsigned long rpathEntryPosition = 0; + std::vector<char> bytes; + { + // Parse the ELF binary. + cmELF elf(file.c_str()); + + // Get the RPATH or RUNPATH entry from it. + cmELF::StringEntry const* se = elf.GetRPath(); + if(!se) + { + se = elf.GetRunPath(); + } + + if(se) + { + // Store information about the entry. + rpathPosition = se->Position; + rpathSize = se->Size; + rpathEntryPosition = elf.GetDynamicEntryPosition(se->IndexInSection); + + // Get the file range containing the rest of the DYNAMIC table + // after the RPATH entry. + unsigned long nextEntryPosition = + elf.GetDynamicEntryPosition(se->IndexInSection+1); + unsigned int count = elf.GetDynamicEntryCount(); + if(count == 0) + { + // This should happen only for invalid ELF files where a DT_NULL + // appears before the end of the table. + if(emsg) + { + *emsg = "DYNAMIC section contains a DT_NULL before the end."; + } + return false; + } + unsigned long nullEntryPosition = elf.GetDynamicEntryPosition(count); + + // Allocate and fill a buffer with zeros. + bytes.resize(nullEntryPosition - rpathEntryPosition, 0); + + // Read the part of the DYNAMIC section header that will move. + // The remainder of the buffer will be left with zeros which + // represent a DT_NULL entry. + if(!elf.ReadBytes(nextEntryPosition, + nullEntryPosition - nextEntryPosition, + &bytes[0])) + { + if(emsg) + { + *emsg = "Failed to read DYNAMIC section header."; + } + return false; + } + } + else + { + // There is no RPATH or RUNPATH anyway. + return true; + } + } + + // Open the file for update. + std::ofstream f(file.c_str(), + std::ios::in | std::ios::out | std::ios::binary); + if(!f) + { + if(emsg) + { + *emsg = "Error opening file for update."; + } + return false; + } + + // Write the new DYNAMIC table header. + if(!f.seekp(rpathEntryPosition)) + { + if(emsg) + { + *emsg = "Error seeking to DYNAMIC table header for RPATH."; + } + return false; + } + if(!f.write(&bytes[0], bytes.size())) + { + if(emsg) + { + *emsg = "Error replacing DYNAMIC table header."; + } + return false; + } + + // Fill the RPATH string with zero bytes. + if(!f.seekp(rpathPosition)) + { + if(emsg) + { + *emsg = "Error seeking to RPATH position."; + } + return false; + } + for(unsigned long i=0; i < rpathSize; ++i) + { + f << '\0'; + } + + // Make sure everything was okay. + if(f) + { + return true; + } + else + { + if(emsg) + { + *emsg = "Error writing the empty rpath to the file."; + } + return false; + } +#else + (void)file; + (void)emsg; + return false; +#endif +} + +//---------------------------------------------------------------------------- +bool cmSystemTools::CheckRPath(std::string const& file, + std::string const& newRPath) +{ +#if defined(CMAKE_USE_ELF_PARSER) + // Parse the ELF binary. + cmELF elf(file.c_str()); + + // Get the RPATH or RUNPATH entry from it. + cmELF::StringEntry const* se = elf.GetRPath(); + if(!se) + { + se = elf.GetRunPath(); + } + + // Make sure the current rpath contains the new rpath. + if(newRPath.empty()) + { + if(!se) + { + return true; + } + } + else + { + if(se && + cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) + { + return true; + } + } + return false; +#else + (void)file; + (void)newRPath; + return false; +#endif +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index a7abc5f108..89cf407a2d 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -22,7 +22,7 @@ #include <cmsys/SystemTools.hxx> #include <cmsys/Process.h> - +class cmSystemToolsFileTime; /** \class cmSystemTools * \brief A collection of useful functions for CMake. @@ -363,6 +363,12 @@ public: the first argument to that named by the second. */ static bool CopyFileTime(const char* fromFile, const char* toFile); + /** Save and restore file times. */ + static cmSystemToolsFileTime* FileTimeNew(); + static void FileTimeDelete(cmSystemToolsFileTime*); + static bool FileTimeGet(const char* fname, cmSystemToolsFileTime* t); + static bool FileTimeSet(const char* fname, cmSystemToolsFileTime* t); + /** Find the directory containing the running executable. Save it in a global location to be queried by GetExecutableDirectory later. */ @@ -387,6 +393,14 @@ public: std::string const& newRPath, std::string* emsg = 0); + /** Try to remove the RPATH from an ELF binary. */ + static bool RemoveRPath(std::string const& file, std::string* emsg = 0); + + /** Check whether the RPATH in an ELF binary contains the path + given. */ + static bool CheckRPath(std::string const& file, + std::string const& newRPath); + private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e7bf4eca22..1bf306124c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -134,8 +134,8 @@ void cmTarget::DefineProperties(cmake *cm) ("DEBUG_POSTFIX", cmProperty::TARGET, "A postfix that will be applied to this target when build debug.", "A property on a target that specifies a postfix to add to the " - "target name when built in debug mode. For example foo.dll " - "versus fooD.dll"); + "target name when built in debug mode. For example \"foo.dll\" " + "versus \"fooD.dll\". Ignored for Mac Frameworks and App Bundles."); cm->DefineProperty ("EchoString", cmProperty::TARGET, @@ -2311,6 +2311,12 @@ void cmTarget::GetFullNameInternal(TargetType type, std::string configProp = cmSystemTools::UpperCase(config); configProp += "_POSTFIX"; configPostfix = this->GetProperty(configProp.c_str()); + // Mac application bundles and frameworks have no postfix. + if(configPostfix && + (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) + { + configPostfix = 0; + } } const char* prefixVar = this->GetPrefixVariableInternal(type, implib); const char* suffixVar = this->GetSuffixVariableInternal(type, implib); diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt index 3eb0dbc32d..397e970f5c 100644 --- a/Tests/Framework/CMakeLists.txt +++ b/Tests/Framework/CMakeLists.txt @@ -24,6 +24,7 @@ set_target_properties(foo PROPERTIES PUBLIC_HEADER "foo.h;foo2.h;fooPublic.h;fooBoth.h" RESOURCE "test.lua" INSTALL_NAME_DIR "@executable_path/../../../Library/Frameworks" + DEBUG_POSTFIX -d ) # fooBoth.h is listed as both public and private... (private wins...) # fooNeither.h is listed as neither public nor private... diff --git a/Tests/Tutorial/Step7/CMakeLists.txt b/Tests/Tutorial/Step7/CMakeLists.txt index 826599b9f5..42f73f221b 100644 --- a/Tests/Tutorial/Step7/CMakeLists.txt +++ b/Tests/Tutorial/Step7/CMakeLists.txt @@ -75,6 +75,7 @@ include (InstallRequiredSystemLibraries) set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set (CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") set (CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}") +set (CPACK_PACKAGE_CONTACT "foo@bar.org") include (CPack) # enable dashboard scripting diff --git a/Tests/X11/CMakeLists.txt b/Tests/X11/CMakeLists.txt index 28b41edc9a..52f4a6fe9e 100644 --- a/Tests/X11/CMakeLists.txt +++ b/Tests/X11/CMakeLists.txt @@ -1,6 +1,6 @@ # a simple C only test case cmake_minimum_required (VERSION 2.6) -PROJECT (UseX11 C) +PROJECT (UseX11 CXX C) INCLUDE (${CMAKE_ROOT}/Modules/FindX11.cmake) MESSAGE("X11_FOUND: ${X11_FOUND}") @@ -23,4 +23,13 @@ IF(X11_FOUND) ADD_DEFINITIONS(-DCMAKE_HAS_X) INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR}) TARGET_LINK_LIBRARIES(UseX11 ${X11_LIBRARIES}) + IF(APPLE) + ADD_EXECUTABLE(HelloWorldX11 HelloWorldX11.cxx) + TARGET_LINK_LIBRARIES(HelloWorldX11 ${X11_LIBRARIES}) + install( TARGETS HelloWorldX11 DESTINATION bin) + # build a CPack driven installer package + set(CPACK_PACKAGE_NAME HelloWorldX11Package) + set(CPACK_PACKAGE_EXECUTABLES HelloWorldX11 HelloWorldX11) + include(CPack) + ENDIF(APPLE) ENDIF(X11_FOUND) diff --git a/Tests/X11/HelloWorldX11.cxx b/Tests/X11/HelloWorldX11.cxx new file mode 100644 index 0000000000..5bbc19a4aa --- /dev/null +++ b/Tests/X11/HelloWorldX11.cxx @@ -0,0 +1,145 @@ + +/*** START MAIN.H ***/ +/* http://www.geocities.com/jeff_louie/x11/helloworld.htm* */ +/* + * main.h + * TestX + * + * Created by Jeff Louie on Tue Feb 03 2004. + * Copyright (c) 2004 __MyCompanyName__. All rights reserved. + * + */ + + +#ifndef MAIN_H +#define MAIN_H 1 + +#include <iostream> + +/* include the X library headers */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> + +class Main { + +public: + // constructor + Main(int argc, char * const argv[]); + //virtual ~Main(); + + +private: + + + /* here are our X variables */ + Display *dis; + int screen; + Window win; + GC gc; + + /* here are our X routines declared! */ + void init_x(); + void close_x(); + void redraw(); + int delay(int i); + +}; + +#endif + +/*** END MAIN.H ***/ + +/*** START MAIN.CPP ***/ + +// modified from Brian Hammond's Howdy program at +// http://www.insanityengine.com/doc/x11/xintro.html +// jeff louie 02.05.2004 + + + +int main (int argc, char * const argv[]) { + Main m(argc, argv); + return 0; +} + +//Main::~Main() {;}; +Main::Main (int argc, char * const argv[]) { + XEvent event; // XEvent declaration + KeySym key; // KeyPress Events + char text[255]; // char buffer for KeyPress Events + + init_x(); + + // event loop + while(1) { + // get the next event and stuff it into our event variable. + // Note: only events we set the mask for are detected! + XNextEvent(dis, &event); + + + switch (event.type) { + int x; + int y; + case Expose: + if (event.xexpose.count==0) { + redraw(); + } + break; + case KeyPress: + if (XLookupString(&event.xkey,text,255,&key,0)==1) { + // use the XLookupString routine to convert the invent + // KeyPress data into regular text. Weird but necessary... + if ((text[0]=='q') || (text[0]=='Q')) { + close_x(); + } + else { + // echo key press + printf("You pressed the %c key!\n",text[0]); + } + } + break; + case ButtonPress: + // get cursor position + x= event.xbutton.x; + y= event.xbutton.y; + strcpy(text,"X is FUN!"); + XSetForeground(dis,gc,rand()%event.xbutton.x%255); + // draw text at cursor + XDrawString(dis,win,gc,x,y, text, strlen(text)); + break; + default: + printf("Unhandled event.\n"); + } + } +} + +void Main::init_x() { + unsigned long black,white; + + dis=XOpenDisplay(NULL); + screen=DefaultScreen(dis); + black=BlackPixel(dis,screen), + white=WhitePixel(dis, screen); + win=XCreateSimpleWindow(dis,DefaultRootWindow(dis),0,0, + 300, 300, 5,black, white); + XSetStandardProperties(dis,win,"Hello World","Hi",None,NULL,0,NULL); + XSelectInput(dis, win, ExposureMask|ButtonPressMask|KeyPressMask); + // get Graphics Context + gc=XCreateGC(dis, win, 0,0); + XSetBackground(dis,gc,white); + XSetForeground(dis,gc,black); + XClearWindow(dis, win); + XMapRaised(dis, win); +}; + +void Main::close_x() { + XFreeGC(dis, gc); + XDestroyWindow(dis,win); + XCloseDisplay(dis); + exit(1); +}; + +void Main::redraw() { + XClearWindow(dis, win); +}; |