diff --git a/CMakeLists.txt b/CMakeLists.txt index 14e7e7ab0..c94f14454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ MARK_AS_ADVANCED(CMAKE_BACKWARDS_COMPATIBILITY) # The CMake version number. SET(CMake_VERSION_MAJOR 2) SET(CMake_VERSION_MINOR 3) -SET(CMake_VERSION_PATCH 4) +SET(CMake_VERSION_PATCH 5) SET(CMake_VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") SET(CMake_VERSION_FULL "${CMake_VERSION}.${CMake_VERSION_PATCH}") diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index fcc694161..f02ba9894 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -99,11 +99,14 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) bool doing_targets = true; bool doing_destination = false; bool doing_permissions = false; + bool archive_settings = true; bool library_settings = true; bool runtime_settings = true; std::vector targets; + const char* archive_destination = 0; const char* library_destination = 0; const char* runtime_destination = 0; + std::string archive_permissions; std::string library_permissions; std::string runtime_permissions; for(unsigned int i=1; i < args.size(); ++i) @@ -122,12 +125,23 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_destination = false; doing_permissions = true; } + else if(args[i] == "ARCHIVE") + { + // Switch to setting only archive properties. + doing_targets = false; + doing_destination = false; + doing_permissions = false; + archive_settings = true; + library_settings = false; + runtime_settings = false; + } else if(args[i] == "LIBRARY") { // Switch to setting only library properties. doing_targets = false; doing_destination = false; doing_permissions = false; + archive_settings = false; library_settings = true; runtime_settings = false; } @@ -137,6 +151,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) doing_targets = false; doing_destination = false; doing_permissions = false; + archive_settings = false; library_settings = false; runtime_settings = true; } @@ -174,6 +189,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) else if(doing_destination) { // Set the destination in the active set(s) of properties. + if(archive_settings) + { + archive_destination = args[i].c_str(); + } if(library_settings) { library_destination = args[i].c_str(); @@ -187,6 +206,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) else if(doing_permissions) { // Set the permissions in the active set(s) of properties. + if(archive_settings) + { + // Check the requested permission. + if(!this->CheckPermissions(args[i], archive_permissions)) + { + cmOStringStream e; + e << args[0] << " given invalid permission \"" + << args[i] << "\"."; + this->SetError(e.str().c_str()); + return false; + } + } if(library_settings) { // Check the requested permission. @@ -227,15 +258,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) { return true; } - if(!library_destination && !runtime_destination) + if(!archive_destination && !library_destination && !runtime_destination) { this->SetError("TARGETS given no DESTINATION!"); return false; } // Compute destination paths. + std::string archive_dest; std::string library_dest; std::string runtime_dest; + this->ComputeDestination(archive_destination, archive_dest); this->ComputeDestination(library_destination, library_dest); this->ComputeDestination(runtime_destination, runtime_dest); @@ -255,12 +288,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) // platform. #if defined(_WIN32) || defined(__CYGWIN__) // This is a DLL platform. - if(library_destination) + if(archive_destination) { - // The import library uses the LIBRARY properties. + // The import library uses the ARCHIVE properties. this->Makefile->AddInstallGenerator( - new cmInstallTargetGenerator(target, library_dest.c_str(), true, - library_permissions.c_str())); + new cmInstallTargetGenerator(target, archive_dest.c_str(), true, + archive_permissions.c_str())); } if(runtime_destination) { @@ -278,13 +311,39 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) new cmInstallTargetGenerator(target, library_dest.c_str(), false, library_permissions.c_str())); } + else + { + cmOStringStream e; + e << "TARGETS given no LIBRARY DESTINATION for shared library " + "target \"" << target.GetName() << "\"."; + this->SetError(e.str().c_str()); + return false; + } #endif } break; case cmTarget::STATIC_LIBRARY: + { + // Static libraries use ARCHIVE properties. + if(archive_destination) + { + this->Makefile->AddInstallGenerator( + new cmInstallTargetGenerator(target, archive_dest.c_str(), false, + archive_permissions.c_str())); + } + else + { + cmOStringStream e; + e << "TARGETS given no ARCHIVE DESTINATION for static library " + "target \"" << target.GetName() << "\"."; + this->SetError(e.str().c_str()); + return false; + } + } + break; case cmTarget::MODULE_LIBRARY: { - // Static libraries and modules use LIBRARY properties. + // Modules use LIBRARY properties. if(library_destination) { this->Makefile->AddInstallGenerator( @@ -294,16 +353,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) else { cmOStringStream e; - e << "TARGETS given no LIBRARY DESTINATION for "; - if(target.GetType() == cmTarget::STATIC_LIBRARY) - { - e << "static library"; - } - else - { - e << "module"; - } - e << " target \"" << target.GetName() << "\"."; + e << "TARGETS given no LIBRARY DESTINATION for module target \"" + << target.GetName() << "\"."; this->SetError(e.str().c_str()); return false; } diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index d31fef5c0..e74d3b9fb 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -88,22 +88,26 @@ public: "when a single file is installed by the command. " "\n" "The TARGETS signature:\n" - " INSTALL(TARGETS targets... [[LIBRARY|RUNTIME]\n" + " INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME]\n" " [DESTINATION ]\n" " [PERMISSIONS permissions...]\n" " ] [...])\n" "The TARGETS form specifies rules for installing targets from a " - "project. There are two kinds of target files that may be " - "installed: library and runtime. Static libraries and modules " - "are always treated as library targets. Executables are always " - "treated as runtime targets. For non-DLL platforms, shared libraries " - "are treated as library targets. For DLL platforms, the DLL part of " - "a shared library is treated as a runtime target and the corresponding " - "import library is treated as a library target. All Windows-based " - "systems including Cygwin are DLL platforms. The LIBRARY and RUNTIME " - "arguments change the type of target to which the following properties " - "apply. If neither is given the installation properties apply to " - "both target types. If only one is given then only targets of that " + "project. There are three kinds of target files that may be " + "installed: archive, library, and runtime. " + + "Executables are always treated as runtime targets. " + "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. " + "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. " + "All Windows-based systems including Cygwin are DLL platforms. " + "The ARCHIVE, LIBRARY, and RUNTIME " + "arguments change the type of target to which the subsequent properties " + "apply. If none is given the installation properties apply to " + "all target types. If only one is given then only targets of that " "type will be installed (which can be used to install just a DLL or " "just an import library)." "\n" @@ -113,14 +117,16 @@ public: "targets \"myExe\", \"mySharedLib\", and \"myStaticLib\". The code\n" " INSTALL(TARGETS myExe mySharedLib myStaticLib\n" " RUNTIME DESTINATION bin\n" - " LIBRARY DESTINATION lib)\n" + " LIBRARY DESTINATION lib\n" + " ARCHIVE DESTINATION lib/static)\n" " INSTALL(TARGETS mySharedLib DESTINATION /some/full/path)\n" - "will install myExe to /bin and myStaticLib to /lib. " + "will install myExe to /bin and myStaticLib to " + "/lib/static. " "On non-DLL platforms mySharedLib will be installed to /lib and " "/some/full/path. On DLL platforms the mySharedLib DLL will be " "installed to /bin and /some/full/path and its import library " - "will be installed to /lib and /some/full/path. On non-DLL " - "platforms mySharedLib will be installed to /lib and " + "will be installed to /lib/static and /some/full/path. " + "On non-DLL platforms mySharedLib will be installed to /lib and " "/some/full/path." "\n" "The FILES signature:\n" diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index bc42e4026..31585ea39 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -22,7 +22,10 @@ SET(EXTRA_INSTALL_FLAGS) MESSAGE("Extra install: ${EXTRA_INSTALL_FLAGS}") IF(STAGE2) - SET(LIBPATHS "${CMAKE_INSTALL_PREFIX}/MyTest/lib") + SET(LIBPATHS + ${CMAKE_INSTALL_PREFIX}/MyTest/lib/static + ${CMAKE_INSTALL_PREFIX}/MyTest/lib + ) SET(t1NAMES test1 test1${CMAKE_DEBUG_POSTFIX}) SET(t2NAMES test2 test2${CMAKE_DEBUG_POSTFIX}) SET(t4NAMES test4 test4${CMAKE_DEBUG_POSTFIX}) @@ -63,6 +66,12 @@ IF(STAGE2) TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} ${TEST4_LIBRARY}) SET(install_target SimpleInstallS2) + IF("${TEST1_LIBRARY}" MATCHES "static") + MESSAGE(STATUS "test1 correctly found in lib/static") + ELSE("${TEST1_LIBRARY}" MATCHES "static") + MESSAGE(SEND_ERROR "test1 not found in lib/static!") + ENDIF("${TEST1_LIBRARY}" MATCHES "static") + # Make sure the test executable can run from the install tree. SET_TARGET_PROPERTIES(SimpleInstallS2 PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/MyTest/lib) @@ -93,9 +102,15 @@ ELSE(STAGE2) ADD_DEPENDENCIES(test4 test2) INSTALL(TARGETS SimpleInstall test1 test2 test3 - RUNTIME DESTINATION MyTest/bin LIBRARY DESTINATION MyTest/lib) + RUNTIME DESTINATION MyTest/bin # .exe, .dll + LIBRARY DESTINATION MyTest/lib # .so, module.dll, ... + ARCHIVE DESTINATION MyTest/lib/static # .a, .lib + ) INSTALL(TARGETS test4 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE - RUNTIME DESTINATION MyTest/bin LIBRARY DESTINATION MyTest/lib) + RUNTIME DESTINATION MyTest/bin + LIBRARY DESTINATION MyTest/lib + ARCHIVE DESTINATION MyTest/lib/static + ) INSTALL(FILES lib1.h DESTINATION MyTest/include/foo) INSTALL(FILES lib2.h DESTINATION MyTest/include/foo diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index bc42e4026..31585ea39 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/Tests/SimpleInstallS2/CMakeLists.txt @@ -22,7 +22,10 @@ SET(EXTRA_INSTALL_FLAGS) MESSAGE("Extra install: ${EXTRA_INSTALL_FLAGS}") IF(STAGE2) - SET(LIBPATHS "${CMAKE_INSTALL_PREFIX}/MyTest/lib") + SET(LIBPATHS + ${CMAKE_INSTALL_PREFIX}/MyTest/lib/static + ${CMAKE_INSTALL_PREFIX}/MyTest/lib + ) SET(t1NAMES test1 test1${CMAKE_DEBUG_POSTFIX}) SET(t2NAMES test2 test2${CMAKE_DEBUG_POSTFIX}) SET(t4NAMES test4 test4${CMAKE_DEBUG_POSTFIX}) @@ -63,6 +66,12 @@ IF(STAGE2) TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} ${TEST4_LIBRARY}) SET(install_target SimpleInstallS2) + IF("${TEST1_LIBRARY}" MATCHES "static") + MESSAGE(STATUS "test1 correctly found in lib/static") + ELSE("${TEST1_LIBRARY}" MATCHES "static") + MESSAGE(SEND_ERROR "test1 not found in lib/static!") + ENDIF("${TEST1_LIBRARY}" MATCHES "static") + # Make sure the test executable can run from the install tree. SET_TARGET_PROPERTIES(SimpleInstallS2 PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/MyTest/lib) @@ -93,9 +102,15 @@ ELSE(STAGE2) ADD_DEPENDENCIES(test4 test2) INSTALL(TARGETS SimpleInstall test1 test2 test3 - RUNTIME DESTINATION MyTest/bin LIBRARY DESTINATION MyTest/lib) + RUNTIME DESTINATION MyTest/bin # .exe, .dll + LIBRARY DESTINATION MyTest/lib # .so, module.dll, ... + ARCHIVE DESTINATION MyTest/lib/static # .a, .lib + ) INSTALL(TARGETS test4 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE - RUNTIME DESTINATION MyTest/bin LIBRARY DESTINATION MyTest/lib) + RUNTIME DESTINATION MyTest/bin + LIBRARY DESTINATION MyTest/lib + ARCHIVE DESTINATION MyTest/lib/static + ) INSTALL(FILES lib1.h DESTINATION MyTest/include/foo) INSTALL(FILES lib2.h DESTINATION MyTest/include/foo