diff options
101 files changed, 1808 insertions, 340 deletions
diff --git a/Modules/AutomocInfo.cmake.in b/Modules/AutomocInfo.cmake.in index 640bf70..9cff735 100644 --- a/Modules/AutomocInfo.cmake.in +++ b/Modules/AutomocInfo.cmake.in @@ -6,10 +6,9 @@ set(AM_MOC_OPTIONS @_moc_options@) set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@QT_MOC_EXECUTABLE@") +set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") -set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" ) -set(AM_Qt5Core_VERSION_MAJOR "@Qt5Core_VERSION_MAJOR@" ) +set(AM_QT_VERSION_MAJOR "@_target_qt_version@") set(AM_TARGET_NAME @_moc_target_name@) set(AM_RELAXED_MODE "@_moc_relaxed_mode@") diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 187f408..8332725 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -551,7 +551,10 @@ function(_ExternalData_arg_find_files pattern regex) set(relname "${entry}") set(alg "") endif() - if("x${relname}" MATCHES "^x${regex}$" AND NOT IS_DIRECTORY "${top_src}/${entry}") + if("x${relname}" MATCHES "^x${regex}$" # matches + AND NOT IS_DIRECTORY "${top_src}/${entry}" # not a directory + AND NOT "x${relname}" MATCHES "(^x|/)\\.ExternalData_" # not staged obj + ) set(name "${top_src}/${relname}") set(file "${top_bin}/${relname}") if(alg) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 7f79b14..d1ce2f4 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -928,9 +928,13 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") endif() + + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE NAMES ${_boost_RELEASE_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS} + HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} NAMES_PER_DIR DOC "${_boost_docstring_release}" ) @@ -960,9 +964,13 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") endif() + + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG NAMES ${_boost_DEBUG_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS} + HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} NAMES_PER_DIR DOC "${_boost_docstring_debug}" ) diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index af0c2dd..2972198 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -156,6 +156,16 @@ function(_protobuf_find_libraries name filename) endif() endfunction() +# Internal function: find threads library +function(_protobuf_find_threads) + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + find_package(Threads) + if(Threads_FOUND) + list(APPEND PROTOBUF_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) + set(PROTOBUF_LIBRARIES "${PROTOBUF_LIBRARIES}" PARENT_SCOPE) + endif() +endfunction() + # # Main. # @@ -190,6 +200,9 @@ if(MSVC) set(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}") endif() +if(UNIX) + _protobuf_find_threads() +endif() # Find the include directory find_path(PROTOBUF_INCLUDE_DIR diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index 68b37f3..8ce1934 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -884,16 +884,20 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) endforeach() if(Q_WS_WIN) - set(QT_MODULES ${QT_MODULES} QAxContainer QAxServer) - # Set QT_AXCONTAINER_INCLUDE_DIR and QT_AXSERVER_INCLUDE_DIR - find_path(QT_QAXCONTAINER_INCLUDE_DIR ActiveQt - PATHS ${QT_HEADERS_DIR}/ActiveQt - NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH - ) - find_path(QT_QAXSERVER_INCLUDE_DIR ActiveQt - PATHS ${QT_HEADERS_DIR}/ActiveQt - NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH - ) + if (QT_QAXCONTAINER_FOUND) + set(QT_MODULES ${QT_MODULES} QAxContainer) + # Set QT_AXCONTAINER_INCLUDE_DIR and QT_AXSERVER_INCLUDE_DIR + find_path(QT_QAXCONTAINER_INCLUDE_DIR ActiveQt + PATHS ${QT_HEADERS_DIR}/ActiveQt + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH + ) + endif() + if (QT_QAXSERVER_FOUND) + find_path(QT_QAXSERVER_INCLUDE_DIR ActiveQt + PATHS ${QT_HEADERS_DIR}/ActiveQt + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH + ) + endif() endif() # Set QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR @@ -1054,14 +1058,18 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) if(Q_WS_WIN) _QT4_ADJUST_LIB_VARS(qtmain) - _QT4_ADJUST_LIB_VARS(QAxServer) - set_property(TARGET Qt4::QAxServer PROPERTY - INTERFACE_QT4_NO_LINK_QTMAIN ON - ) - set_property(TARGET Qt4::QAxServer APPEND PROPERTY - COMPATIBLE_INTERFACE_BOOL QT4_NO_LINK_QTMAIN) + if(QT_QAXSERVER_FOUND) + _QT4_ADJUST_LIB_VARS(QAxServer) + set_property(TARGET Qt4::QAxServer PROPERTY + INTERFACE_QT4_NO_LINK_QTMAIN ON + ) + set_property(TARGET Qt4::QAxServer APPEND PROPERTY + COMPATIBLE_INTERFACE_BOOL QT4_NO_LINK_QTMAIN) + endif() - _QT4_ADJUST_LIB_VARS(QAxContainer) + if(QT_QAXCONTAINER_FOUND) + _QT4_ADJUST_LIB_VARS(QAxContainer) + endif() endif() # Only public dependencies are listed here. @@ -1083,7 +1091,9 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) _qt4_add_target_depends(QtWebKit Gui Network) _qt4_add_target_private_depends(Qt3Support Xml) - _qt4_add_target_private_depends(QtSvg Xml) + if(QT_VERSION VERSION_GREATER 4.6) + _qt4_add_target_private_depends(QtSvg Xml) + endif() _qt4_add_target_private_depends(QtDBus Xml) _qt4_add_target_private_depends(QtUiTools Xml Gui) _qt4_add_target_private_depends(QtHelp Sql Xml Network) @@ -1093,8 +1103,12 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) _qt4_add_target_private_depends(QtDeclarative XmlPatterns Svg Sql Gui) _qt4_add_target_private_depends(QtMultimedia Gui) _qt4_add_target_private_depends(QtOpenGL Gui) - _qt4_add_target_private_depends(QAxServer Gui) - _qt4_add_target_private_depends(QAxContainer Gui) + if(QT_QAXSERVER_FOUND) + _qt4_add_target_private_depends(QAxServer Gui) + endif() + if(QT_QAXCONTAINER_FOUND) + _qt4_add_target_private_depends(QAxContainer Gui) + endif() _qt4_add_target_private_depends(phonon Gui) if(QT_QTDBUS_FOUND) _qt4_add_target_private_depends(phonon DBus) diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 2e6b71e..f0652b9 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -30,6 +30,11 @@ set(CMAKE_SHARED_MODULE_SUFFIX ".so") set(CMAKE_MODULE_EXISTS 1) set(CMAKE_DL_LIBS "") +# Enable rpath support for 10.5 and greater where it is known to work. +if("${DARWIN_MAJOR_VERSION}" GREATER 8) + set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") +endif() + set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") @@ -207,12 +212,8 @@ if("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$") "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress") endif() -if(NOT XCODE) - # Enable shared library versioning. This flag is not actually referenced - # but the fact that the setting exists will cause the generators to support - # soname computation. - set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") -endif() +# Enable shared library versioning. +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") # Xcode does not support -isystem yet. if(XCODE) diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake index 251d57c..f6c8476 100644 --- a/Modules/Qt4Macros.cmake +++ b/Modules/Qt4Macros.cmake @@ -451,14 +451,22 @@ function(qt4_use_modules _target _link_type) endif() foreach(_module ${modules}) string(TOUPPER ${_module} _ucmodule) - if (NOT QT_QT${_ucmodule}_FOUND) - message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.") - endif() - if ("${_ucmodule}" STREQUAL "MAIN") - message(FATAL_ERROR "Can not use \"${_module}\" module with qt4_use_modules.") + set(_targetPrefix QT_QT${_ucmodule}) + if (_ucmodule STREQUAL QAXCONTAINER OR _ucmodule STREQUAL QAXSERVER) + if (NOT QT_Q${_ucmodule}_FOUND) + message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.") + endif() + set(_targetPrefix QT_Q${_ucmodule}) + else() + if (NOT QT_QT${_ucmodule}_FOUND) + message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.") + endif() + if ("${_ucmodule}" STREQUAL "MAIN") + message(FATAL_ERROR "Can not use \"${_module}\" module with qt4_use_modules.") + endif() endif() - target_link_libraries(${_target} ${link_type} ${QT_QT${_ucmodule}_LIBRARY}) - set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${QT_QT${_ucmodule}_INCLUDE_DIR} ${QT_HEADERS_DIR} ${QT_MKSPECS_DIR}/default) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${QT_QT${_ucmodule}_COMPILE_DEFINITIONS}) + target_link_libraries(${_target} ${link_type} ${${_targetPrefix}_LIBRARIES}) + set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${${_targetPrefix}_INCLUDE_DIR} ${QT_HEADERS_DIR} ${QT_MKSPECS_DIR}/default) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${${_targetPrefix}_COMPILE_DEFINITIONS}) endforeach() endfunction() diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index e686c1d..9c23127 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -6,6 +6,10 @@ # add_jar(target_name # [SOURCES] source1 [source2 ...] [resource1 ...] # [INCLUDE_JARS jar1 [jar2 ...]] +# [ENTRY_POINT entry] +# [VERSION version] +# [OUTPUT_NAME name] +# [OUTPUT_DIR dir] # ) # # This command creates a <target_name>.jar. It compiles the given source files @@ -17,6 +21,9 @@ # listed as sources are ignored (as they have been since the first version of # this module). # +# The default OUTPUT_DIR can also be changed by setting the variable +# CMAKE_JAVA_TARGET_OUTPUT_DIR. +# # Additional instructions: # To add compile flags to the target you can set these flags with # the following variable: @@ -30,32 +37,30 @@ # # To use a different output name for the target you can set it with: # -# set(CMAKE_JAVA_TARGET_OUTPUT_NAME shibboleet.jar) -# add_jar(foobar foobar.java) +# add_jar(foobar foobar.java OUTPUT_NAME shibboleet.jar) # # To use a different output directory than CMAKE_CURRENT_BINARY_DIR # you can set it with: # -# set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) +# add_jar(foobar foobar.java OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) # -# To define an entry point in your jar you can set it with: +# To define an entry point in your jar you can set it with the ENTRY_POINT +# named argument: # -# set(CMAKE_JAVA_JAR_ENTRY_POINT com/examples/MyProject/Main) +# add_jar(example ENTRY_POINT com/examples/MyProject/Main) # # To add a VERSION to the target output name you can set it using -# CMAKE_JAVA_TARGET_VERSION. This will create a jar file with the name -# shibboleet-1.0.0.jar and will create a symlink shibboleet.jar +# the VERSION named argument to add_jar. This will create a jar file with the +# name shibboleet-1.0.0.jar and will create a symlink shibboleet.jar # pointing to the jar with the version information. # -# set(CMAKE_JAVA_TARGET_VERSION 1.2.0) -# add_jar(shibboleet shibbotleet.java) +# add_jar(shibboleet shibbotleet.java VERSION 1.2.0) # # If the target is a JNI library, utilize the following commands to # create a JNI symbolic link: # # set(CMAKE_JNI_TARGET TRUE) -# set(CMAKE_JAVA_TARGET_VERSION 1.2.0) -# add_jar(shibboleet shibbotleet.java) +# add_jar(shibboleet shibbotleet.java VERSION 1.2.0) # install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet) # install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR}) # @@ -216,23 +221,43 @@ set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake) function(add_jar _TARGET_NAME) - cmake_parse_arguments(_add_jar "" "" "SOURCES;INCLUDE_JARS" ${ARGN}) + if(DEFINED CMAKE_JAVA_TARGET_VERSION) + set(_add_jar_VERSION "${CMAKE_JAVA_TARGET_VERSION}") + endif() + if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) + set(_add_jar_OUTPUT_DIR "${CMAKE_JAVA_TARGET_OUTPUT_DIR}") + endif() + if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME) + set(_add_jar_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}") + # reset + set(CMAKE_JAVA_TARGET_OUTPUT_NAME) + endif() + if(DEFINED CMAKE_JAVA_JAR_ENTRY_POINT) + set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}") + endif() + + cmake_parse_arguments(_add_jar + "" + "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT" + "SOURCES;INCLUDE_JARS" + ${ARGN} + ) set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS}) - if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) - set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) + if (NOT DEFINED _add_jar_OUTPUT_DIR) + set(_add_jar_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() - if (CMAKE_JAVA_JAR_ENTRY_POINT) - set(_ENTRY_POINT_OPTION e) - set(_ENTRY_POINT_VALUE ${CMAKE_JAVA_JAR_ENTRY_POINT}) + if (_add_jar_ENTRY_POINT) + set(_ENTRY_POINT_OPTION e) + set(_ENTRY_POINT_VALUE ${_add_jar_ENTRY_POINT}) endif () if (LIBRARY_OUTPUT_PATH) set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}) else () - set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR}) + set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${_add_jar_OUTPUT_DIR}) endif () set(CMAKE_JAVA_INCLUDE_PATH @@ -252,20 +277,18 @@ function(add_jar _TARGET_NAME) set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}") endforeach() - set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") + set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${_add_jar_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar") - if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION) - set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") - set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") - elseif (CMAKE_JAVA_TARGET_VERSION) - set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") + if (_add_jar_OUTPUT_NAME AND _add_jar_VERSION) + set(_JAVA_TARGET_OUTPUT_NAME "${_add_jar_OUTPUT_NAME}-${_add_jar_VERSION}.jar") + set(_JAVA_TARGET_OUTPUT_LINK "${_add_jar_OUTPUT_NAME}.jar") + elseif (_add_jar_VERSION) + set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${_add_jar_VERSION}.jar") set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar") - elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME) - set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") + elseif (_add_jar_OUTPUT_NAME) + set(_JAVA_TARGET_OUTPUT_NAME "${_add_jar_OUTPUT_NAME}.jar") endif () - # reset - set(CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_JAVA_CLASS_FILES) set(_JAVA_COMPILE_FILES) @@ -279,7 +302,7 @@ function(add_jar _TARGET_NAME) get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE) if (_JAVA_EXT MATCHES ".java") - file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR} ${_JAVA_FULL}) + file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${_add_jar_OUTPUT_DIR} ${_JAVA_FULL}) file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL}) string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN) string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN) @@ -364,7 +387,7 @@ function(add_jar _TARGET_NAME) # create the jar file set(_JAVA_JAR_OUTPUT_PATH - ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) + ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) if (CMAKE_JNI_TARGET) add_custom_command( OUTPUT ${_JAVA_JAR_OUTPUT_PATH} @@ -372,12 +395,12 @@ function(add_jar _TARGET_NAME) -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} - -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} + -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} COMMAND ${CMAKE_COMMAND} - -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} + -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} @@ -392,7 +415,7 @@ function(add_jar _TARGET_NAME) -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} - -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} + -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} @@ -420,7 +443,7 @@ function(add_jar _TARGET_NAME) PROPERTY INSTALL_FILES ${_JAVA_JAR_OUTPUT_PATH} - ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} + ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) if (CMAKE_JNI_TARGET) @@ -429,7 +452,7 @@ function(add_jar _TARGET_NAME) ${_TARGET_NAME} PROPERTY JNI_SYMLINK - ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} + ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) endif () endif () diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f12d928..1230403 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 11) -set(CMake_VERSION_TWEAK 20130524) +set(CMake_VERSION_TWEAK 20130603) #set(CMake_VERSION_RC 1) diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx index e3a2ad4..1b7a751 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands.cxx @@ -52,6 +52,7 @@ #include "cmFindProgramCommand.cxx" #include "cmForEachCommand.cxx" #include "cmFunctionCommand.cxx" +#include "cmGeneratorExpressionEvaluationFile.cxx" #include "cmGetCMakePropertyCommand.cxx" #include "cmGetDirectoryPropertyCommand.cxx" #include "cmGetFilenameComponentCommand.cxx" diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 0158508..02495c4 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1730,6 +1730,17 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget* target) { + // Ignore targets on Apple where install_name is not @rpath. + // The dependenty library can be found with other means such as + // @loader_path or full paths. + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + if(!target->HasMacOSXRpath(this->Config)) + { + return; + } + } + // Libraries with unknown type must be handled using just the file // on disk. if(target->GetType() == cmTarget::UNKNOWN_LIBRARY) @@ -1762,25 +1773,60 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath) { // Get the name of the library from the file name. + bool is_shared_library = false; std::string file = cmSystemTools::GetFilenameName(fullPath); - if(!this->ExtractSharedLibraryName.find(file.c_str())) + + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + // Check that @rpath is part of the install name. + // If it isn't, return. + std::string soname; + if(!cmSystemTools::GuessLibraryInstallName(fullPath, soname)) + { + return; + } + + if(soname.find("@rpath") == std::string::npos) + { + return; + } + } + + is_shared_library = this->ExtractSharedLibraryName.find(file.c_str()); + + if(!is_shared_library) { // On some platforms (AIX) a shared library may look static. if(this->ArchivesMayBeShared) { - if(!this->ExtractStaticLibraryName.find(file.c_str())) + if(this->ExtractStaticLibraryName.find(file.c_str())) { - // This is not the name of a shared library or archive. - return; + // This is the name of a shared library or archive. + is_shared_library = true; } } - else + } + + // It could be an Apple framework + if(!is_shared_library) + { + if(fullPath.find(".framework") != std::string::npos) { - // This is not the name of a shared library. - return; + cmsys::RegularExpression splitFramework; + splitFramework.compile("^(.*)/(.*).framework/.*/(.*)$"); + if(splitFramework.find(fullPath) && + (splitFramework.match(2) == splitFramework.match(3))) + { + is_shared_library = true; + } } } + if(!is_shared_library) + { + return; + } + // Include this library in the runtime path ordering. this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath); if(this->LinkWithRuntimePath) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 9f38b25..85e49a9 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -111,7 +111,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) ++i) { extraArgs++; - libsToLink += argv[i] + " "; + libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" "; cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str()); if (!tgt) { diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index e1c26c6..39184fb 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -143,7 +143,7 @@ cmExportBuildFileGenerator std::string prop = "IMPORTED_LOCATION"; prop += suffix; std::string value; - if(target->IsFrameworkOnApple() || target->IsAppBundleOnApple()) + if(target->IsAppBundleOnApple()) { value = target->GetFullPath(config, false); } @@ -211,3 +211,19 @@ cmExportBuildFileGenerator << "consider using the APPEND option with multiple separate calls."; this->ExportCommand->ErrorMessage = e.str(); } + +std::string +cmExportBuildFileGenerator::InstallNameDir(cmTarget* target, + const std::string& config) +{ + std::string install_name_dir; + + cmMakefile* mf = target->GetMakefile(); + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + install_name_dir = + target->GetInstallNameDirForBuildTree(config.c_str()); + } + + return install_name_dir; +} diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 5e1be16..3ffdf8b 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -61,6 +61,8 @@ protected: cmTarget* target, ImportPropertyMap& properties); + std::string InstallNameDir(cmTarget* target, const std::string& config); + std::vector<cmTarget*> const* Exports; cmExportCommand* ExportCommand; }; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index a6ccbd5..6bef017 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -624,8 +624,12 @@ cmExportFileGenerator std::string value; if(target->HasSOName(config)) { + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + value = this->InstallNameDir(target, config); + } prop = "IMPORTED_SONAME"; - value = target->GetSOName(config); + value += target->GetSOName(config); } else { diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 9f958a2..ed2d93b 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -159,6 +159,9 @@ private: std::vector<std::string> &missingTargets); virtual void ReplaceInstallPrefix(std::string &input); + + virtual std::string InstallNameDir(cmTarget* target, + const std::string& config) = 0; }; #endif diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 55081a7..dfcf472 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -351,13 +351,7 @@ cmExportInstallFileGenerator prop += suffix; // Append the installed file name. - if(target->IsFrameworkOnApple()) - { - value += itgen->GetInstallFilename(target, config); - value += ".framework/"; - value += itgen->GetInstallFilename(target, config); - } - else if(target->IsCFBundleOnApple()) + if(target->IsCFBundleOnApple()) { const char *ext = target->GetProperty("BUNDLE_EXTENSION"); if (!ext) @@ -497,3 +491,19 @@ cmExportInstallFileGenerator } cmSystemTools::Error(e.str().c_str()); } + +std::string +cmExportInstallFileGenerator::InstallNameDir(cmTarget* target, + const std::string&) +{ + std::string install_name_dir; + + cmMakefile* mf = target->GetMakefile(); + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + install_name_dir = + target->GetInstallNameDirForInstallTree(); + } + + return install_name_dir; +} diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 20dd57a..7c634a4 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -85,6 +85,8 @@ protected: void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen); + std::string InstallNameDir(cmTarget* target, const std::string& config); + cmInstallExportGenerator* IEGen; std::string ImportPrefix; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 75f2651..948508b 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -112,3 +112,18 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target, } } } +std::string +cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target, + const std::string& config) +{ + std::string install_name_dir; + + cmMakefile* mf = target->GetMakefile(); + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + install_name_dir = + target->GetInstallNameDirForBuildTree(config.c_str()); + } + + return install_name_dir; +} diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index ed393ab..91b4a61 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -43,6 +43,8 @@ protected: ImportPropertyMap& properties, std::set<cmTarget*> &emitted); + std::string InstallNameDir(cmTarget* target, + const std::string& config); private: std::string FindTargets(const char *prop, cmTarget *tgt, std::set<cmTarget*> &emitted); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 2e6f3e0..e72e756 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -167,6 +167,10 @@ bool cmFileCommand { return this->HandleTimestampCommand(args); } + else if ( subCommand == "GENERATE" ) + { + return this->HandleGenerateCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -3250,6 +3254,80 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) } //---------------------------------------------------------------------------- +void cmFileCommand::AddEvaluationFile(const std::string &inputName, + const std::string &outputExpr, + const std::string &condition, + bool inputIsContent + ) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + + cmGeneratorExpression outputGe(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputCge + = outputGe.Parse(outputExpr); + + cmGeneratorExpression conditionGe(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge + = conditionGe.Parse(condition); + + this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->AddEvaluationFile(inputName, + outputCge, + this->Makefile, + conditionCge, + inputIsContent); +} + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleGenerateCommand( + std::vector<std::string> const& args) +{ + if (args.size() < 5) + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + if (args[1] != "OUTPUT") + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + std::string condition; + if (args.size() > 5) + { + if (args[5] != "CONDITION") + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + if (args.size() != 7) + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + condition = args[6]; + if (condition.empty()) + { + this->SetError("CONDITION of sub-command GENERATE must not be empty if " + "specified."); + return false; + } + } + std::string output = args[2]; + const bool inputIsContent = args[3] != "INPUT"; + if (inputIsContent && args[3] != "CONTENT") + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + std::string input = args[4]; + + this->AddEvaluationFile(input, output, condition, inputIsContent); + return true; +} + +//---------------------------------------------------------------------------- bool cmFileCommand::HandleTimestampCommand( std::vector<std::string> const& args) { diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 5973fa7..586fee2 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -88,6 +88,9 @@ public: " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" " file(TIMESTAMP filename variable [<format string>] [UTC])\n" + " file(GENERATE OUTPUT output_file\n" + " <INPUT input_file|CONTENT input_content>\n" + " CONDITION expression)\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist. (If the file is a build input, use " @@ -231,6 +234,15 @@ public: "it prints status messages, and NO_SOURCE_PERMISSIONS is default. " "Installation scripts generated by the install() command use this " "signature (with some undocumented options for internal use)." + "\n" + "GENERATE will write an <output_file> with content from an " + "<input_file>, or from <input_content>. The output is generated " + "conditionally based on the content of the <condition>. The file is " + "written at CMake generate-time and the input may contain generator " + "expressions. The <condition>, <output_file> and <input_file> may " + "also contain generator expressions. The <condition> must evaluate to " + "either '0' or '1'. The <output_file> must evaluate to a unique name " + "among all configurations and among all invocations of file(GENERATE)." // Undocumented INSTALL options: // - RENAME <name> // - OPTIONAL @@ -269,6 +281,13 @@ protected: bool HandleUploadCommand(std::vector<std::string> const& args); bool HandleTimestampCommand(std::vector<std::string> const& args); + bool HandleGenerateCommand(std::vector<std::string> const& args); + +private: + void AddEvaluationFile(const std::string &inputName, + const std::string &outputExpr, + const std::string &condition, + bool inputIsContent); }; diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx new file mode 100644 index 0000000..cab99ed --- /dev/null +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -0,0 +1,151 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmGeneratorExpressionEvaluationFile.h" + +#include "cmMakefile.h" + +#include <assert.h> + +//---------------------------------------------------------------------------- +cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( + const std::string &input, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent) + : Input(input), + OutputFileExpr(outputFileExpr), + Makefile(makefile), + Condition(condition), + InputIsContent(inputIsContent) +{ +} + +//---------------------------------------------------------------------------- +void cmGeneratorExpressionEvaluationFile::Generate(const char *config, + cmCompiledGeneratorExpression* inputExpression, + std::map<std::string, std::string> &outputFiles) +{ + std::string rawCondition = this->Condition->GetInput(); + if (!rawCondition.empty()) + { + std::string condResult = this->Condition->Evaluate(this->Makefile, config); + if (condResult == "0") + { + return; + } + if (condResult != "1") + { + cmOStringStream e; + e << "Evaluation file condition \"" << rawCondition << "\" did " + "not evaluate to valid content. Got \"" << condResult << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + } + + const std::string outputFileName + = this->OutputFileExpr->Evaluate(this->Makefile, config); + const std::string outputContent + = inputExpression->Evaluate(this->Makefile, config); + + std::map<std::string, std::string>::iterator it + = outputFiles.find(outputFileName); + + if(it != outputFiles.end()) + { + if (it->second == outputContent) + { + return; + } + cmOStringStream e; + e << "Evaluation file to be written multiple times for different " + "configurations with different content:\n " << outputFileName; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + + this->Files.push_back(outputFileName); + outputFiles[outputFileName] = outputContent; + + std::ofstream fout(outputFileName.c_str()); + + if(!fout) + { + cmOStringStream e; + e << "Evaluation file \"" << outputFileName << "\" cannot be written."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + + fout << outputContent; + + fout.close(); +} + +//---------------------------------------------------------------------------- +void cmGeneratorExpressionEvaluationFile::Generate() +{ + std::string inputContent; + if (this->InputIsContent) + { + inputContent = this->Input; + } + else + { + std::ifstream fin(this->Input.c_str()); + if(!fin) + { + cmOStringStream e; + e << "Evaluation file \"" << this->Input << "\" cannot be read."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + + std::string line; + std::string sep; + while(cmSystemTools::GetLineFromStream(fin, line)) + { + inputContent += sep + line; + sep = "\n"; + } + inputContent += sep; + } + + cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace(); + cmGeneratorExpression contentGE(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> inputExpression + = contentGE.Parse(inputContent); + + std::map<std::string, std::string> outputFiles; + + std::vector<std::string> allConfigs; + this->Makefile->GetConfigurations(allConfigs); + + if (allConfigs.empty()) + { + this->Generate(0, inputExpression.get(), outputFiles); + } + else + { + for(std::vector<std::string>::const_iterator li = allConfigs.begin(); + li != allConfigs.end(); ++li) + { + this->Generate(li->c_str(), inputExpression.get(), outputFiles); + if(cmSystemTools::GetFatalErrorOccured()) + { + return; + } + } + } +} diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h new file mode 100644 index 0000000..20ee5cb --- /dev/null +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -0,0 +1,48 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGeneratorExpressionEvaluationFile_h +#define cmGeneratorExpressionEvaluationFile_h + +#include "cmStandardIncludes.h" +#include <cmsys/auto_ptr.hxx> + +#include "cmGeneratorExpression.h" + +//---------------------------------------------------------------------------- +class cmGeneratorExpressionEvaluationFile +{ +public: + cmGeneratorExpressionEvaluationFile(const std::string &input, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent); + + void Generate(); + + std::vector<std::string> GetFiles() const { return this->Files; } + +private: + void Generate(const char *config, + cmCompiledGeneratorExpression* inputExpression, + std::map<std::string, std::string> &outputFiles); + +private: + const std::string Input; + const cmsys::auto_ptr<cmCompiledGeneratorExpression> OutputFileExpr; + cmMakefile *Makefile; + const cmsys::auto_ptr<cmCompiledGeneratorExpression> Condition; + std::vector<std::string> Files; + const bool InputIsContent; +}; + +#endif diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 93d881e..df52368 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -399,6 +399,59 @@ static const char* targetPropertyTransitiveWhitelist[] = { , "INTERFACE_COMPILE_DEFINITIONS" }; +std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, + cmTarget *target, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string &interfacePropertyName) +{ + cmGeneratorExpression ge(context->Backtrace); + + std::string sep; + std::string depString; + for (std::vector<std::string>::const_iterator + it = libraries.begin(); + it != libraries.end(); ++it) + { + if (*it == target->GetName()) + { + // Broken code can have a target in its own link interface. + // Don't follow such link interface entries so as not to create a + // self-referencing loop. + continue; + } + if (context->Makefile->FindTargetToUse(it->c_str())) + { + depString += + sep + "$<TARGET_PROPERTY:" + *it + "," + interfacePropertyName + ">"; + sep = ";"; + } + } + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString); + std::string linkedTargetsContent = cge->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + dagChecker); + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + return linkedTargetsContent; +} + +//---------------------------------------------------------------------------- +struct TransitiveWhitelistCompare +{ + explicit TransitiveWhitelistCompare(const std::string &needle) + : Needle(needle) {} + bool operator() (const char *item) + { return strcmp(item, this->Needle.c_str()) == 0; } +private: + std::string Needle; +}; + //---------------------------------------------------------------------------- static const struct TargetPropertyNode : public cmGeneratorExpressionNode { @@ -571,49 +624,36 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; } - if (interfacePropertyName == "INTERFACE_INCLUDE_DIRECTORIES" - || interfacePropertyName == "INTERFACE_COMPILE_DEFINITIONS") + const char **transBegin = targetPropertyTransitiveWhitelist; + const char **transEnd = targetPropertyTransitiveWhitelist + + (sizeof(targetPropertyTransitiveWhitelist) / + sizeof(*targetPropertyTransitiveWhitelist)); + if (std::find_if(transBegin, transEnd, + TransitiveWhitelistCompare(propertyName)) != transEnd) { const cmTarget::LinkInterface *iface = target->GetLinkInterface( context->Config, context->HeadTarget); if(iface) { - cmGeneratorExpression ge(context->Backtrace); - - std::string sep; - std::string depString; - for (std::vector<std::string>::const_iterator - it = iface->Libraries.begin(); - it != iface->Libraries.end(); ++it) - { - if (*it == target->GetName()) - { - // Broken code can have a target in its own link interface. - // Don't follow such link interface entries so as not to create a - // self-referencing loop. - continue; - } - if (context->Makefile->FindTargetToUse(it->c_str())) - { - depString += - sep + "$<TARGET_PROPERTY:" + *it + "," - + interfacePropertyName + ">"; - sep = ";"; - } - } - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(depString); - linkedTargetsContent = cge->Evaluate(context->Makefile, - context->Config, - context->Quiet, - context->HeadTarget, - target, - &dagChecker); - if (cge->GetHadContextSensitiveCondition()) - { - context->HadContextSensitiveCondition = true; - } + linkedTargetsContent = + getLinkedTargetsContent(iface->Libraries, target, + context, &dagChecker, + interfacePropertyName); + } + } + else if (std::find_if(transBegin, transEnd, + TransitiveWhitelistCompare(interfacePropertyName)) != transEnd) + { + const cmTarget::LinkImplementation *impl = target->GetLinkImplementation( + context->Config, + context->HeadTarget); + if(impl) + { + linkedTargetsContent = + getLinkedTargetsContent(impl->Libraries, target, + context, &dagChecker, + interfacePropertyName); } } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index f38ef65..3496823 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -26,6 +26,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionEvaluationFile.h" #include <cmsys/Directory.hxx> @@ -69,6 +70,13 @@ cmGlobalGenerator::~cmGlobalGenerator() { delete this->LocalGenerators[i]; } + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = this->EvaluationFiles.begin(); + li != this->EvaluationFiles.end(); + ++li) + { + delete *li; + } this->LocalGenerators.clear(); if (this->ExtraGenerator) @@ -981,6 +989,8 @@ void cmGlobalGenerator::Generate() // Create per-target generator information. this->CreateGeneratorTargets(); + this->ProcessEvaluationFiles(); + // Compute the inter-target dependencies. if(!this->ComputeTargetDepends()) { @@ -2560,3 +2570,44 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) { } return result; } + +//---------------------------------------------------------------------------- +void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent) +{ + this->EvaluationFiles.push_back( + new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr, + makefile, condition, + inputIsContent)); +} + +//---------------------------------------------------------------------------- +void cmGlobalGenerator::ProcessEvaluationFiles() +{ + std::set<std::string> generatedFiles; + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = this->EvaluationFiles.begin(); + li != this->EvaluationFiles.end(); + ++li) + { + (*li)->Generate(); + if (cmSystemTools::GetFatalErrorOccured()) + { + return; + } + std::vector<std::string> files = (*li)->GetFiles(); + for(std::vector<std::string>::const_iterator fi = files.begin(); + fi != files.end(); ++fi) + { + if (!generatedFiles.insert(*fi).second) + { + cmSystemTools::Error("File to be generated by multiple different " + "commands: ", fi->c_str()); + return; + } + } + } +} diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 9427434..2fcdc43 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -20,9 +20,11 @@ #include "cmSystemTools.h" // for cmSystemTools::OutputOption #include "cmExportSetMap.h" // For cmExportSetMap #include "cmGeneratorTarget.h" +#include "cmGeneratorExpression.h" class cmake; class cmGeneratorTarget; +class cmGeneratorExpressionEvaluationFile; class cmMakefile; class cmLocalGenerator; class cmExternalMakefileProjectGenerator; @@ -279,6 +281,14 @@ public: static std::string EscapeJSON(const std::string& s); + void AddEvaluationFile(const std::string &inputFile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent); + + void ProcessEvaluationFiles(); + protected: typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend @@ -338,6 +348,7 @@ protected: // All targets in the entire project. std::map<cmStdString,cmTarget *> TotalTargets; std::map<cmStdString,cmTarget *> ImportedTargets; + std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; virtual const char* GetPredefinedTargetsFolder(); virtual bool UseFolderProperty(); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index bb1e792..d782a06 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1321,8 +1321,40 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, = cmtarget.GetPreBuildCommands(); std::vector<cmCustomCommand> const & prelink = cmtarget.GetPreLinkCommands(); - std::vector<cmCustomCommand> const & postbuild + std::vector<cmCustomCommand> postbuild = cmtarget.GetPostBuildCommands(); + + if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY && + !cmtarget.IsFrameworkOnApple()) + { + cmCustomCommandLines cmd; + cmd.resize(1); + cmd[0].push_back(this->CurrentMakefile->GetDefinition("CMAKE_COMMAND")); + cmd[0].push_back("-E"); + cmd[0].push_back("cmake_symlink_library"); + std::string str_file = "$<TARGET_FILE:"; + str_file += cmtarget.GetName(); + str_file += ">"; + std::string str_so_file = "$<TARGET_SONAME_FILE:"; + str_so_file += cmtarget.GetName(); + str_so_file += ">"; + std::string str_link_file = "$<TARGET_LINKER_FILE:"; + str_link_file += cmtarget.GetName(); + str_link_file += ">"; + cmd[0].push_back(str_file); + cmd[0].push_back(str_so_file); + cmd[0].push_back(str_link_file); + + cmCustomCommand command(this->CurrentMakefile, + std::vector<std::string>(), + std::vector<std::string>(), + cmd, + "Creating symlinks", + ""); + + postbuild.push_back(command); + } + std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles(); // add all the sources std::vector<cmCustomCommand> commands; @@ -1795,9 +1827,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string pnprefix; std::string pnbase; std::string pnsuffix; - target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); + const char* version = target.GetProperty("VERSION"); + const char* soversion = target.GetProperty("SOVERSION"); + if(!target.HasSOName(configName) || target.IsFrameworkOnApple()) + { + version = 0; + soversion = 0; + } + if(version && !soversion) + { + soversion = version; + } + if(!version && soversion) + { + version = soversion; + } + + std::string realName = pnbase; + std::string soName = pnbase; + if(version && soversion) + { + realName += "."; + realName += version; + soName += "."; + soName += soversion; + } + // Set attributes to specify the proper name for the target. std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory(); if(target.GetType() == cmTarget::STATIC_LIBRARY || @@ -1821,6 +1878,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, pndir = target.GetDirectory(configName); } + if(target.IsFrameworkOnApple()) + { + pnprefix = ""; + } + buildSettings->AddAttribute("EXECUTABLE_PREFIX", this->CreateString(pnprefix.c_str())); buildSettings->AddAttribute("EXECUTABLE_SUFFIX", @@ -1850,7 +1912,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Store the product name for all target types. buildSettings->AddAttribute("PRODUCT_NAME", - this->CreateString(pnbase.c_str())); + this->CreateString(realName.c_str())); buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir.c_str())); @@ -1928,9 +1990,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { if(target.GetPropertyAsBool("FRAMEWORK")) { - std::string version = target.GetFrameworkVersion(); + std::string fw_version = target.GetFrameworkVersion(); buildSettings->AddAttribute("FRAMEWORK_VERSION", - this->CreateString(version.c_str())); + this->CreateString(fw_version.c_str())); std::string plist = this->ComputeInfoPListLocation(target); // Xcode will create the final version of Info.plist at build time, @@ -2154,25 +2216,55 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, if(target.GetType() == cmTarget::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = target.GetInstallNameDirForBuildTree(configName, true); - if(install_name_dir.empty()) - { - // Xcode will not pass the -install_name option at all if INSTALL_PATH - // is not given or is empty. We must explicitly put the flag in the - // link flags to create an install_name with just the library soname. - extraLinkOptions += " -install_name "; - extraLinkOptions += target.GetFullName(configName); - } - else + install_name_dir = target.GetInstallNameDirForBuildTree(configName); + // Xcode doesn't create the correct install_name in some cases. + // That is, if the INSTALL_PATH is empty, or if we have versioning + // of dylib libraries, we want to specify the install_name. + // This is done by adding a link flag to create an install_name + // with just the library soname. + std::string install_name; + if(!install_name_dir.empty()) { // Convert to a path for the native build tool. cmSystemTools::ConvertToUnixSlashes(install_name_dir); - // do not escape spaces on this since it is only a single path + install_name += install_name_dir; + install_name += "/"; + } + install_name += target.GetSOName(configName); + + if((realName != soName) || install_name_dir.empty()) + { + install_name_dir = ""; + extraLinkOptions += " -install_name "; + extraLinkOptions += XCodeEscapePath(install_name.c_str()); } } buildSettings->AddAttribute("INSTALL_PATH", this->CreateString(install_name_dir.c_str())); + // Create the LD_RUNPATH_SEARCH_PATHS + cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + if(pcli) + { + std::string search_paths; + std::vector<std::string> runtimeDirs; + pcli->GetRPath(runtimeDirs, false); + for(std::vector<std::string>::const_iterator i = runtimeDirs.begin(); + i != runtimeDirs.end(); ++i) + { + if(!search_paths.empty()) + { + search_paths += " "; + } + search_paths += this->XCodeEscapePath((*i).c_str()); + } + if(!search_paths.empty()) + { + buildSettings->AddAttribute("LD_RUNPATH_SEARCH_PATHS", + this->CreateString(search_paths.c_str())); + } + } + buildSettings->AddAttribute("OTHER_LDFLAGS", this->CreateString(extraLinkOptions.c_str())); buildSettings->AddAttribute("OTHER_REZFLAGS", diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 5f9b658..ed01210 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -198,14 +198,12 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, // Install the whole framework directory. type = cmInstallType_DIRECTORY; literal_args += " USE_SOURCE_PERMISSIONS"; - std::string from1 = fromDirConfig + targetName + ".framework"; + + std::string from1 = fromDirConfig + targetName; + from1 = cmSystemTools::GetFilenamePath(from1); // Tweaks apply to the binary inside the bundle. - std::string to1 = toDir + targetName; - to1 += ".framework/Versions/"; - to1 += this->Target->GetFrameworkVersion(); - to1 += "/"; - to1 += targetName; + std::string to1 = toDir + targetNameReal; filesFrom.push_back(from1); filesTo.push_back(to1); @@ -528,7 +526,7 @@ cmInstallTargetGenerator // components of the install_name field then we need to create a // mapping to be applied after installation. std::string for_build = tgt->GetInstallNameDirForBuildTree(config); - std::string for_install = tgt->GetInstallNameDirForInstallTree(config); + std::string for_install = tgt->GetInstallNameDirForInstallTree(); if(for_build != for_install) { // The directory portions differ. Append the filename to @@ -555,7 +553,7 @@ cmInstallTargetGenerator std::string for_build = this->Target->GetInstallNameDirForBuildTree(config); std::string for_install = - this->Target->GetInstallNameDirForInstallTree(config); + this->Target->GetInstallNameDirForInstallTree(); if(this->Target->IsFrameworkOnApple() && for_install.empty()) { @@ -608,6 +606,12 @@ cmInstallTargetGenerator return; } + // Skip if on Apple + if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + return; + } + // Get the link information for this target. // It can provide the RPATH. cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); @@ -647,30 +651,62 @@ cmInstallTargetGenerator return; } - // Construct the original rpath string to be replaced. - std::string oldRpath = cli->GetRPathString(false); - - // Get the install RPATH from the link information. - std::string newRpath = cli->GetChrpathString(); - - // Skip the rule if the paths are identical - if(oldRpath == newRpath) + if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - return; - } + // If using install_name_tool, set up the rules to modify the rpaths. + std::string installNameTool = + this->Target->GetMakefile()-> + GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); + + std::vector<std::string> oldRuntimeDirs, newRuntimeDirs; + cli->GetRPath(oldRuntimeDirs, false); + cli->GetRPath(newRuntimeDirs, true); + + // Note: These are separate commands to avoid install_name_tool + // corruption on 10.6. + for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin(); + i != oldRuntimeDirs.end(); ++i) + { + os << indent << "execute_process(COMMAND " << installNameTool << "\n"; + os << indent << " -delete_rpath \"" << *i << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } - // Write a rule to run chrpath to set the install-tree RPATH - if(newRpath.empty()) - { - os << indent << "FILE(RPATH_REMOVE\n" - << indent << " FILE \"" << toDestDirPath << "\")\n"; + for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin(); + i != newRuntimeDirs.end(); ++i) + { + os << indent << "execute_process(COMMAND " << installNameTool << "\n"; + os << indent << " -add_rpath \"" << *i << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } } else { - os << indent << "FILE(RPATH_CHANGE\n" - << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " OLD_RPATH \"" << oldRpath << "\"\n" - << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + // Construct the original rpath string to be replaced. + std::string oldRpath = cli->GetRPathString(false); + + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + + // Skip the rule if the paths are identical + if(oldRpath == newRpath) + { + return; + } + + // Write a rule to run chrpath to set the install-tree RPATH + 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/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index b7a454b..e4219a9 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -30,11 +30,8 @@ cmMakefileExecutableTargetGenerator this->TargetNamePDB, this->ConfigName); this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, - this->TargetNameOut, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - this->MacContentDirectory = - this->OSXBundleGenerator->GetMacContentDirectory(); } //---------------------------------------------------------------------------- @@ -103,11 +100,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct the full path version of the names. std::string outpath = this->Target->GetDirectory(this->ConfigName); - outpath += "/"; if(this->Target->IsAppBundleOnApple()) { this->OSXBundleGenerator->CreateAppBundle(targetName, outpath); } + outpath += "/"; std::string outpathImp; if(relink) { diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 5b4e4d7..3edaa44 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -32,11 +32,8 @@ cmMakefileLibraryTargetGenerator this->TargetNameImport, this->TargetNamePDB, this->ConfigName); this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, - this->TargetNameOut, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - this->MacContentDirectory = - this->OSXBundleGenerator->GetMacContentDirectory(); } //---------------------------------------------------------------------------- @@ -292,14 +289,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules std::string outpathImp; if(this->Target->IsFrameworkOnApple()) { - outpath = this->MacContentDirectory; - this->OSXBundleGenerator->CreateFramework(targetName); + outpath = this->Target->GetDirectory(this->ConfigName); + this->OSXBundleGenerator->CreateFramework(targetName, outpath); + outpath += "/"; } else if(this->Target->IsCFBundleOnApple()) { outpath = this->Target->GetDirectory(this->ConfigName); - outpath += "/"; this->OSXBundleGenerator->CreateCFBundle(targetName, outpath); + outpath += "/"; } else if(relink) { @@ -727,7 +725,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules commands1.clear(); // Add a rule to create necessary symlinks for the library. - if(targetOutPath != targetOutPathReal) + // Frameworks are handled by cmOSXBundleGenerator. + if(targetOutPath != targetOutPathReal && !this->Target->IsFrameworkOnApple()) { std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library "; symlink += targetOutPathReal; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4220ae1..6fc88d6 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -357,7 +357,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator() (cmSourceFile& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(this->Generator->MacContentDirectory.empty()) + if(!this->Generator->GetTarget()->IsBundleOnApple()) { return; } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 2798e54..f7a1e2e 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -233,7 +233,6 @@ protected: std::string TargetNamePDB; // Mac OS X content info. - std::string MacContentDirectory; std::set<cmStdString> MacContentFolders; cmOSXBundleGenerator* OSXBundleGenerator; MacOSXContentGeneratorType* MacOSXContentGenerator; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 4456aa7..1fa4e95 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -25,11 +25,8 @@ cmMakefileUtilityTargetGenerator { this->CustomCommandDriver = OnUtility; this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, - this->TargetNameOut, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - this->MacContentDirectory = - this->OSXBundleGenerator->GetMacContentDirectory(); } //---------------------------------------------------------------------------- diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index e5f3570..1bdaf90 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -61,7 +61,6 @@ cmNinjaNormalTargetGenerator(cmTarget* target) } this->OSXBundleGenerator = new cmOSXBundleGenerator(target, - this->TargetNameOut, this->GetConfigName()); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -383,24 +382,32 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() if (this->GetTarget()->IsAppBundleOnApple()) { // Create the app bundle - std::string outpath; + std::string outpath = + this->GetTarget()->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath); // Calculate the output path - targetOutput = outpath + this->TargetNameOut; + targetOutput = outpath; + targetOutput += "/"; + targetOutput += this->TargetNameOut; targetOutput = this->ConvertToNinjaPath(targetOutput.c_str()); - targetOutputReal = outpath + this->TargetNameReal; + targetOutputReal = outpath; + targetOutputReal += "/"; + targetOutputReal += this->TargetNameReal; targetOutputReal = this->ConvertToNinjaPath(targetOutputReal.c_str()); } else if (this->GetTarget()->IsFrameworkOnApple()) { // Create the library framework. - this->OSXBundleGenerator->CreateFramework(this->TargetNameOut); + std::string outpath = + this->GetTarget()->GetDirectory(this->GetConfigName()); + this->OSXBundleGenerator->CreateFramework(this->TargetNameOut, outpath); } else if(this->GetTarget()->IsCFBundleOnApple()) { // Create the core foundation bundle. - std::string outpath; + std::string outpath = + this->GetTarget()->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut, outpath); } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 850e5ea..532ee67 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -699,7 +699,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( cmSourceFile& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(this->Generator->OSXBundleGenerator->GetMacContentDirectory().empty()) + if(!this->Generator->GetTarget()->IsBundleOnApple()) { return; } diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 42fad07..621a49f 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -28,26 +28,16 @@ void cmOSXBundleGenerator::PrepareTargetProperties(cmTarget* target) //---------------------------------------------------------------------------- cmOSXBundleGenerator:: cmOSXBundleGenerator(cmTarget* target, - std::string targetNameOut, const char* configName) : Target(target) , Makefile(target->GetMakefile()) , LocalGenerator(Makefile->GetLocalGenerator()) - , TargetNameOut(targetNameOut) , ConfigName(configName) - , MacContentDirectory() - , FrameworkVersion() , MacContentFolders(0) { if (this->MustSkip()) return; - this->MacContentDirectory = - this->Target->GetMacContentDirectory(this->ConfigName, - /*implib*/ false, - /*includeMacOS*/ false); - if(this->Target->IsFrameworkOnApple()) - this->FrameworkVersion = this->Target->GetFrameworkVersion(); } //---------------------------------------------------------------------------- @@ -57,41 +47,60 @@ bool cmOSXBundleGenerator::MustSkip() } //---------------------------------------------------------------------------- -void cmOSXBundleGenerator::CreateAppBundle(std::string& targetName, +void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, std::string& outpath) { if (this->MustSkip()) return; // Compute bundle directory names. - outpath = this->MacContentDirectory; - outpath += "MacOS"; - cmSystemTools::MakeDirectory(outpath.c_str()); - outpath += "/"; - this->Makefile->AddCMakeOutputFile(outpath.c_str()); + std::string out = outpath; + out += "/"; + out += this->Target->GetAppBundleDirectory(this->ConfigName, false); + cmSystemTools::MakeDirectory(out.c_str()); + this->Makefile->AddCMakeOutputFile(out.c_str()); + + std::string newoutpath = out; // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = this->MacContentDirectory + "Info.plist"; + std::string plist = outpath; + plist += "/"; + plist += this->Target->GetAppBundleDirectory(this->ConfigName, true); + plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->Target, targetName.c_str(), plist.c_str()); this->Makefile->AddCMakeOutputFile(plist.c_str()); + outpath = newoutpath; } //---------------------------------------------------------------------------- -void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) +void cmOSXBundleGenerator::CreateFramework( + const std::string& targetName, const std::string& outpath) { if (this->MustSkip()) return; assert(this->MacContentFolders); + // Compute the location of the top-level foo.framework directory. + std::string contentdir = outpath + "/" + + this->Target->GetFrameworkDirectory(this->ConfigName, true); + contentdir += "/"; + + std::string newoutpath = outpath + "/" + + this->Target->GetFrameworkDirectory(this->ConfigName, false); + + std::string frameworkVersion = this->Target->GetFrameworkVersion(); + // Configure the Info.plist file into the Resources directory. this->MacContentFolders->insert("Resources"); - std::string plist = this->MacContentDirectory + "Resources/Info.plist"; + std::string plist = newoutpath; + plist += "/Resources/Info.plist"; + std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateFrameworkInfoPList(this->Target, - targetName.c_str(), + name.c_str(), plist.c_str()); // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to @@ -99,25 +108,17 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) std::string oldName; std::string newName; - // Compute the location of the top-level foo.framework directory. - std::string top = this->Target->GetDirectory(this->ConfigName); - top += "/"; - top += this->TargetNameOut; - top += ".framework/"; // Make foo.framework/Versions - std::string versions = top; + std::string versions = contentdir; versions += "Versions"; cmSystemTools::MakeDirectory(versions.c_str()); // Make foo.framework/Versions/version - std::string version = versions; - version += "/"; - version += this->FrameworkVersion; - cmSystemTools::MakeDirectory(version.c_str()); + cmSystemTools::MakeDirectory(newoutpath.c_str()); // Current -> version - oldName = this->FrameworkVersion; + oldName = frameworkVersion; newName = versions; newName += "/Current"; cmSystemTools::RemoveFile(newName.c_str()); @@ -126,9 +127,9 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) // foo -> Versions/Current/foo oldName = "Versions/Current/"; - oldName += this->TargetNameOut; - newName = top; - newName += this->TargetNameOut; + oldName += name; + newName = contentdir; + newName += name; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); this->Makefile->AddCMakeOutputFile(newName.c_str()); @@ -138,7 +139,7 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) this->MacContentFolders->end()) { oldName = "Versions/Current/Resources"; - newName = top; + newName = contentdir; newName += "Resources"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); @@ -150,7 +151,7 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) this->MacContentFolders->end()) { oldName = "Versions/Current/Headers"; - newName = top; + newName = contentdir; newName += "Headers"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); @@ -162,7 +163,7 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) this->MacContentFolders->end()) { oldName = "Versions/Current/PrivateHeaders"; - newName = top; + newName = contentdir; newName += "PrivateHeaders"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); @@ -171,27 +172,32 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) } //---------------------------------------------------------------------------- -void cmOSXBundleGenerator::CreateCFBundle(std::string& targetName, +void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, std::string& outpath) { if (this->MustSkip()) return; // Compute bundle directory names. - outpath = this->MacContentDirectory; - outpath += "MacOS"; - cmSystemTools::MakeDirectory(outpath.c_str()); - outpath += "/"; - this->Makefile->AddCMakeOutputFile(outpath.c_str()); + std::string out = outpath; + out += "/"; + out += this->Target->GetCFBundleDirectory(this->ConfigName, true); + std::string top = out; + out += "/MacOS"; + cmSystemTools::MakeDirectory(out.c_str()); + this->Makefile->AddCMakeOutputFile(out.c_str()); + + std::string newoutpath = out; // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = this->MacContentDirectory; - plist += "Info.plist"; + std::string plist = top; + plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->Target, targetName.c_str(), plist.c_str()); this->Makefile->AddCMakeOutputFile(plist.c_str()); + outpath = newoutpath; } //---------------------------------------------------------------------------- @@ -220,7 +226,11 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc) { // Construct the full path to the content subdirectory. - std::string macdir = this->MacContentDirectory; + + std::string macdir = + this->Target->GetMacContentDirectory(this->ConfigName, + /*implib*/ false); + macdir += "/"; macdir += pkgloc; cmSystemTools::MakeDirectory(macdir.c_str()); diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 01e3cbe..6cf81d2 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -28,12 +28,19 @@ public: static void PrepareTargetProperties(cmTarget* target); cmOSXBundleGenerator(cmTarget* target, - std::string targetNameOut, const char* configName); - void CreateAppBundle(std::string& targetName, std::string& outpath); - void CreateFramework(std::string const& targetName); - void CreateCFBundle(std::string& targetName, std::string& outpath); + // create an app bundle at a given root, and return + // the directory within the bundle that contains the executable + void CreateAppBundle(const std::string& targetName, std::string& root); + + // create a framework at a given root + void CreateFramework(const std::string& targetName, + const std::string& root); + + // create a cf bundle at a given root and return the + // directory within the bundle that contains the library + void CreateCFBundle(const std::string& targetName, std::string& outpath); struct MacOSXContentGeneratorType { @@ -46,10 +53,6 @@ public: MacOSXContentGeneratorType* generator); std::string InitMacOSXContentDirectory(const char* pkgloc); - std::string GetMacContentDirectory() const - { return this->MacContentDirectory; } - std::string GetFrameworkVersion() const - { return this->FrameworkVersion; } void SetMacContentFolders(std::set<cmStdString>* macContentFolders) { this->MacContentFolders = macContentFolders; } @@ -60,10 +63,7 @@ private: cmTarget* Target; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; - std::string TargetNameOut; const char* ConfigName; - std::string MacContentDirectory; - std::string FrameworkVersion; std::set<cmStdString>* MacContentFolders; }; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 6e41768..93885b2 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -36,8 +36,25 @@ public: OD(od), GlobalGenerator(od->GlobalGenerator) { this->FullPath = file; - this->Directory = cmSystemTools::GetFilenamePath(file); - this->FileName = cmSystemTools::GetFilenameName(file); + + if(file.rfind(".framework") != std::string::npos) + { + cmsys::RegularExpression splitFramework; + splitFramework.compile("^(.*)/(.*).framework/.*/(.*)$"); + if(splitFramework.find(file) && + (splitFramework.match(2) == splitFramework.match(3))) + { + this->Directory = splitFramework.match(1); + this->FileName = + std::string(file.begin() + this->Directory.size() + 1, file.end()); + } + } + + if(this->FileName.empty()) + { + this->Directory = cmSystemTools::GetFilenamePath(file); + this->FileName = cmSystemTools::GetFilenameName(file); + } } virtual ~cmOrderDirectoriesConstraint() {} @@ -301,22 +318,42 @@ void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath, // Add the runtime library at most once. if(this->EmmittedConstraintSOName.insert(fullPath).second) { + std::string soname2 = soname ? soname : ""; // Implicit link directories need special handling. if(!this->ImplicitDirectories.empty()) { std::string dir = cmSystemTools::GetFilenamePath(fullPath); + + if(fullPath.rfind(".framework") != std::string::npos) + { + cmsys::RegularExpression splitFramework; + splitFramework.compile("^(.*)/(.*).framework/(.*)/(.*)$"); + if(splitFramework.find(fullPath) && + (splitFramework.match(2) == splitFramework.match(4))) + { + dir = splitFramework.match(1); + soname2 = splitFramework.match(2); + soname2 += ".framework/"; + soname2 += splitFramework.match(3); + soname2 += "/"; + soname2 += splitFramework.match(4); + } + } + if(this->ImplicitDirectories.find(dir) != this->ImplicitDirectories.end()) { this->ImplicitDirEntries.push_back( - new cmOrderDirectoriesConstraintSOName(this, fullPath, soname)); + new cmOrderDirectoriesConstraintSOName(this, fullPath, + soname2.c_str())); return; } } // Construct the runtime information entry for this library. this->ConstraintEntries.push_back( - new cmOrderDirectoriesConstraintSOName(this, fullPath, soname)); + new cmOrderDirectoriesConstraintSOName(this, fullPath, + soname2.c_str())); } else { diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index a468fa7..350b462 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -309,6 +309,46 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) cmLocalGenerator::EscapeForCMake(_moc_headers.c_str()).c_str()); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); + const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR"); + if (!qtVersion) + { + qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); + } + if (const char *targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", 0)) + { + qtVersion = targetQtVersion; + } + if (qtVersion) + { + makefile->AddDefinition("_target_qt_version", qtVersion); + } + + { + const char *qtMoc = makefile->GetSafeDefinition("QT_MOC_EXECUTABLE"); + makefile->AddDefinition("_qt_moc_executable", qtMoc); + } + + if (strcmp(qtVersion, "5") == 0) + { + cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc"); + if (!qt5Moc) + { + cmSystemTools::Error("Qt5::moc target not found ", + automocTargetName.c_str()); + return; + } + makefile->AddDefinition("_qt_moc_executable", qt5Moc->GetLocation(0)); + } + else + { + if (strcmp(qtVersion, "4") != 0) + { + cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " + "Qt 5 ", automocTargetName.c_str()); + } + } + const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT"); std::string inputFile = cmakeRoot; inputFile += "/Modules/AutomocInfo.cmake.in"; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 67f3023..803d0da 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2413,6 +2413,27 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath, } //---------------------------------------------------------------------------- +bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath, + std::string& soname) +{ + std::vector<cmStdString> cmds; + cmds.push_back("otool"); + cmds.push_back("-D"); + cmds.push_back(fullPath.c_str()); + + std::string output; + RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE); + + std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n"); + if(strs.size() == 2) + { + soname = strs[1]; + return true; + } + return false; +} + +//---------------------------------------------------------------------------- #if defined(CMAKE_USE_ELF_PARSER) std::string::size_type cmSystemToolsFindRPath(std::string const& have, std::string const& want) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 8355d78..f5be26b 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -439,6 +439,10 @@ public: static bool GuessLibrarySOName(std::string const& fullPath, std::string& soname); + /** Try to guess the install name of a shared library. */ + static bool GuessLibraryInstallName(std::string const& fullPath, + std::string& soname); + /** Try to set the RPATH in an ELF binary. */ static bool ChangeRPath(std::string const& file, std::string const& oldRPath, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 75873ff..4f7fa87 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1186,6 +1186,15 @@ void cmTarget::DefineProperties(cmake *cm) "hard-code all the settings instead of using the target properties."); cm->DefineProperty + ("MACOSX_RPATH", cmProperty::TARGET, + "Whether to use rpaths on Mac OS X.", + "When this property is set to true, the directory portion of the" + "\"install_name\" field of shared libraries will default to \"@rpath\"." + "Runtime paths will also be embedded in binaries using this target." + "This property is initialized by the value of the variable " + "CMAKE_MACOSX_RPATH if it is set when a target is created."); + + cm->DefineProperty ("ENABLE_EXPORTS", cmProperty::TARGET, "Specify whether an executable exports symbols for loadable modules.", "Normally an executable does not export any symbols because it is " @@ -1513,6 +1522,8 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0); this->SetPropertyDefault("WIN32_EXECUTABLE", 0); this->SetPropertyDefault("MACOSX_BUNDLE", 0); + this->SetPropertyDefault("MACOSX_RPATH", 0); + // Collect the set of configuration types. std::vector<std::string> configNames; @@ -1683,6 +1694,13 @@ bool cmTarget::IsCFBundleOnApple() } //---------------------------------------------------------------------------- +bool cmTarget::IsBundleOnApple() +{ + return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() || + this->IsCFBundleOnApple(); +} + +//---------------------------------------------------------------------------- class cmTargetTraceDependencies { public: @@ -3379,17 +3397,23 @@ const char* cmTarget::NormalGetLocation(const char* config) // Now handle the deprecated build-time configuration location. this->Location = this->GetDirectory(); - if(!this->Location.empty()) - { - this->Location += "/"; - } const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); if(cfgid && strcmp(cfgid, ".") != 0) { - this->Location += cfgid; this->Location += "/"; + this->Location += cfgid; + } + + if(this->IsCFBundleOnApple() || this->IsAppBundleOnApple()) + { + std::string macdir = this->BuildMacContentDirectory("", config, false); + if(!macdir.empty()) + { + this->Location += "/"; + this->Location += macdir; + } } - this->Location = this->BuildMacContentDirectory(this->Location, config); + this->Location += "/"; this->Location += this->GetFullName(config, false); return this->Location.c_str(); } @@ -3873,6 +3897,10 @@ std::string cmTarget::GetSOName(const char* config) else { // Use the soname given if any. + if(info->SOName.find("@rpath/") == 0) + { + return info->SOName.substr(6); + } return info->SOName; } } @@ -3895,6 +3923,75 @@ std::string cmTarget::GetSOName(const char* config) } //---------------------------------------------------------------------------- +bool cmTarget::HasMacOSXRpath(const char* config) +{ + bool install_name_is_rpath = false; + bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH"); + + if(!this->IsImportedTarget) + { + const char* install_name = this->GetProperty("INSTALL_NAME_DIR"); + bool use_install_name = + this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + if(install_name && use_install_name && + std::string(install_name) == "@rpath") + { + install_name_is_rpath = true; + } + } + else + { + // Lookup the imported soname. + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) + { + if(!info->NoSOName && !info->SOName.empty()) + { + if(info->SOName.find("@rpath/") == 0) + { + install_name_is_rpath = true; + } + } + else + { + std::string install_name; + cmSystemTools::GuessLibraryInstallName(info->Location, install_name); + if(install_name.find("@rpath") != std::string::npos) + { + install_name_is_rpath = true; + } + } + } + } + + if(!install_name_is_rpath && !macosx_rpath) + { + return false; + } + + if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) + { + cmOStringStream w; + w << "Attempting to use"; + if(macosx_rpath) + { + w << " MACOSX_RPATH"; + } + else + { + w << " @rpath"; + } + w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set."; + w << " This could be because you are using a Mac OS X version"; + w << " less than 10.5 or because CMake's platform configuration is"; + w << " corrupt."; + cmake* cm = this->Makefile->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace()); + } + + return true; +} + +//---------------------------------------------------------------------------- bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) { if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) @@ -3991,7 +4088,13 @@ std::string cmTarget::GetFullPath(const char* config, bool implib, std::string cmTarget::NormalGetFullPath(const char* config, bool implib, bool realname) { - std::string fpath = this->GetMacContentDirectory(config, implib); + std::string fpath = this->GetDirectory(config, implib); + fpath += "/"; + if(this->IsCFBundleOnApple() || this->IsAppBundleOnApple()) + { + fpath = this->BuildMacContentDirectory(fpath, config, false); + fpath += "/"; + } // Add the full name of the target. if(implib) @@ -4123,10 +4226,13 @@ void cmTarget::GetFullNameInternal(const char* config, targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); } - // frameworks do not have a prefix or a suffix + // frameworks have directory prefix but no suffix + std::string fw_prefix; if(this->IsFrameworkOnApple()) { - targetPrefix = 0; + fw_prefix = this->GetOutputName(config, false); + fw_prefix += ".framework/"; + targetPrefix = fw_prefix.c_str(); targetSuffix = 0; } @@ -4206,13 +4312,24 @@ void cmTarget::GetLibraryNames(std::string& name, // The library name. name = prefix+base+suffix; - // The library's soname. - this->ComputeVersionedName(soName, prefix, base, suffix, - name, soversion); - - // The library's real name on disk. - this->ComputeVersionedName(realName, prefix, base, suffix, - name, version); + if(this->IsFrameworkOnApple()) + { + realName = prefix; + realName += "Versions/"; + realName += this->GetFrameworkVersion(); + realName += "/"; + realName += base; + soName = realName; + } + else + { + // The library's soname. + this->ComputeVersionedName(soName, prefix, base, suffix, + name, soversion); + // The library's real name on disk. + this->ComputeVersionedName(realName, prefix, base, suffix, + name, version); + } // The import library name. if(this->GetType() == cmTarget::SHARED_LIBRARY || @@ -4500,14 +4617,13 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config) } //---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, - bool for_xcode) +std::string cmTarget::GetInstallNameDirForBuildTree(const char* config) { // If building directly for installation then the build tree install_name // is the same as the install tree. if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) { - return GetInstallNameDirForInstallTree(config, for_xcode); + return GetInstallNameDirForInstallTree(); } // Use the build tree directory for the target. @@ -4515,12 +4631,16 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { - std::string dir = this->GetDirectory(config); - dir += "/"; - if(this->IsFrameworkOnApple() && !for_xcode) + std::string dir; + if(this->GetPropertyAsBool("MACOSX_RPATH")) + { + dir = "@rpath"; + } + else { - dir += this->GetFrameworkDirectory(config); + dir = this->GetDirectory(config); } + dir += "/"; return dir; } else @@ -4530,8 +4650,7 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, } //---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForInstallTree(const char* config, - bool for_xcode) +std::string cmTarget::GetInstallNameDirForInstallTree() { if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { @@ -4547,12 +4666,10 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char* config, dir += "/"; } } - - if(this->IsFrameworkOnApple() && !for_xcode) + if(dir.empty() && this->GetPropertyAsBool("MACOSX_RPATH")) { - dir += this->GetFrameworkDirectory(config); + dir = "@rpath/"; } - return dir; } else @@ -5134,7 +5251,6 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const //---------------------------------------------------------------------------- bool cmTarget::IsChrpathUsed(const char* config) { -#if defined(CMAKE_USE_ELF_PARSER) // Only certain target types have an rpath. if(!(this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY || @@ -5168,6 +5284,12 @@ bool cmTarget::IsChrpathUsed(const char* config) return false; } + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + return true; + } + +#if defined(CMAKE_USE_ELF_PARSER) // Enable if the rpath flag uses a separator and the target uses ELF // binaries. if(const char* ll = this->GetLinkerLanguage(config, this)) @@ -6010,59 +6132,86 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head) } //---------------------------------------------------------------------------- -std::string cmTarget::GetFrameworkDirectory(const char* config) +std::string cmTarget::GetFrameworkDirectory(const char* config, + bool rootDir) { std::string fpath; - fpath += this->GetFullName(config, false); - fpath += ".framework/Versions/"; - fpath += this->GetFrameworkVersion(); - fpath += "/"; + fpath += this->GetOutputName(config, false); + fpath += ".framework"; + if(!rootDir) + { + fpath += "/Versions/"; + fpath += this->GetFrameworkVersion(); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetCFBundleDirectory(const char* config, + bool contentOnly) +{ + std::string fpath; + fpath += this->GetOutputName(config, false); + fpath += "."; + const char *ext = this->GetProperty("BUNDLE_EXTENSION"); + if (!ext) + { + ext = "bundle"; + } + fpath += ext; + fpath += "/Contents"; + if(!contentOnly) + fpath += "/MacOS"; + return fpath; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetAppBundleDirectory(const char* config, + bool contentOnly) +{ + std::string fpath = this->GetFullName(config, false); + fpath += ".app/Contents"; + if(!contentOnly) + fpath += "/MacOS"; return fpath; } //---------------------------------------------------------------------------- std::string cmTarget::BuildMacContentDirectory(const std::string& base, const char* config, - bool includeMacOS) + bool contentOnly) { std::string fpath = base; if(this->IsAppBundleOnApple()) { - fpath += this->GetFullName(config, false); - fpath += ".app/Contents/"; - if(includeMacOS) - fpath += "MacOS/"; + fpath += this->GetAppBundleDirectory(config, contentOnly); } if(this->IsFrameworkOnApple()) { - fpath += this->GetFrameworkDirectory(config); + fpath += this->GetFrameworkDirectory(config, contentOnly); } if(this->IsCFBundleOnApple()) { - fpath += this->GetFullName(config, false); - fpath += "."; - const char *ext = this->GetProperty("BUNDLE_EXTENSION"); - if (!ext) - { - ext = "bundle"; - } - fpath += ext; - fpath += "/Contents/"; - if(includeMacOS) - fpath += "MacOS/"; + fpath += this->GetCFBundleDirectory(config, contentOnly); } return fpath; } //---------------------------------------------------------------------------- std::string cmTarget::GetMacContentDirectory(const char* config, - bool implib, - bool includeMacOS) + bool implib) { // Start with the output directory for the target. std::string fpath = this->GetDirectory(config, implib); fpath += "/"; - fpath = this->BuildMacContentDirectory(fpath, config, includeMacOS); + bool contentOnly = true; + if(this->IsFrameworkOnApple()) + { + // additional files with a framework go into the version specific + // directory + contentOnly = false; + } + fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); return fpath; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 508fc11..0bcc2a8 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -367,6 +367,9 @@ public: /** Get the soname of the target. Allowed only for a shared library. */ std::string GetSOName(const char* config); + /** Whether this library has @rpath and platform supports it. */ + bool HasMacOSXRpath(const char* config); + /** Test for special case of a third-party shared library that has no soname at all. */ bool IsImportedSharedLibWithoutSOName(const char* config); @@ -412,10 +415,14 @@ public: /** Return true if builtin chrpath will work for this target */ bool IsChrpathUsed(const char* config); - std::string GetInstallNameDirForBuildTree(const char* config, - bool for_xcode = false); - std::string GetInstallNameDirForInstallTree(const char* config, - bool for_xcode = false); + /** Return the install name directory for the target in the + * build tree. For example: "@rpath/", "@loader_path/", + * or "/full/path/to/library". */ + std::string GetInstallNameDirForBuildTree(const char* config); + + /** Return the install name directory for the target in the + * install tree. For example: "@rpath/" or "@loader_path/". */ + std::string GetInstallNameDirForInstallTree(); cmComputeLinkInformation* GetLinkInformation(const char* config, cmTarget *head = 0); @@ -467,6 +474,10 @@ public: /** Return whether this target is an executable Bundle on Apple. */ bool IsAppBundleOnApple(); + /** Return whether this target is an executable Bundle, a framework + or CFBundle on Apple. */ + bool IsBundleOnApple(); + /** Return the framework version string. Undefined if IsFrameworkOnApple returns false. */ std::string GetFrameworkVersion(); @@ -481,21 +492,21 @@ public: directory. */ bool UsesDefaultOutputDir(const char* config, bool implib); - /** Append to @a base the mac content directory and return it. */ - std::string BuildMacContentDirectory(const std::string& base, - const char* config = 0, - bool includeMacOS = true); - /** @return the mac content directory for this target. */ - std::string GetMacContentDirectory(const char* config = 0, - bool implib = false, - bool includeMacOS = true); + std::string GetMacContentDirectory(const char* config, + bool implib); /** @return whether this target have a well defined output file name. */ bool HaveWellDefinedOutputFiles(); /** @return the Mac framework directory without the base. */ - std::string GetFrameworkDirectory(const char* config = 0); + std::string GetFrameworkDirectory(const char* config, bool rootDir); + + /** @return the Mac CFBundle directory without the base */ + std::string GetCFBundleDirectory(const char* config, bool contentOnly); + + /** @return the Mac App directory without the base */ + std::string GetAppBundleDirectory(const char* config, bool contentOnly); std::vector<std::string> GetIncludeDirectories(const char *config); void InsertInclude(const cmValueWithOrigin &entry, @@ -601,6 +612,11 @@ private: the same as GetFullName. */ std::string NormalGetRealName(const char* config); + /** Append to @a base the mac content directory and return it. */ + std::string BuildMacContentDirectory(const std::string& base, + const char* config, + bool contentOnly); + private: std::string Name; std::vector<cmCustomCommand> PreBuildCommands; diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 9e2a93d..9db1dee 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -1471,7 +1471,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName( { char host[NI_MAXHOST]={'\0'}; - int addrlen + socklen_t addrlen = (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6)); ierr=getnameinfo( @@ -3487,7 +3487,7 @@ bool SystemInformationImplementation::QueryLinuxMemory() bool have[6] = { false, false, false, false, false, false }; unsigned long value[6]; int count = 0; - while(fgets(buffer, sizeof(buffer), fd)) + while(fgets(buffer, static_cast<int>(sizeof(buffer)), fd)) { for(int i=0; i < 6; ++i) { diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 394d65e..158217e 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -2742,14 +2742,23 @@ bool SystemTools::FileIsDirectory(const char* name) } // Remove any trailing slash from the name except in a root component. - char buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; + char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; + std::string string_buffer; size_t last = length-1; if(last > 0 && (name[last] == '/' || name[last] == '\\') && strcmp(name, "/") !=0 && name[last-1] != ':') { - memcpy(buffer, name, last); - buffer[last] = 0; - name = buffer; + if(last < sizeof(local_buffer)) + { + memcpy(local_buffer, name, last); + local_buffer[last] = 0; + name = local_buffer; + } + else + { + string_buffer.append(name, last); + name = string_buffer.c_str(); + } } // Now check the file node type. diff --git a/Source/kwsys/testIOS.cxx b/Source/kwsys/testIOS.cxx index 3b971e2..f0c7f1a 100644 --- a/Source/kwsys/testIOS.cxx +++ b/Source/kwsys/testIOS.cxx @@ -48,7 +48,7 @@ int testIOS(int, char*[]) return 1; } static const unsigned char array[] = { 0xff,0x4f,0xff,0x51,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x01,0x01,0xff,0x52,0x00,0x0c,0x00,0x00,0x00,0x01,0x00,0x05,0x04,0x04,0x00,0x01,0xff,0x5c,0x00,0x13,0x40,0x40,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0xff,0x64,0x00,0x2c,0x00,0x00,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x49,0x54,0x4b,0x2f,0x47,0x44,0x43,0x4d,0x2f,0x4f,0x70,0x65,0x6e,0x4a,0x50,0x45,0x47,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2e,0x30,0xff,0x90,0x00,0x0a,0x00,0x00,0x00,0x00,0x06,0x2c,0x00,0x01,0xff,0x93,0xcf,0xb0,0x18,0x08,0x7f,0xc6,0x99,0xbf,0xff,0xc0,0xf8,0xc1,0xc1,0xf3,0x05,0x81,0xf2,0x83,0x0a,0xa5,0xff,0x10,0x90,0xbf,0x2f,0xff,0x04,0xa8,0x7f,0xc0,0xf8,0xc4,0xc1,0xf3,0x09,0x81,0xf3,0x0c,0x19,0x34 }; - const unsigned int narray = sizeof(array); // 180 + const size_t narray = sizeof(array); // 180 kwsys_ios::stringstream strstr; strstr.write( (char*)array, narray ); //strstr.seekp( narray / 2 ); // set position of put pointer in mid string diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 49a686c..738043f 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -88,9 +88,9 @@ int testSystemInformation(int, char*[]) printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB"); - for (int i = 0; i <= 31; i++) + for (long int i = 0; i <= 31; i++) { - if (info.DoesCPUSupportFeature(1 << i)) + if (info.DoesCPUSupportFeature(static_cast<long int>(1) << i)) { kwsys_ios::cout << "CPU feature " << i << "\n"; } diff --git a/Tests/BundleUtilities/CMakeLists.txt b/Tests/BundleUtilities/CMakeLists.txt index 8f24afe..5cc7071 100644 --- a/Tests/BundleUtilities/CMakeLists.txt +++ b/Tests/BundleUtilities/CMakeLists.txt @@ -12,8 +12,7 @@ add_library(shared2 SHARED shared2.cpp shared2.h) # a framework library add_library(framework SHARED framework.cpp framework.h) -# TODO: fix problems with local frameworks without rpaths -#set_target_properties(framework PROPERTIES FRAMEWORK 1) +set_target_properties(framework PROPERTIES FRAMEWORK 1) # make sure rpaths are not helping BundleUtilities or the executables set_target_properties(shared shared2 framework PROPERTIES diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 0b221e8..cd562c2 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1044,6 +1044,20 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Targets") + + if(Qt5Widgets_FOUND AND NOT Qt5Widgets_VERSION VERSION_LESS 5.1.0) + add_test(Qt4And5Automoc ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Qt4And5Automoc" + "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc" + ${build_generator_args} + --build-project Qt4And5Automoc + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc" + --force-new-ctest-process + --test-command ${CMAKE_CTEST_COMMAND} -V + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc") + endif() endif() add_test(ExternalProject ${CMAKE_CTEST_COMMAND} @@ -1233,6 +1247,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ endif() endif() + if(APPLE AND "${DARWIN_MAJOR_VERSION}" GREATER 9) + add_test(MacRuntimePath ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/MacRuntimePath" + "${CMake_BINARY_DIR}/Tests/MacRuntimePath" + ${build_generator_args} + --build-project MacRuntimePath + ) + endif() + add_test(linkorder1 ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/LinkLineOrder" diff --git a/Tests/CompileDefinitions/CMakeLists.txt b/Tests/CompileDefinitions/CMakeLists.txt index d3e9a3e..930d220 100644 --- a/Tests/CompileDefinitions/CMakeLists.txt +++ b/Tests/CompileDefinitions/CMakeLists.txt @@ -5,6 +5,7 @@ project(CompileDefinitions) if ("${CMAKE_GENERATOR}" STREQUAL "Visual Studio 6") add_definitions(-DNO_SPACES_IN_DEFINE_VALUES) + set(NO_SPACES_IN_DEFINE_VALUES 1) endif() # Use compile flags to tell executables which config is built diff --git a/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt b/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt index d3886a1..23e0134 100644 --- a/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt +++ b/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt @@ -1,8 +1,15 @@ project(add_definitions_command) -add_definitions(-DCMAKE_IS_FUN -DCMAKE_IS=Fun -DCMAKE_IS_="Fun" -DCMAKE_IS_REALLY="Very Fun") -add_definitions(-DCMAKE_IS_="Fun" -DCMAKE_IS_REALLY="Very Fun" -DCMAKE_IS_FUN -DCMAKE_IS=Fun) +add_definitions(-DCMAKE_IS_FUN -DCMAKE_IS=Fun -DCMAKE_IS_="Fun") +if (NOT NO_SPACES_IN_DEFINE_VALUES) + add_definitions(-DCMAKE_IS_REALLY="Very Fun") +endif() +add_definitions(-DCMAKE_IS_="Fun") +if (NOT NO_SPACES_IN_DEFINE_VALUES) + add_definitions(-DCMAKE_IS_REALLY="Very Fun") +endif() +add_definitions(-DCMAKE_IS_FUN -DCMAKE_IS=Fun) add_definitions(-DBUILD_IS_DEBUG=$<CONFIG:Debug> -DBUILD_IS_NOT_DEBUG=$<NOT:$<CONFIG:Debug>>) add_executable(add_definitions_command_executable ../compiletest.cpp) diff --git a/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt b/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt index 5587f7f..55108db 100644 --- a/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt +++ b/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt @@ -7,7 +7,9 @@ add_executable(add_definitions_command_with_target_prop_executable ../compiletes set_target_properties(add_definitions_command_with_target_prop_executable PROPERTIES COMPILE_DEFINITIONS CMAKE_IS_="Fun") -set_property(TARGET add_definitions_command_with_target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun") +if (NOT NO_SPACES_IN_DEFINE_VALUES) + set_property(TARGET add_definitions_command_with_target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun") +endif() add_definitions(-DCMAKE_IS_FUN) diff --git a/Tests/CompileDefinitions/target_prop/CMakeLists.txt b/Tests/CompileDefinitions/target_prop/CMakeLists.txt index 66a3aa6..6bf9c5c 100644 --- a/Tests/CompileDefinitions/target_prop/CMakeLists.txt +++ b/Tests/CompileDefinitions/target_prop/CMakeLists.txt @@ -5,7 +5,11 @@ add_executable(target_prop_executable ../compiletest.cpp) set_target_properties(target_prop_executable PROPERTIES COMPILE_DEFINITIONS CMAKE_IS_FUN) -set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun" CMAKE_IS=Fun) +if (NOT NO_SPACES_IN_DEFINE_VALUES) + set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun" CMAKE_IS=Fun) +else() + set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS=Fun) +endif() set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_FUN CMAKE_IS_="Fun") set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt index 50f12ee..088725b 100644 --- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt @@ -110,6 +110,25 @@ set_property(TARGET libbad APPEND PROPERTY ) +add_library(includes_source_good empty.cpp) +target_include_directories(includes_source_good + INTERFACE + "${CMAKE_CURRENT_BINARY_DIR}/good" + "${CMAKE_CURRENT_BINARY_DIR}/othergood/" +) +add_library(includes_source_bad empty.cpp) +target_include_directories(includes_source_bad + INTERFACE + "${CMAKE_CURRENT_BINARY_DIR}/bad" +) + +add_library(includes_proxy SHARED empty.cpp) +target_link_libraries(includes_proxy includes_source_good) +target_link_libraries(includes_proxy LINK_INTERFACE_LIBRARIES includes_source_bad) +add_executable(copy_includes copy_includes.cpp) +target_include_directories(copy_includes PRIVATE $<TARGET_PROPERTY:includes_proxy,INCLUDE_DIRECTORIES>) + + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp" "#include \"common.h\"\n") add_library(lib5 "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp") diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/copy_includes.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/copy_includes.cpp new file mode 100644 index 0000000..fed4c03 --- /dev/null +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/copy_includes.cpp @@ -0,0 +1,7 @@ + +#include "common.h" + +int main() +{ + return 0; +} diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/empty.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/empty.cpp new file mode 100644 index 0000000..7279c5e --- /dev/null +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty(void) +{ + return 0; +} diff --git a/Tests/MacRuntimePath/A/CMakeLists.txt b/Tests/MacRuntimePath/A/CMakeLists.txt new file mode 100644 index 0000000..6e6de42 --- /dev/null +++ b/Tests/MacRuntimePath/A/CMakeLists.txt @@ -0,0 +1,63 @@ +cmake_minimum_required(VERSION 2.8) +project(MacRuntimePath_A) + +# a shared library +add_library(shared SHARED shared.cpp shared.h) +set_target_properties(shared PROPERTIES MACOSX_RPATH 1) + +# a shared library with custom set @rpath +add_library(shared2 SHARED shared.cpp shared.h) +set_target_properties(shared2 PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath") + +# a framework library +add_library(framework SHARED framework.cpp framework.h) +set_target_properties(framework PROPERTIES MACOSX_RPATH 1 FRAMEWORK 1) + +# executable to test a shared library dependency with install rpaths +add_executable(test1 test1.cpp) +target_link_libraries(test1 shared) +set_target_properties(test1 PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 INSTALL_RPATH "@loader_path/../lib") + +# executable to test a framework library dependency with install rpaths +add_executable(test2 test2.cpp) +target_link_libraries(test2 framework) +set_target_properties(test2 PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 INSTALL_RPATH "@loader_path/../lib") + +# executable to test a framework library dependency with build tree rpaths +add_executable(test3 test3.cpp) +target_link_libraries(test3 framework) + +# executable to test a framework library dependency with build tree rpaths +add_executable(test4 test1.cpp) +target_link_libraries(test4 shared2) + +set_target_properties(shared shared2 framework PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") +set_target_properties(test1 test2 test3 test4 PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") +foreach(config ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER ${config} CONFIG) + set_target_properties(shared shared2 framework PROPERTIES + LIBRARY_OUTPUT_DIRECTORY_${CONFIG} + "${CMAKE_CURRENT_BINARY_DIR}/${config}/lib") + set_target_properties(test1 test2 test3 test4 PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_${CONFIG} + "${CMAKE_CURRENT_BINARY_DIR}/${config}/bin") +endforeach() + +foreach(test test1 test2 test3 test4) + add_custom_target(${test}_run ALL + COMMAND ${test} + DEPENDS ${test} + ) +endforeach() + +export(TARGETS shared shared2 framework FILE "${CMAKE_CURRENT_BINARY_DIR}/exp.cmake") + +install(TARGETS shared EXPORT MyExport DESTINATION lib) +install(TARGETS shared2 EXPORT MyExport DESTINATION lib2) +install(TARGETS framework EXPORT MyExport DESTINATION lib-fw) +install(EXPORT MyExport DESTINATION lib FILE exp.cmake) diff --git a/Tests/MacRuntimePath/A/framework.cpp b/Tests/MacRuntimePath/A/framework.cpp new file mode 100644 index 0000000..abda195 --- /dev/null +++ b/Tests/MacRuntimePath/A/framework.cpp @@ -0,0 +1,8 @@ + +#include "framework.h" +#include "stdio.h" + +void framework() +{ + printf("framework\n"); +} diff --git a/Tests/MacRuntimePath/A/framework.h b/Tests/MacRuntimePath/A/framework.h new file mode 100644 index 0000000..bdd10f0 --- /dev/null +++ b/Tests/MacRuntimePath/A/framework.h @@ -0,0 +1,17 @@ + +#ifndef framework_h +#define framework_h + +#ifdef WIN32 +# ifdef framework_EXPORTS +# define FRAMEWORK_EXPORT __declspec(dllexport) +# else +# define FRAMEWORK_EXPORT __declspec(dllimport) +# endif +#else +# define FRAMEWORK_EXPORT +#endif + +void FRAMEWORK_EXPORT framework(); + +#endif diff --git a/Tests/MacRuntimePath/A/shared.cpp b/Tests/MacRuntimePath/A/shared.cpp new file mode 100644 index 0000000..e5e7dc5 --- /dev/null +++ b/Tests/MacRuntimePath/A/shared.cpp @@ -0,0 +1,8 @@ + +#include "shared.h" +#include "stdio.h" + +void shared() +{ + printf("shared\n"); +} diff --git a/Tests/MacRuntimePath/A/shared.h b/Tests/MacRuntimePath/A/shared.h new file mode 100644 index 0000000..3588fb8 --- /dev/null +++ b/Tests/MacRuntimePath/A/shared.h @@ -0,0 +1,17 @@ + +#ifndef shared_h +#define shared_h + +#ifdef WIN32 +# ifdef shared_EXPORTS +# define SHARED_EXPORT __declspec(dllexport) +# else +# define SHARED_EXPORT __declspec(dllimport) +# endif +#else +# define SHARED_EXPORT +#endif + +void SHARED_EXPORT shared(); + +#endif diff --git a/Tests/MacRuntimePath/A/test1.cpp b/Tests/MacRuntimePath/A/test1.cpp new file mode 100644 index 0000000..cb93448 --- /dev/null +++ b/Tests/MacRuntimePath/A/test1.cpp @@ -0,0 +1,8 @@ + +#include "shared.h" + +int main(int, char**) +{ + shared(); + return 0; +} diff --git a/Tests/MacRuntimePath/A/test2.cpp b/Tests/MacRuntimePath/A/test2.cpp new file mode 100644 index 0000000..26bc9dd --- /dev/null +++ b/Tests/MacRuntimePath/A/test2.cpp @@ -0,0 +1,8 @@ + +#include "framework.h" + +int main(int, char**) +{ + framework(); + return 0; +} diff --git a/Tests/MacRuntimePath/A/test3.cpp b/Tests/MacRuntimePath/A/test3.cpp new file mode 100644 index 0000000..26bc9dd --- /dev/null +++ b/Tests/MacRuntimePath/A/test3.cpp @@ -0,0 +1,8 @@ + +#include "framework.h" + +int main(int, char**) +{ + framework(); + return 0; +} diff --git a/Tests/MacRuntimePath/B/CMakeLists.txt b/Tests/MacRuntimePath/B/CMakeLists.txt new file mode 100644 index 0000000..c361620 --- /dev/null +++ b/Tests/MacRuntimePath/B/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8) +project(MacRuntimePath_B) + +include(${MacRuntimePath_B_BINARY_DIR}/../Root/lib/exp.cmake) + +add_executable(testb ${MacRuntimePath_B_SOURCE_DIR}/../A/test3.cpp) + +# test link with rpath enabled targets +target_link_libraries(testb shared framework) + +# test link with rpath enabled library by filename +target_link_libraries(testb $<TARGET_LINKER_FILE:shared2> framework) + +add_custom_target(testb_run ALL + COMMAND testb + DEPENDS testb + ) diff --git a/Tests/MacRuntimePath/CMakeLists.txt b/Tests/MacRuntimePath/CMakeLists.txt new file mode 100644 index 0000000..5e5b6c4 --- /dev/null +++ b/Tests/MacRuntimePath/CMakeLists.txt @@ -0,0 +1,72 @@ +cmake_minimum_required (VERSION 2.8) +project(MacRuntimePath) + + +# Wipe out the install tree to make sure the exporter works. +add_custom_command( + OUTPUT ${MacRuntimePath_BINARY_DIR}/CleanupProject + COMMAND ${CMAKE_COMMAND} -E remove_directory ${MacRuntimePath_BINARY_DIR}/Root + ) +add_custom_target(CleanupTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/CleanupProject) +set_property( + SOURCE ${MacRuntimePath_BINARY_DIR}/CleanupProject + PROPERTY SYMBOLIC 1 + ) + +configure_file(${MacRuntimePath_SOURCE_DIR}/InitialCache.cmake.in + ${MacRuntimePath_BINARY_DIR}/InitialCache.cmake @ONLY) + +if(CMAKE_CONFIGURATION_TYPES) + set(NESTED_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}") +else() + if(CMAKE_BUILD_TYPE) + set(NESTED_CONFIG_TYPE -C "${CMAKE_BUILD_TYPE}") + else() + set(NESTED_CONFIG_TYPE) + endif() +endif() + +# Build and install the exporter. +add_custom_command( + OUTPUT ${MacRuntimePath_BINARY_DIR}/ExportProject + COMMAND ${CMAKE_CTEST_COMMAND} ${NESTED_CONFIG_TYPE} + --build-and-test + ${MacRuntimePath_SOURCE_DIR}/A + ${MacRuntimePath_BINARY_DIR}/A + --build-noclean + --build-project MacRuntimePath_A + --build-target install + --build-generator ${CMAKE_GENERATOR} + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options -C${MacRuntimePath_BINARY_DIR}/InitialCache.cmake + VERBATIM + ) +add_custom_target(ExportTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/ExportProject) +add_dependencies(ExportTarget CleanupTarget) +set_property( + SOURCE ${MacRuntimePath_BINARY_DIR}/ExportProject + PROPERTY SYMBOLIC 1 + ) + +# Build the importer. +add_custom_command( + OUTPUT ${MacRuntimePath_BINARY_DIR}/ImportProject + COMMAND ${CMAKE_CTEST_COMMAND} ${NESTED_CONFIG_TYPE} + --build-and-test + ${MacRuntimePath_SOURCE_DIR}/B + ${MacRuntimePath_BINARY_DIR}/B + --build-noclean + --build-project MacRuntimePath_B + --build-generator ${CMAKE_GENERATOR} + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options -C${MacRuntimePath_BINARY_DIR}/InitialCache.cmake + VERBATIM + ) +add_custom_target(ImportTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/ImportProject) +add_dependencies(ImportTarget ExportTarget) +set_property( + SOURCE ${MacRuntimePath_BINARY_DIR}/ImportProject + PROPERTY SYMBOLIC 1 + ) diff --git a/Tests/MacRuntimePath/InitialCache.cmake.in b/Tests/MacRuntimePath/InitialCache.cmake.in new file mode 100644 index 0000000..be15eb3 --- /dev/null +++ b/Tests/MacRuntimePath/InitialCache.cmake.in @@ -0,0 +1,13 @@ +set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@" CACHE STRING "C Compiler") +set(CMAKE_C_FLAGS "@CMAKE_C_FLAGS@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_DEBUG "@CMAKE_C_FLAGS_DEBUG@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_RELEASE "@CMAKE_C_FLAGS_RELEASE@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_MINSIZEREL "@CMAKE_C_FLAGS_MINSIZEREL@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "@CMAKE_C_FLAGS_RELWITHDEBINFO@" CACHE STRING "C Flags") +set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@" CACHE STRING "C++ Compiler") +set(CMAKE_CXX_FLAGS "@CMAKE_CXX_FLAGS@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_DEBUG "@CMAKE_CXX_FLAGS_DEBUG@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_RELEASE "@CMAKE_CXX_FLAGS_RELEASE@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_MINSIZEREL "@CMAKE_CXX_FLAGS_MINSIZEREL@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "@CMAKE_CXX_FLAGS_RELWITHDEBINFO@" CACHE STRING "C++ Flags") +set(CMAKE_INSTALL_PREFIX "@MacRuntimePath_BINARY_DIR@/Root" CACHE STRING "Installation Prefix") diff --git a/Tests/Qt4And5Automoc/CMakeLists.txt b/Tests/Qt4And5Automoc/CMakeLists.txt new file mode 100644 index 0000000..0cc80fe --- /dev/null +++ b/Tests/Qt4And5Automoc/CMakeLists.txt @@ -0,0 +1,13 @@ + +project(Qt4And5Automoc) + +find_package(Qt4 REQUIRED) +find_package(Qt5Core REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_executable(qt4_exe main_qt4.cpp) +target_link_libraries(qt4_exe Qt4::QtCore) +add_executable(qt5_exe main_qt5.cpp) +target_link_libraries(qt5_exe Qt5::Core) diff --git a/Tests/Qt4And5Automoc/main.cpp b/Tests/Qt4And5Automoc/main.cpp new file mode 100644 index 0000000..00fd641 --- /dev/null +++ b/Tests/Qt4And5Automoc/main.cpp @@ -0,0 +1,18 @@ + +#include <QObject> + +class SomeObject : public QObject +{ + Q_OBJECT +public: + explicit SomeObject(QObject *parent = 0) + : QObject(parent) + { + + } +}; + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/Tests/Qt4And5Automoc/main_qt4.cpp b/Tests/Qt4And5Automoc/main_qt4.cpp new file mode 100644 index 0000000..a84ce89 --- /dev/null +++ b/Tests/Qt4And5Automoc/main_qt4.cpp @@ -0,0 +1,4 @@ + +#include "main.cpp" + +#include "main_qt4.moc" diff --git a/Tests/Qt4And5Automoc/main_qt5.cpp b/Tests/Qt4And5Automoc/main_qt5.cpp new file mode 100644 index 0000000..287b261 --- /dev/null +++ b/Tests/Qt4And5Automoc/main_qt5.cpp @@ -0,0 +1,4 @@ + +#include "main.cpp" + +#include "main_qt5.moc" diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index f676107..66f86b6 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -72,6 +72,7 @@ add_RunCMake_test(add_dependencies) add_RunCMake_test(build_command) add_RunCMake_test(find_package) add_RunCMake_test(get_filename_component) +add_RunCMake_test(if) add_RunCMake_test(include) add_RunCMake_test(include_directories) add_RunCMake_test(list) @@ -87,3 +88,5 @@ if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]") add_RunCMake_test(include_external_msproject) add_RunCMake_test(SolutionGlobalSections) endif() + +add_RunCMake_test(File_Generate) diff --git a/Tests/RunCMake/ExternalData/LinkDirectory1-stdout.txt b/Tests/RunCMake/ExternalData/LinkDirectory1-stdout.txt new file mode 100644 index 0000000..953ea68 --- /dev/null +++ b/Tests/RunCMake/ExternalData/LinkDirectory1-stdout.txt @@ -0,0 +1,5 @@ +-- Linked Dir/ToLink.txt.md5 to ExternalData MD5/c18ff9804c8deec9eaeb17063cda8b7b +-- Raw data correctly transformed to content link! +-- Staged content exists! +-- Staged content is correct! +-- Staged content was correctly not re-staged! diff --git a/Tests/RunCMake/ExternalData/LinkDirectory1.cmake b/Tests/RunCMake/ExternalData/LinkDirectory1.cmake new file mode 100644 index 0000000..541fc79 --- /dev/null +++ b/Tests/RunCMake/ExternalData/LinkDirectory1.cmake @@ -0,0 +1,37 @@ +include(ExternalData) +set(ExternalData_LINK_CONTENT MD5) +set(ExternalData_SOURCE_ROOT ${CMAKE_CURRENT_BINARY_DIR}) +set(ExternalData_BINARY_ROOT ${CMAKE_CURRENT_BINARY_DIR}/ExternalData) +set(input ${CMAKE_CURRENT_BINARY_DIR}/Dir) +set(output ${CMAKE_CURRENT_BINARY_DIR}/ExternalData/Dir) +set(staged "${input}/.ExternalData_MD5_c18ff9804c8deec9eaeb17063cda8b7b") +set(content "To be transformed into a content link.") +file(REMOVE ${staged}) +file(REMOVE_RECURSE ${input}) +file(WRITE ${input}/ToLink.txt "${content}") +ExternalData_Expand_Arguments(Data args "DATA{${input}/,REGEX:.*}") +if("x${args}" STREQUAL "x${output}") + message(STATUS "Raw data correctly transformed to content link!") +else() + message(FATAL_ERROR "Data reference transformed to:\n ${args}\n" + "but we expected:\n ${output}") +endif() +if(EXISTS "${staged}") + message(STATUS "Staged content exists!") +else() + message(FATAL_ERROR "Staged content missing!") +endif() + +# Expand again to check whether staged content is ignored. +ExternalData_Expand_Arguments(Data args "DATA{${input}/,REGEX:.*}") +file(STRINGS "${staged}" staged_content LIMIT_INPUT 1024) +if("${content}" STREQUAL "${staged_content}") + message(STATUS "Staged content is correct!") +else() + message(STATUS "Staged content is incorrect!") +endif() +if(EXISTS "${staged}.md5") + message(FATAL_ERROR "Staged content was incorrectly re-staged!") +else() + message(STATUS "Staged content was correctly not re-staged!") +endif() diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake index ceb2ecf..8fba82c 100644 --- a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake @@ -13,6 +13,7 @@ run_cmake(Directory4) run_cmake(Directory5) run_cmake(LinkContentMD5) run_cmake(LinkContentSHA1) +run_cmake(LinkDirectory1) run_cmake(MissingData) run_cmake(NoLinkInSource) run_cmake(NoURLTemplates) diff --git a/Tests/RunCMake/File_Generate/BadCondition-result.txt b/Tests/RunCMake/File_Generate/BadCondition-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Generate/BadCondition-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/BadCondition-stderr.txt b/Tests/RunCMake/File_Generate/BadCondition-stderr.txt new file mode 100644 index 0000000..bab8368 --- /dev/null +++ b/Tests/RunCMake/File_Generate/BadCondition-stderr.txt @@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + Evaluation file condition \"\$<1:Bad>\" did not evaluate to valid content. + Got \"Bad\". diff --git a/Tests/RunCMake/File_Generate/BadCondition.cmake b/Tests/RunCMake/File_Generate/BadCondition.cmake new file mode 100644 index 0000000..82ad672 --- /dev/null +++ b/Tests/RunCMake/File_Generate/BadCondition.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<1:Bad> +) diff --git a/Tests/RunCMake/File_Generate/CMakeLists.txt b/Tests/RunCMake/File_Generate/CMakeLists.txt new file mode 100644 index 0000000..e8db6b0 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/File_Generate/CommandConflict-result.txt b/Tests/RunCMake/File_Generate/CommandConflict-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Generate/CommandConflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/CommandConflict-stderr.txt b/Tests/RunCMake/File_Generate/CommandConflict-stderr.txt new file mode 100644 index 0000000..da97ba4 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CommandConflict-stderr.txt @@ -0,0 +1 @@ +CMake Error: File to be generated by multiple different commands: .*CommandConflict-build/output_.*.txt diff --git a/Tests/RunCMake/File_Generate/CommandConflict.cmake b/Tests/RunCMake/File_Generate/CommandConflict.cmake new file mode 100644 index 0000000..d57bc12 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CommandConflict.cmake @@ -0,0 +1,9 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output_$<CONFIGURATION>.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<CONFIG:$<CONFIGURATION>> +) +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output_$<CONFIGURATION>.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<CONFIG:$<CONFIGURATION>> +) diff --git a/Tests/RunCMake/File_Generate/DebugEvaluate.cmake b/Tests/RunCMake/File_Generate/DebugEvaluate.cmake new file mode 100644 index 0000000..1fa9b62 --- /dev/null +++ b/Tests/RunCMake/File_Generate/DebugEvaluate.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<CONFIG:Debug> +) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-result.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt new file mode 100644 index 0000000..9fe39cc --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EmptyCondition1.cmake:2 \(file\): + file Incorrect arguments to GENERATE subcommand. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1.cmake b/Tests/RunCMake/File_Generate/EmptyCondition1.cmake new file mode 100644 index 0000000..8574a5f --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition1.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION +) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition2-result.txt b/Tests/RunCMake/File_Generate/EmptyCondition2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/EmptyCondition2-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition2-stderr.txt new file mode 100644 index 0000000..73d5f25 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EmptyCondition2.cmake:2 \(file\): + file CONDITION of sub-command GENERATE must not be empty if specified. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition2.cmake b/Tests/RunCMake/File_Generate/EmptyCondition2.cmake new file mode 100644 index 0000000..626bfb4 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition2.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION "" +) diff --git a/Tests/RunCMake/File_Generate/OutputConflict-result.txt b/Tests/RunCMake/File_Generate/OutputConflict-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Generate/OutputConflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt new file mode 100644 index 0000000..dbd39de --- /dev/null +++ b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt @@ -0,0 +1,5 @@ +CMake Error in CMakeLists.txt: + Evaluation file to be written multiple times for different configurations + with different content: + + .*output.txt diff --git a/Tests/RunCMake/File_Generate/OutputConflict.cmake b/Tests/RunCMake/File_Generate/OutputConflict.cmake new file mode 100644 index 0000000..7f3e8c7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/OutputConflict.cmake @@ -0,0 +1,4 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" +) diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake new file mode 100644 index 0000000..f07431c --- /dev/null +++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake @@ -0,0 +1,10 @@ +include(RunCMake) + +run_cmake(CommandConflict) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio" OR "${RunCMake_GENERATOR}" MATCHES "XCode" ) + run_cmake(OutputConflict) +endif() +run_cmake(EmptyCondition1) +run_cmake(EmptyCondition2) +run_cmake(BadCondition) +run_cmake(DebugEvaluate) diff --git a/Tests/RunCMake/File_Generate/input.txt b/Tests/RunCMake/File_Generate/input.txt new file mode 100644 index 0000000..3db429d --- /dev/null +++ b/Tests/RunCMake/File_Generate/input.txt @@ -0,0 +1 @@ +Some $<$<CONFIG:Debug>:conflicting> $<$<NOT:$<CONFIG:Debug>>:content> diff --git a/Tests/RunCMake/if/CMakeLists.txt b/Tests/RunCMake/if/CMakeLists.txt new file mode 100644 index 0000000..e8db6b0 --- /dev/null +++ b/Tests/RunCMake/if/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/if/IsDirectory-stdout.txt b/Tests/RunCMake/if/IsDirectory-stdout.txt new file mode 100644 index 0000000..b89446a --- /dev/null +++ b/Tests/RunCMake/if/IsDirectory-stdout.txt @@ -0,0 +1 @@ +CMAKE_CURRENT_SOURCE_DIR exists, tested with trailing slash diff --git a/Tests/RunCMake/if/IsDirectory.cmake b/Tests/RunCMake/if/IsDirectory.cmake new file mode 100644 index 0000000..23d126d --- /dev/null +++ b/Tests/RunCMake/if/IsDirectory.cmake @@ -0,0 +1,5 @@ +if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/") + message(STATUS "CMAKE_CURRENT_SOURCE_DIR exists, tested with trailing slash") +else() + message(FATAL_ERROR "CMAKE_CURRENT_SOURCE_DIR does not exist!") +endif() diff --git a/Tests/RunCMake/if/IsDirectoryLong-stdout.txt b/Tests/RunCMake/if/IsDirectoryLong-stdout.txt new file mode 100644 index 0000000..5e62754 --- /dev/null +++ b/Tests/RunCMake/if/IsDirectoryLong-stdout.txt @@ -0,0 +1 @@ +Directory path with length 94208 correctly does not exist. diff --git a/Tests/RunCMake/if/IsDirectoryLong.cmake b/Tests/RunCMake/if/IsDirectoryLong.cmake new file mode 100644 index 0000000..0e93be7 --- /dev/null +++ b/Tests/RunCMake/if/IsDirectoryLong.cmake @@ -0,0 +1,10 @@ +set(d "/long/path/to/directory") +foreach(i RANGE 11) + set(d "${d}${d}") +endforeach() +string(LENGTH "${d}" dl) +if(IS_DIRECTORY "${d}/") + message(FATAL_ERROR "Directory should not exist!") +else() + message(STATUS "Directory path with length ${dl} correctly does not exist.") +endif() diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake new file mode 100644 index 0000000..6b6b74b --- /dev/null +++ b/Tests/RunCMake/if/RunCMakeTest.cmake @@ -0,0 +1,4 @@ +include(RunCMake) + +run_cmake(IsDirectory) +run_cmake(IsDirectoryLong) |