diff options
75 files changed, 1468 insertions, 601 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 309e224..b4a577c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,10 @@ if(POLICY CMP0053) endif() project(CMake) +# Make sure we can find internal find_package modules only used for +# building CMake and not for shipping externally +list(INSERT CMAKE_MODULE_PATH 0 ${CMake_SOURCE_DIR}/Source/Modules) + if(CMAKE_BOOTSTRAP) # Running from bootstrap script. Set local variable and remove from cache. set(CMAKE_BOOTSTRAP 1) @@ -441,7 +445,7 @@ macro (CMAKE_BUILD_UTILITIES) # Build jsoncpp library. if(CMAKE_USE_SYSTEM_JSONCPP) if(NOT CMAKE_VERSION VERSION_LESS 3.0) - include(${CMake_SOURCE_DIR}/Source/Modules/FindJsonCpp.cmake) + find_package(JsonCpp) else() message(FATAL_ERROR "CMAKE_USE_SYSTEM_JSONCPP requires CMake >= 3.0") endif() @@ -487,7 +491,7 @@ int main(void) { return 0; } if(CMAKE_USE_LIBUV) if(CMAKE_USE_SYSTEM_LIBUV) if(NOT CMAKE_VERSION VERSION_LESS 3.0) - include(${CMake_SOURCE_DIR}/Source/Modules/FindLibUV.cmake) + find_package(LibUV 1.0.0) else() message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBUV requires CMake >= 3.0") endif() diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 271f497..fa21a1f 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -121,6 +121,7 @@ Properties on Targets /prop_tgt/AUTORCC /prop_tgt/AUTORCC_OPTIONS /prop_tgt/BINARY_DIR + /prop_tgt/BUILD_RPATH /prop_tgt/BUILD_WITH_INSTALL_RPATH /prop_tgt/BUNDLE_EXTENSION /prop_tgt/BUNDLE diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index b74f867..f76c467 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -257,6 +257,7 @@ Variables that Control the Build /variable/CMAKE_AUTORCC_OPTIONS /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS + /variable/CMAKE_BUILD_RPATH /variable/CMAKE_BUILD_WITH_INSTALL_RPATH /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/prop_tgt/BUILD_RPATH.rst b/Help/prop_tgt/BUILD_RPATH.rst new file mode 100644 index 0000000..27393f5 --- /dev/null +++ b/Help/prop_tgt/BUILD_RPATH.rst @@ -0,0 +1,10 @@ +BUILD_RPATH +----------- + +A :ref:`;-list <CMake Language Lists>` specifying runtime path (``RPATH``) +entries to add to binaries linked in the build tree (for platforms that +support it). The entries will *not* be used for binaries in the install +tree. See also the :prop_tgt:`INSTALL_RPATH` target property. + +This property is initialized by the value of the variable +:variable:`CMAKE_BUILD_RPATH` if it is set when a target is created. diff --git a/Help/release/3.7.rst b/Help/release/3.7.rst index 9794267..3b8ade6 100644 --- a/Help/release/3.7.rst +++ b/Help/release/3.7.rst @@ -32,7 +32,7 @@ Generators with :ref:`Makefile Generators`. * The :generator:`Visual Studio 15` generator was added. This is - experimental and based on Preview 4 because this version of VS + experimental and based on Preview 5 because this version of VS has not been released. * :ref:`Visual Studio Generators` for VS 2010 and above learned to diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst new file mode 100644 index 0000000..e4cc01e --- /dev/null +++ b/Help/release/dev/0-sample-topic.rst @@ -0,0 +1,7 @@ +0-sample-topic +-------------- + +* This is a sample release note for the change in a topic. + Developers should add similar notes for each topic branch + making a noteworthy change. Each document should be named + and titled to match the topic name to avoid merge conflicts. diff --git a/Help/release/dev/add-BUILD_RPATH.rst b/Help/release/dev/add-BUILD_RPATH.rst new file mode 100644 index 0000000..0d69e45 --- /dev/null +++ b/Help/release/dev/add-BUILD_RPATH.rst @@ -0,0 +1,6 @@ +add-BUILD_RPATH +--------------- + +* A :variable:`CMAKE_BUILD_RPATH` variable and corresponding + :prop_tgt:`BUILD_RPATH` target property were added to support custom + ``RPATH`` locations to be added to binaries in the build tree. diff --git a/Help/release/dev/cpack-rpm-single-debuginfo.rst b/Help/release/dev/cpack-rpm-single-debuginfo.rst new file mode 100644 index 0000000..34a710d --- /dev/null +++ b/Help/release/dev/cpack-rpm-single-debuginfo.rst @@ -0,0 +1,11 @@ +cpack-rpm-single-debuginfo +-------------------------- + +* The :module:`CPackRPM` module learned to generate main component package + which forces generation of a rpm for defined component without component + suffix in filename and package name. + See :variable:`CPACK_RPM_MAIN_COMPONENT` variable. + +* The :module:`CPackRPM` module learned to generate a single debuginfo package + on demand even if components packagin is used. + See :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` variable. diff --git a/Help/release/index.rst b/Help/release/index.rst index 25c6c3e..30decd5 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -5,6 +5,8 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. +.. include:: dev.txt + Releases ======== diff --git a/Help/variable/CMAKE_BUILD_RPATH.rst b/Help/variable/CMAKE_BUILD_RPATH.rst new file mode 100644 index 0000000..f20eb41 --- /dev/null +++ b/Help/variable/CMAKE_BUILD_RPATH.rst @@ -0,0 +1,10 @@ +CMAKE_BUILD_RPATH +----------------- + +A :ref:`;-list <CMake Language Lists>` specifying runtime path (``RPATH``) +entries to add to binaries linked in the build tree (for platforms that +support it). The entries will *not* be used for binaries in the install +tree. See also the :variable:`CMAKE_INSTALL_RPATH` variable. + +This is used to initialize the :prop_tgt:`BUILD_RPATH` target property +for all targets. diff --git a/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst b/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst index 4aede03..33cdf6c 100644 --- a/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst +++ b/Help/variable/CMAKE_CODELITE_USE_TARGETS.rst @@ -3,5 +3,6 @@ CMAKE_CODELITE_USE_TARGETS Change the way the CodeLite generator creates projectfiles. -If this variable is set to ``ON`` the generator creates projectfiles -based on targets rather than projects. +If this variable evaluates to ``ON`` at the end of the top-level +``CMakeLists.txt`` file, the generator creates projectfiles based on targets +rather than projects. diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index 3bbaae9..6017ce3 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -95,6 +95,17 @@ # and it is up to the packager to set the variables in a manner that will # prevent such errors. # +# .. variable:: CPACK_RPM_MAIN_COMPONENT +# +# Main component that is packaged without component suffix. +# +# * Mandatory : NO +# * Default : - +# +# This variable can be set to any component or group name so that component or +# group rpm package is generated without component suffix in filename and +# package name. +# # .. variable:: CPACK_RPM_PACKAGE_VERSION # # The RPM package version. @@ -792,6 +803,26 @@ # * Mandatory : NO # * Default : - # +# .. variable:: CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE +# +# Create a single debuginfo package even if components packaging is set. +# +# * Mandatory : NO +# * Default : OFF +# +# When this variable is enabled it produces a single debuginfo package even if +# component packaging is enabled. +# +# When using this feature in combination with components packaging and there is +# more than one component this variable requires :variable:`CPACK_RPM_MAIN_COMPONENT` +# to be set. +# +# .. note:: +# +# If none of the :variable:`CPACK_RPM_<component>_DEBUGINFO_PACKAGE` variables +# is set then :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is automatically set to +# ``ON`` when :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` is set. +# # Packaging of sources (SRPM) # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ # @@ -1427,7 +1458,8 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR) execute_process(COMMAND "${OBJDUMP_EXECUTABLE}" -h ${WORKING_DIR}/${F} WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}" RESULT_VARIABLE OBJDUMP_EXEC_RESULT - OUTPUT_VARIABLE OBJDUMP_OUT) + OUTPUT_VARIABLE OBJDUMP_OUT + ERROR_QUIET) # Check that if the given file was executable or not if(NOT OBJDUMP_EXEC_RESULT) string(FIND "${OBJDUMP_OUT}" "debug" FIND_RESULT) @@ -1476,16 +1508,22 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR) endif() endforeach() - list(REMOVE_DUPLICATES mkdir_list_) - unset(TMP_RPM_DEBUGINFO_INSTALL) - foreach(part_ IN LISTS mkdir_list_) - string(APPEND TMP_RPM_DEBUGINFO_INSTALL "mkdir -p \"${part_}\"\n") - endforeach() + list(LENGTH mkdir_list_ len_) + if(len_) + list(REMOVE_DUPLICATES mkdir_list_) + unset(TMP_RPM_DEBUGINFO_INSTALL) + foreach(part_ IN LISTS mkdir_list_) + string(APPEND TMP_RPM_DEBUGINFO_INSTALL "mkdir -p \"${part_}\"\n") + endforeach() + endif() - list(REMOVE_DUPLICATES cp_list_) - foreach(part_ IN LISTS cp_list_) - string(APPEND TMP_RPM_DEBUGINFO_INSTALL "${part_}\n") - endforeach() + list(LENGTH cp_list_ len_) + if(len_) + list(REMOVE_DUPLICATES cp_list_) + foreach(part_ IN LISTS cp_list_) + string(APPEND TMP_RPM_DEBUGINFO_INSTALL "${part_}\n") + endforeach() + endif() if(NOT DEFINED CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS) set(CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS /usr /usr/src /usr/src/debug) @@ -1500,29 +1538,34 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR) message("CPackRPM:Debug: CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS= ${CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS}") endif() - list(REMOVE_DUPLICATES additional_sources_) - unset(additional_sources_all_) - foreach(source_ IN LISTS additional_sources_) - string(REPLACE "/" ";" split_source_ " ${source_}") - list(REMOVE_AT split_source_ 0) - unset(tmp_path_) - # Now generate all segments of the path - foreach(segment_ IN LISTS split_source_) - string(APPEND tmp_path_ "/${segment_}") - list(APPEND additional_sources_all_ "${tmp_path_}") + list(LENGTH additional_sources_ len_) + if(len_) + list(REMOVE_DUPLICATES additional_sources_) + unset(additional_sources_all_) + foreach(source_ IN LISTS additional_sources_) + string(REPLACE "/" ";" split_source_ " ${source_}") + list(REMOVE_AT split_source_ 0) + unset(tmp_path_) + # Now generate all segments of the path + foreach(segment_ IN LISTS split_source_) + string(APPEND tmp_path_ "/${segment_}") + list(APPEND additional_sources_all_ "${tmp_path_}") + endforeach() endforeach() - endforeach() - list(REMOVE_DUPLICATES additional_sources_all_) - list(REMOVE_ITEM additional_sources_all_ ${CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS}) + list(REMOVE_DUPLICATES additional_sources_all_) + list(REMOVE_ITEM additional_sources_all_ + ${CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS}) - unset(TMP_DEBUGINFO_ADDITIONAL_SOURCES) - foreach(source_ IN LISTS additional_sources_all_) - string(APPEND TMP_DEBUGINFO_ADDITIONAL_SOURCES "${source_}\n") - endforeach() + unset(TMP_DEBUGINFO_ADDITIONAL_SOURCES) + foreach(source_ IN LISTS additional_sources_all_) + string(APPEND TMP_DEBUGINFO_ADDITIONAL_SOURCES "${source_}\n") + endforeach() + endif() set(TMP_RPM_DEBUGINFO_INSTALL "${TMP_RPM_DEBUGINFO_INSTALL}" PARENT_SCOPE) - set(TMP_DEBUGINFO_ADDITIONAL_SOURCES "${TMP_DEBUGINFO_ADDITIONAL_SOURCES}" PARENT_SCOPE) + set(TMP_DEBUGINFO_ADDITIONAL_SOURCES "${TMP_DEBUGINFO_ADDITIONAL_SOURCES}" + PARENT_SCOPE) endfunction() function(cpack_rpm_variable_fallback OUTPUT_VAR_NAME) @@ -1637,10 +1680,16 @@ function(cpack_rpm_generate_package) endif() if(CPACK_RPM_PACKAGE_COMPONENT) - string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}") - cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_NAME" - "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME" - "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME") + string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}" + CPACK_RPM_MAIN_COMPONENT_UPPER) + + if(NOT CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER) + string(APPEND CPACK_RPM_PACKAGE_NAME "-${CPACK_RPM_PACKAGE_COMPONENT}") + + cpack_rpm_variable_fallback("CPACK_RPM_PACKAGE_NAME" + "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_NAME" + "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME") + endif() endif() # CPACK_RPM_PACKAGE_VERSION (mandatory) @@ -2047,7 +2096,7 @@ function(cpack_rpm_generate_package) "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_PACKAGE" "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_PACKAGE" "CPACK_RPM_DEBUGINFO_PACKAGE") - if(CPACK_RPM_DEBUGINFO_PACKAGE) + if(CPACK_RPM_DEBUGINFO_PACKAGE OR (CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND NOT GENERATE_SPEC_PARTS)) cpack_rpm_variable_fallback("CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX" "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_BUILD_SOURCE_DIRS_PREFIX" "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_BUILD_SOURCE_DIRS_PREFIX" @@ -2055,9 +2104,81 @@ function(cpack_rpm_generate_package) if(NOT CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX) set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/src/debug/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}") endif() - cpack_rpm_debugsymbol_check("${CPACK_RPM_INSTALL_FILES}" "${WDIR}") - set(TMP_RPM_DEBUGINFO " + if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS) + file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.files" + "${CPACK_RPM_INSTALL_FILES}") + else() + if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND CPACK_RPM_PACKAGE_COMPONENT) + # this part is only required by components packaging - with monolithic + # packages we can be certain that there are no other components present + # so CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is a noop + if(CPACK_RPM_DEBUGINFO_PACKAGE) + # only add current package files to debuginfo list if debuginfo + # generation is enabled for current package + set(install_files_ "${CPACK_RPM_INSTALL_FILES}") + else() + unset(install_files_) + endif() + + file(GLOB files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.files") + + foreach(f_ IN LISTS files_) + file(READ "${f_}" tmp_) + string(APPEND install_files_ ";${tmp_}") + endforeach() + + # if there were other components/groups so we need to move files from them + # to current component otherwise those files won't be found + file(GLOB components_ LIST_DIRECTORIES true RELATIVE + "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}" + "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/*") + foreach(component_ IN LISTS components_) + string(TOUPPER "${component_}" component_dir_upper_) + if(component_dir_upper_ STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER) + # skip current component + continue() + endif() + + cmake_policy(PUSH) + cmake_policy(SET CMP0009 NEW) + file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES false RELATIVE + "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}" + "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/*") + cmake_policy(POP) + + foreach(f_ IN LISTS files_for_move_) + get_filename_component(dir_path_ "${f_}" DIRECTORY) + set(src_file_ + "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/${f_}") + + # check that we are not overriding an existing file that doesn't + # match the file that we want to copy + if(EXISTS "${src_file_}" AND EXISTS "${WDIR}/${f_}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E compare_files "${src_file_}" "${WDIR}/${f_}" + RESULT_VARIABLE res_ + ) + if(res_) + message(FATAL_ERROR "CPackRPM:Error: File on path '${WDIR}/${f_}'" + " already exists but is a different than the one in component" + " '${component_}'! Packages will not be generated.") + endif() + endif() + + file(MAKE_DIRECTORY "${WDIR}/${dir_path_}") + file(RENAME "${src_file_}" + "${WDIR}/${f_}") + endforeach() + endforeach() + + cpack_rpm_debugsymbol_check("${install_files_}" "${WDIR}") + else() + cpack_rpm_debugsymbol_check("${CPACK_RPM_INSTALL_FILES}" "${WDIR}") + endif() + + if(TMP_DEBUGINFO_ADDITIONAL_SOURCES) + set(TMP_RPM_DEBUGINFO " # Modified version of %%debug_package macro # defined in /usr/lib/rpm/macros as that one # can't handle injection of extra source files. @@ -2076,6 +2197,15 @@ package or when debugging this package. ${TMP_DEBUGINFO_ADDITIONAL_SOURCES} %endif ") + elseif(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE) + message(AUTHOR_WARNING "CPackRPM:Warning: debuginfo package was requested" + " but will not be generated as no source files were found!") + else() + message(AUTHOR_WARNING "CPackRPM:Warning: debuginfo package was requested" + " but will not be generated as no source files were found! Component: '" + "${CPACK_RPM_PACKAGE_COMPONENT}'.") + endif() + endif() endif() # Prepare install files @@ -2152,12 +2282,25 @@ ${TMP_DEBUGINFO_ADDITIONAL_SOURCES} cmake_policy(POP) else() # old file name format for back compatibility - set(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}") + string(TOUPPER "${CPACK_RPM_MAIN_COMPONENT}" + CPACK_RPM_MAIN_COMPONENT_UPPER) + + if(CPACK_RPM_MAIN_COMPONENT_UPPER STREQUAL CPACK_RPM_PACKAGE_COMPONENT_UPPER) + # this is the main component so ignore the component filename part + set(CPACK_RPM_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.rpm") + else() + set(CPACK_RPM_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}") + endif() endif() # else example: #set(CPACK_RPM_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}-${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") - if(NOT CPACK_RPM_DEBUGINFO_PACKAGE) + if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS) + string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" expected_filename_) + + file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.rpm_name" + "${expected_filename_};${CPACK_RPM_FILE_NAME}") + elseif(NOT CPACK_RPM_DEBUGINFO_PACKAGE) set(FILE_NAME_DEFINE "%define _rpmfilename ${CPACK_RPM_FILE_NAME}") endif() endif() @@ -2252,7 +2395,54 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ \@CPACK_RPM_SPEC_CHANGELOG\@ " ) + + elseif(GENERATE_SPEC_PARTS) # binary rpm with single debuginfo package + file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in + "# -*- rpm-spec -*- +%package -n \@CPACK_RPM_PACKAGE_NAME\@ +Summary: \@CPACK_RPM_PACKAGE_SUMMARY\@ +Version: \@CPACK_RPM_PACKAGE_VERSION\@ +Release: \@CPACK_RPM_PACKAGE_RELEASE\@ +License: \@CPACK_RPM_PACKAGE_LICENSE\@ +Group: \@CPACK_RPM_PACKAGE_GROUP\@ +Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ + +\@TMP_RPM_URL\@ +\@TMP_RPM_REQUIRES\@ +\@TMP_RPM_REQUIRES_PRE\@ +\@TMP_RPM_REQUIRES_POST\@ +\@TMP_RPM_REQUIRES_PREUN\@ +\@TMP_RPM_REQUIRES_POSTUN\@ +\@TMP_RPM_PROVIDES\@ +\@TMP_RPM_OBSOLETES\@ +\@TMP_RPM_CONFLICTS\@ +\@TMP_RPM_AUTOPROV\@ +\@TMP_RPM_AUTOREQ\@ +\@TMP_RPM_AUTOREQPROV\@ +\@TMP_RPM_BUILDARCH\@ +\@TMP_RPM_PREFIXES\@ + +%description -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_PACKAGE_DESCRIPTION\@ + +%files -n \@CPACK_RPM_PACKAGE_NAME\@ +%defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@) +\@CPACK_RPM_INSTALL_FILES\@ +\@CPACK_RPM_ABSOLUTE_INSTALL_FILES\@ +\@CPACK_RPM_USER_INSTALL_FILES\@ +" + ) + else() # binary rpm + if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE) + # find generated spec file and take its name + file(GLOB spec_files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.spec") + + foreach(f_ IN LISTS spec_files_) + file(READ "${f_}" tmp_) + string(APPEND TMP_OTHER_COMPONENTS "\n${tmp_}\n") + endforeach() + endif() # We should generate a USER spec file template: # - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE @@ -2338,6 +2528,8 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT %changelog \@CPACK_RPM_SPEC_CHANGELOG\@ + +\@TMP_OTHER_COMPONENTS\@ " ) endif() @@ -2364,60 +2556,90 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT configure_file(${CPACK_RPM_BINARY_SPECFILE}.in ${CPACK_RPM_BINARY_SPECFILE} @ONLY) endif() - if(RPMBUILD_EXECUTABLE) - # Now call rpmbuild using the SPECFILE - execute_process( - COMMAND "${RPMBUILD_EXECUTABLE}" ${RPMBUILD_FLAGS} - --define "_topdir ${CPACK_RPM_DIRECTORY}" - --buildroot "%_topdir/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" - --target "${CPACK_RPM_PACKAGE_ARCHITECTURE}" - "${CPACK_RPM_BINARY_SPECFILE}" - WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" - RESULT_VARIABLE CPACK_RPMBUILD_EXEC_RESULT - ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err" - OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out") - if(CPACK_RPM_PACKAGE_DEBUG OR CPACK_RPMBUILD_EXEC_RESULT) - file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err RPMBUILDERR) - file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out RPMBUILDOUT) - message("CPackRPM:Debug: You may consult rpmbuild logs in: ") - message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err") - message("CPackRPM:Debug: *** ${RPMBUILDERR} ***") - message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out") - message("CPackRPM:Debug: *** ${RPMBUILDOUT} ***") + if(NOT GENERATE_SPEC_PARTS) # generate package + if(RPMBUILD_EXECUTABLE) + # Now call rpmbuild using the SPECFILE + execute_process( + COMMAND "${RPMBUILD_EXECUTABLE}" ${RPMBUILD_FLAGS} + --define "_topdir ${CPACK_RPM_DIRECTORY}" + --buildroot "%_topdir/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" + --target "${CPACK_RPM_PACKAGE_ARCHITECTURE}" + "${CPACK_RPM_BINARY_SPECFILE}" + WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}" + RESULT_VARIABLE CPACK_RPMBUILD_EXEC_RESULT + ERROR_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err" + OUTPUT_FILE "${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out") + if(CPACK_RPM_PACKAGE_DEBUG OR CPACK_RPMBUILD_EXEC_RESULT) + file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err RPMBUILDERR) + file(READ ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out RPMBUILDOUT) + message("CPackRPM:Debug: You may consult rpmbuild logs in: ") + message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.err") + message("CPackRPM:Debug: *** ${RPMBUILDERR} ***") + message("CPackRPM:Debug: - ${CPACK_TOPLEVEL_DIRECTORY}/rpmbuild${CPACK_RPM_PACKAGE_NAME}.out") + message("CPackRPM:Debug: *** ${RPMBUILDOUT} ***") + endif() + else() + if(ALIEN_EXECUTABLE) + message(FATAL_ERROR "RPM packaging through alien not done (yet)") + endif() endif() - else() - if(ALIEN_EXECUTABLE) - message(FATAL_ERROR "RPM packaging through alien not done (yet)") + + # find generated rpm files and take their names + cmake_policy(PUSH) + # Tell file(GLOB_RECURSE) not to follow directory symlinks + # even if the project does not set this policy to NEW. + cmake_policy(SET CMP0009 NEW) + file(GLOB_RECURSE GENERATED_FILES "${CPACK_RPM_DIRECTORY}/RPMS/*.rpm" + "${CPACK_RPM_DIRECTORY}/SRPMS/*.rpm") + cmake_policy(POP) + + if(NOT GENERATED_FILES) + message(FATAL_ERROR "RPM package was not generated! ${CPACK_RPM_DIRECTORY}") endif() - endif() - # find generated rpm files and take their names - cmake_policy(PUSH) - # Tell file(GLOB_RECURSE) not to follow directory symlinks - # even if the project does not set this policy to NEW. - cmake_policy(SET CMP0009 NEW) - file(GLOB_RECURSE GENERATED_FILES "${CPACK_RPM_DIRECTORY}/RPMS/*.rpm" - "${CPACK_RPM_DIRECTORY}/SRPMS/*.rpm") - cmake_policy(POP) + unset(expected_filenames_) + unset(filenames_) + if(CPACK_RPM_DEBUGINFO_PACKAGE AND NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT") + string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" efn_) + list(APPEND expected_filenames_ "${efn_}") + list(APPEND filenames_ "${CPACK_RPM_FILE_NAME}") + endif() - if(NOT GENERATED_FILES) - message(FATAL_ERROR "RPM package was not generated! ${CPACK_RPM_DIRECTORY}") - endif() + # check if other files have to be renamed + file(GLOB rename_files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.rpm_name") + if(rename_files_) + foreach(f_ IN LISTS rename_files_) + file(READ "${f_}" tmp_) + list(GET tmp_ 0 efn_) + list(APPEND expected_filenames_ "${efn_}") + list(GET tmp_ 1 fn_) + list(APPEND filenames_ "${fn_}") + endforeach() + endif() - if(CPACK_RPM_DEBUGINFO_PACKAGE AND NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT") - string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" EXPECTED_FILENAME) + if(expected_filenames_) + foreach(F IN LISTS GENERATED_FILES) + unset(matched_) + foreach(expected_ IN LISTS expected_filenames_) + if(F MATCHES ".*/${expected_}") + list(FIND expected_filenames_ "${expected_}" idx_) + list(GET filenames_ ${idx_} filename_) + get_filename_component(FILE_PATH "${F}" DIRECTORY) + file(RENAME "${F}" "${FILE_PATH}/${filename_}") + list(APPEND new_files_list_ "${FILE_PATH}/${filename_}") + set(matched_ "YES") + + break() + endif() + endforeach() - foreach(F IN LISTS GENERATED_FILES) - if(F MATCHES ".*/${EXPECTED_FILENAME}") - get_filename_component(FILE_PATH "${F}" DIRECTORY) - file(RENAME "${F}" "${FILE_PATH}/${CPACK_RPM_FILE_NAME}") - list(APPEND new_files_list_ "${FILE_PATH}/${CPACK_RPM_FILE_NAME}") - else() - list(APPEND new_files_list_ "${F}") - endif() - endforeach() + if(NOT matched_) + list(APPEND new_files_list_ "${F}") + endif() + endforeach() - set(GENERATED_FILES "${new_files_list_}") + set(GENERATED_FILES "${new_files_list_}") + endif() endif() set(GEN_CPACK_OUTPUT_FILES "${GENERATED_FILES}" PARENT_SCOPE) diff --git a/Modules/Platform/Android/ndk-stl-c++.cmake b/Modules/Platform/Android/ndk-stl-c++.cmake index 14748a1..cb9fd68 100644 --- a/Modules/Platform/Android/ndk-stl-c++.cmake +++ b/Modules/Platform/Android/ndk-stl-c++.cmake @@ -3,7 +3,13 @@ set(_ANDROID_STL_RTTI 1) set(_ANDROID_STL_EXCEPTIONS 1) macro(__android_stl_cxx lang filename) # Add the include directory. - __android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include" 1) + if(EXISTS "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include/cstddef") + # r12 and below + __android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include" 1) + else() + # r13 and above + __android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/include" 1) + endif() # Add a secondary include directory if it exists. __android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/android/support/include" 0) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ec49481..e574957 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -384,6 +384,8 @@ set(SRCS cm_sha2.c cm_utf8.h cm_utf8.c + cm_codecvt.hxx + cm_codecvt.cxx ) set(COMMAND_INCLUDES "#include \"cmTargetPropCommandBase.cxx\"\n") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6cb0fea..ee2f4af 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 7) -set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 1) +set(CMake_VERSION_PATCH 20161007) +#set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 9232ffc..db20998 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -32,16 +32,6 @@ class cmMakefile; cmCPackLog_msg.str().c_str()); \ } while (0) -#ifdef cerr -#undef cerr -#endif -#define cerr no_cerr_use_cmCPack_Log - -#ifdef cout -#undef cout -#endif -#define cout no_cout_use_cmCPack_Log - /** \class cmCPackGenerator * \brief A superclass of all CPack Generators * diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx index be429fe..317f613 100644 --- a/Source/CPack/cmCPackLog.cxx +++ b/Source/CPack/cmCPackLog.cxx @@ -15,8 +15,6 @@ cmCPackLog::cmCPackLog() this->NewLine = true; this->LastTag = cmCPackLog::NOTAG; -#undef cerr -#undef cout this->DefaultOutput = &std::cout; this->DefaultError = &std::cerr; diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h index 0831843..370879d 100644 --- a/Source/CPack/cmCPackLog.h +++ b/Source/CPack/cmCPackLog.h @@ -19,16 +19,6 @@ (ctSelf)->Log(logType, __FILE__, __LINE__, cmCPackLog_msg.str().c_str()); \ } while (0) -#ifdef cerr -#undef cerr -#endif -#define cerr no_cerr_use_cmCPack_Log - -#ifdef cout -#undef cout -#endif -#define cout no_cout_use_cmCPack_Log - /** \class cmCPackLog * \brief A container for CPack generators * diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index bd55206..9817327 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -105,39 +105,224 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - // The default behavior is to have one package by component group - // unless CPACK_COMPONENTS_IGNORE_GROUP is specified. - if (!ignoreGroup) { - std::map<std::string, cmCPackComponentGroup>::iterator compGIt; - for (compGIt = this->ComponentGroups.begin(); - compGIt != this->ComponentGroups.end(); ++compGIt) { - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " - << compGIt->first << std::endl); - retval &= PackageOnePack(initialTopLevel, compGIt->first); + const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); + + if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") && + !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) { + // check if we need to set CPACK_RPM_DEBUGINFO_PACKAGE because non of + // the components is setting per component debuginfo package variable + bool shouldSet = true; + + if (ignoreGroup) { + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); compIt != this->Components.end(); + ++compIt) { + std::string component(compIt->first); + std::transform(component.begin(), component.end(), component.begin(), + ::toupper); + + if (this->IsOn("CPACK_RPM_" + compIt->first + "_DEBUGINFO_PACKAGE") || + this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) { + shouldSet = false; + break; + } + } + } else { + std::map<std::string, cmCPackComponentGroup>::iterator compGIt; + for (compGIt = this->ComponentGroups.begin(); + compGIt != this->ComponentGroups.end(); ++compGIt) { + std::string component(compGIt->first); + std::transform(component.begin(), component.end(), component.begin(), + ::toupper); + + if (this->IsOn("CPACK_RPM_" + compGIt->first + "_DEBUGINFO_PACKAGE") || + this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) { + shouldSet = false; + break; + } + } + + if (shouldSet) { + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); + compIt != this->Components.end(); ++compIt) { + // Does the component belong to a group? + if (compIt->second.Group == CM_NULLPTR) { + std::string component(compIt->first); + std::transform(component.begin(), component.end(), + component.begin(), ::toupper); + + if (this->IsOn("CPACK_RPM_" + compIt->first + + "_DEBUGINFO_PACKAGE") || + this->IsOn("CPACK_RPM_" + component + "_DEBUGINFO_PACKAGE")) { + shouldSet = false; + break; + } + } + } + } + } + + if (shouldSet) { + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Setting " + << "CPACK_RPM_DEBUGINFO_PACKAGE because " + << "CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is set but " + << " none of the " + << "CPACK_RPM_<component>_DEBUGINFO_PACKAGE variables " + << "are set." << std::endl); + this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON"); } - // Handle Orphan components (components not belonging to any groups) - std::map<std::string, cmCPackComponent>::iterator compIt; - for (compIt = this->Components.begin(); compIt != this->Components.end(); - ++compIt) { - // Does the component belong to a group? - if (compIt->second.Group == CM_NULLPTR) { - cmCPackLogger( - cmCPackLog::LOG_VERBOSE, "Component <" - << compIt->second.Name - << "> does not belong to any group, package it separately." - << std::endl); + } + + if (mainComponent) { + if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) { + this->SetOption("GENERATE_SPEC_PARTS", "ON"); + } + + std::string mainComponentUpper(mainComponent); + std::transform(mainComponentUpper.begin(), mainComponentUpper.end(), + mainComponentUpper.begin(), ::toupper); + + // The default behavior is to have one package by component group + // unless CPACK_COMPONENTS_IGNORE_GROUP is specified. + if (!ignoreGroup) { + std::map<std::string, cmCPackComponentGroup>::iterator mainCompGIt = + this->ComponentGroups.end(); + + std::map<std::string, cmCPackComponentGroup>::iterator compGIt; + for (compGIt = this->ComponentGroups.begin(); + compGIt != this->ComponentGroups.end(); ++compGIt) { + std::string component(compGIt->first); + std::transform(component.begin(), component.end(), component.begin(), + ::toupper); + + if (mainComponentUpper == component) { + // main component will be handled last + mainCompGIt = compGIt; + continue; + } + + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " + << compGIt->first << std::endl); + retval &= PackageOnePack(initialTopLevel, compGIt->first); + } + // Handle Orphan components (components not belonging to any groups) + std::map<std::string, cmCPackComponent>::iterator mainCompIt = + this->Components.end(); + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); compIt != this->Components.end(); + ++compIt) { + // Does the component belong to a group? + if (compIt->second.Group == CM_NULLPTR) { + std::string component(compIt->first); + std::transform(component.begin(), component.end(), component.begin(), + ::toupper); + + if (mainComponentUpper == component) { + // main component will be handled last + mainCompIt = compIt; + continue; + } + + cmCPackLogger( + cmCPackLog::LOG_VERBOSE, "Component <" + << compIt->second.Name + << "> does not belong to any group, package it separately." + << std::endl); + retval &= PackageOnePack(initialTopLevel, compIt->first); + } + } + + if (retval) { + this->SetOption("GENERATE_SPEC_PARTS", "OFF"); + + if (mainCompGIt != this->ComponentGroups.end()) { + retval &= PackageOnePack(initialTopLevel, mainCompGIt->first); + } else if (mainCompIt != this->Components.end()) { + retval &= PackageOnePack(initialTopLevel, mainCompIt->first); + } else { + cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set" + << " to non existing component.\n"); + retval = 0; + } + } + } + // CPACK_COMPONENTS_IGNORE_GROUPS is set + // We build 1 package per component + else { + std::map<std::string, cmCPackComponent>::iterator mainCompIt = + this->Components.end(); + + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); compIt != this->Components.end(); + ++compIt) { + std::string component(compIt->first); + std::transform(component.begin(), component.end(), component.begin(), + ::toupper); + + if (mainComponentUpper == component) { + // main component will be handled last + mainCompIt = compIt; + continue; + } + retval &= PackageOnePack(initialTopLevel, compIt->first); } + + if (retval) { + this->SetOption("GENERATE_SPEC_PARTS", "OFF"); + + if (mainCompIt != this->Components.end()) { + retval &= PackageOnePack(initialTopLevel, mainCompIt->first); + } else { + cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set" + << " to non existing component.\n"); + retval = 0; + } + } } - } - // CPACK_COMPONENTS_IGNORE_GROUPS is set - // We build 1 package per component - else { - std::map<std::string, cmCPackComponent>::iterator compIt; - for (compIt = this->Components.begin(); compIt != this->Components.end(); - ++compIt) { - retval &= PackageOnePack(initialTopLevel, compIt->first); + } else if (!this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") || + this->Components.size() == 1) { + // The default behavior is to have one package by component group + // unless CPACK_COMPONENTS_IGNORE_GROUP is specified. + if (!ignoreGroup) { + std::map<std::string, cmCPackComponentGroup>::iterator compGIt; + for (compGIt = this->ComponentGroups.begin(); + compGIt != this->ComponentGroups.end(); ++compGIt) { + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " + << compGIt->first << std::endl); + retval &= PackageOnePack(initialTopLevel, compGIt->first); + } + // Handle Orphan components (components not belonging to any groups) + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); compIt != this->Components.end(); + ++compIt) { + // Does the component belong to a group? + if (compIt->second.Group == CM_NULLPTR) { + cmCPackLogger( + cmCPackLog::LOG_VERBOSE, "Component <" + << compIt->second.Name + << "> does not belong to any group, package it separately." + << std::endl); + retval &= PackageOnePack(initialTopLevel, compIt->first); + } + } + } + // CPACK_COMPONENTS_IGNORE_GROUPS is set + // We build 1 package per component + else { + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt = this->Components.begin(); compIt != this->Components.end(); + ++compIt) { + retval &= PackageOnePack(initialTopLevel, compIt->first); + } } + } else { + cmCPackLogger( + cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT not set but" + << " it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE" + << " being set.\n"); + retval = 0; } if (retval) { @@ -156,6 +341,10 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne( packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); + if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) { + this->SetOption("CPACK_RPM_DEBUGINFO_PACKAGE", "ON"); + } + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging all groups in one package..." "(CPACK_COMPONENTS_ALL_[GROUPS_]IN_ONE_PACKAGE is set)" diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 5c45b14..a3281ab 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -415,9 +415,7 @@ int main(int argc, char const* const* argv) } doc.SetSection("Generators", v); -#undef cout return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; -#define cout no_cout_use_cmCPack_Log } if (cmSystemTools::GetErrorOccuredFlag()) { diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index b37db30..0052a16 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -375,11 +375,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) xml.StartElement("DefectList"); for (cc = 0; cc < this->GlobalResults.size(); cc++) { if (this->GlobalResults[cc]) { -#ifdef cerr -#undef cerr -#endif std::cerr.width(35); -#define cerr no_cerr cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, this->ResultStringsLong[cc] << " - " << this->GlobalResults[cc] << std::endl, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 1824d94..7dc9e33 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2651,13 +2651,6 @@ static const char* cmCTestStringLogType[] = { "DEBUG", "ERROR_MESSAGE", CM_NULLPTR }; -#ifdef cerr -#undef cerr -#endif -#ifdef cout -#undef cout -#endif - #define cmCTestLogOutputFileLine(stream) \ if (this->ShowLineNumbers) { \ (stream) << std::endl << file << ":" << line << " "; \ diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 6887a31..14ea1a9 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -75,8 +75,10 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags) // Append the flag and value. Use ConvertToLinkReference to help // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; - flag += (this->LocalGenerator->ConvertToLinkReference( - this->ModuleDefinitionFile->GetFullPath())); + flag += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->ConvertToLinkReference( + this->ModuleDefinitionFile->GetFullPath()), + cmOutputConverter::SHELL); this->LocalGenerator->AppendFlags(flags, flag); } diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index dc8236d..0807ef8 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1710,6 +1710,12 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH"); cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); } + if (use_build_rpath) { + // Add directories explicitly specified by user + if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) { + cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted); + } + } if (use_build_rpath || use_link_rpath) { std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); const char* stagePath = diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index c1c8880..aaa9d3a 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -198,16 +198,13 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, stamp += ".mod.stamp"; fcStream << "\n"; fcStream << " \"" - << this->LocalGenerator->ConvertToRelativePath(currentBinDir, - mod_lower) + << this->MaybeConvertToRelativePath(currentBinDir, mod_lower) << "\"\n"; fcStream << " \"" - << this->LocalGenerator->ConvertToRelativePath(currentBinDir, - mod_upper) + << this->MaybeConvertToRelativePath(currentBinDir, mod_upper) << "\"\n"; fcStream << " \"" - << this->LocalGenerator->ConvertToRelativePath(currentBinDir, - stamp) + << this->MaybeConvertToRelativePath(currentBinDir, stamp) << "\"\n"; } fcStream << " )\n"; @@ -323,17 +320,16 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, // Write the include dependencies to the output stream. std::string binDir = this->LocalGenerator->GetBinaryDirectory(); - std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj); + std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj); std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i.c_str()); internalDepends << obj_i << std::endl; internalDepends << " " << src << std::endl; for (std::set<std::string>::const_iterator i = info.Includes.begin(); i != info.Includes.end(); ++i) { - makeDepends - << obj_m << ": " - << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, *i).c_str()) - << std::endl; + makeDepends << obj_m << ": " + << cmSystemTools::ConvertToOutputPath( + this->MaybeConvertToRelativePath(binDir, *i).c_str()) + << std::endl; internalDepends << " " << *i << std::endl; } makeDepends << std::endl; @@ -359,7 +355,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, proxy += *i; proxy += ".mod.proxy"; proxy = cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, proxy).c_str()); + this->MaybeConvertToRelativePath(binDir, proxy).c_str()); // since we require some things add them to our list of requirements makeDepends << obj_m << ".requires: " << proxy << std::endl; @@ -375,8 +371,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, if (!required->second.empty()) { // This module is known. Depend on its timestamp file. std::string stampFile = cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, required->second) - .c_str()); + this->MaybeConvertToRelativePath(binDir, required->second).c_str()); makeDepends << obj_m << ": " << stampFile << "\n"; } else { // This module is not known to CMake. Try to locate it where @@ -384,7 +379,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, std::string module; if (this->FindModule(*i, module)) { module = cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, module).c_str()); + this->MaybeConvertToRelativePath(binDir, module).c_str()); makeDepends << obj_m << ": " << module << "\n"; } } @@ -398,7 +393,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, proxy += *i; proxy += ".mod.proxy"; proxy = cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, proxy).c_str()); + this->MaybeConvertToRelativePath(binDir, proxy).c_str()); makeDepends << proxy << ": " << obj_m << ".provides" << std::endl; } @@ -420,14 +415,14 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, modFile += "/"; modFile += *i; modFile = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath(binDir, modFile), + this->MaybeConvertToRelativePath(binDir, modFile), cmOutputConverter::SHELL); std::string stampFile = stamp_dir; stampFile += "/"; stampFile += m; stampFile += ".mod.stamp"; stampFile = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath(binDir, stampFile), + this->MaybeConvertToRelativePath(binDir, stampFile), cmOutputConverter::SHELL); makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile << " " << stampFile; @@ -448,7 +443,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, std::string driver = this->TargetDirectory; driver += "/build"; driver = cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, driver).c_str()); + this->MaybeConvertToRelativePath(binDir, driver).c_str()); makeDepends << driver << ": " << obj_m << ".provides.build\n"; } @@ -708,3 +703,13 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, // content. return cmFortranStreamsDiffer(finModFile, finStampFile); } + +std::string cmDependsFortran::MaybeConvertToRelativePath( + std::string const& base, std::string const& path) +{ + if (!cmOutputConverter::ContainedInDirectory( + base, path, this->LocalGenerator->GetStateSnapshot().GetDirectory())) { + return path; + } + return cmOutputConverter::ForceToRelativePath(base, path); +} diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 8d347f4..90b82d4 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -78,6 +78,9 @@ protected: private: cmDependsFortran(cmDependsFortran const&); // Purposely not implemented. void operator=(cmDependsFortran const&); // Purposely not implemented. + + std::string MaybeConvertToRelativePath(std::string const& base, + std::string const& path); }; #endif diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 2d86674..0655da9 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -132,18 +132,13 @@ public: // Forward to the per-class implementation. virtual unsigned int GetNumberOfSections() const = 0; - virtual unsigned int GetDynamicEntryCount() = 0; virtual unsigned long GetDynamicEntryPosition(int j) = 0; + virtual cmELF::DynamicEntryList GetDynamicEntries() = 0; + virtual std::vector<char> EncodeDynamicEntries( + const cmELF::DynamicEntryList&) = 0; virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0; virtual void PrintInfo(std::ostream& os) const = 0; - bool ReadBytes(unsigned long pos, unsigned long size, char* buf) - { - this->Stream.seekg(pos); - this->Stream.read(buf, size); - return !this->Stream.fail(); - } - // Lookup the SONAME in the DYNAMIC section. StringEntry const* GetSOName() { @@ -246,10 +241,13 @@ public: return static_cast<unsigned int>(this->ELFHeader.e_shnum); } - // Get the file position and size of a dynamic section entry. - unsigned int GetDynamicEntryCount() CM_OVERRIDE; + // Get the file position of a dynamic section entry. unsigned long GetDynamicEntryPosition(int j) CM_OVERRIDE; + cmELF::DynamicEntryList GetDynamicEntries() CM_OVERRIDE; + std::vector<char> EncodeDynamicEntries(const cmELF::DynamicEntryList&) + CM_OVERRIDE; + // Lookup a string from the dynamic section with the given tag. StringEntry const* GetDynamicSectionString(unsigned int tag) CM_OVERRIDE; @@ -289,6 +287,10 @@ public: } private: + // ByteSwap(ELF_Dyn) assumes d_val and d_ptr are the same size + typedef char dyn_size_assert + [sizeof(ELF_Dyn().d_un.d_val) == sizeof(ELF_Dyn().d_un.d_ptr) ? 1 : -1]; + void ByteSwap(ELF_Ehdr& elf_header) { cmELFByteSwap(elf_header.e_type); @@ -323,121 +325,7 @@ private: void ByteSwap(ELF_Dyn& dyn) { cmELFByteSwap(dyn.d_tag); - switch (dyn.d_tag) { - case DT_NULL: /* dyn.d_un ignored */ - break; - case DT_NEEDED: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_PLTRELSZ: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_PLTGOT: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_HASH: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_STRTAB: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_SYMTAB: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_RELA: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_RELASZ: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_RELAENT: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_STRSZ: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_SYMENT: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_INIT: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_FINI: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_SONAME: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_RPATH: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_SYMBOLIC: /* dyn.d_un ignored */ - break; - case DT_REL: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_RELSZ: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_RELENT: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_PLTREL: - cmELFByteSwap(dyn.d_un.d_val); - break; - case DT_DEBUG: - cmELFByteSwap(dyn.d_un.d_ptr); - break; - case DT_TEXTREL: /* dyn.d_un ignored */ - break; - case DT_JMPREL: - cmELFByteSwap(dyn.d_un.d_ptr); - break; -#ifdef T_BIND_NOW - case T_BIND_NOW: /* dyn.d_un ignored */ - break; -#endif -#ifdef DT_INIT_ARRAY - case DT_INIT_ARRAY: - cmELFByteSwap(dyn.d_un.d_ptr); - break; -#endif -#ifdef DT_FINI_ARRAY - case DT_FINI_ARRAY: - cmELFByteSwap(dyn.d_un.d_ptr); - break; -#endif -#ifdef DT_INIT_ARRAYSZ - case DT_INIT_ARRAYSZ: - cmELFByteSwap(dyn.d_un.d_val); - break; -#endif -#ifdef DT_FINI_ARRAYSZ - case DT_FINI_ARRAYSZ: - cmELFByteSwap(dyn.d_un.d_val); - break; -#endif -#ifdef DT_RUNPATH - case DT_RUNPATH: - cmELFByteSwap(dyn.d_un.d_val); - break; -#endif -#ifdef DT_FLAGS - case DT_FLAGS: - cmELFByteSwap(dyn.d_un.d_val); - break; -#endif -#ifdef DT_PREINIT_ARRAY - case DT_PREINIT_ARRAY: - cmELFByteSwap(dyn.d_un.d_ptr); - break; -#endif -#ifdef DT_PREINIT_ARRAYSZ - case DT_PREINIT_ARRAYSZ: - cmELFByteSwap(dyn.d_un.d_val); - break; -#endif - } + cmELFByteSwap(dyn.d_un.d_val); } bool FileTypeValid(ELF_Half et) @@ -636,30 +524,64 @@ bool cmELFInternalImpl<Types>::LoadDynamicSection() } template <class Types> -unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount() +unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j) { if (!this->LoadDynamicSection()) { return 0; } - for (unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i) { - if (this->DynamicSectionEntries[i].d_tag == DT_NULL) { - return i; - } + if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) { + return 0; } - return static_cast<unsigned int>(this->DynamicSectionEntries.size()); + ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; + return static_cast<unsigned long>(sec.sh_offset + sec.sh_entsize * j); } template <class Types> -unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j) +cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries() { + cmELF::DynamicEntryList result; + + // Ensure entries have been read from file if (!this->LoadDynamicSection()) { - return 0; + return result; } - if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) { - return 0; + + // Copy into public array + result.reserve(this->DynamicSectionEntries.size()); + for (typename std::vector<ELF_Dyn>::iterator di = + this->DynamicSectionEntries.begin(); + di != this->DynamicSectionEntries.end(); ++di) { + ELF_Dyn& dyn = *di; + result.push_back( + std::pair<unsigned long, unsigned long>(dyn.d_tag, dyn.d_un.d_val)); } - ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex]; - return static_cast<unsigned long>(sec.sh_offset + sec.sh_entsize * j); + + return result; +} + +template <class Types> +std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries( + const cmELF::DynamicEntryList& entries) +{ + std::vector<char> result; + result.reserve(sizeof(ELF_Dyn) * entries.size()); + + for (cmELF::DynamicEntryList::const_iterator it = entries.begin(); + it != entries.end(); it++) { + // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars + ELF_Dyn dyn; + dyn.d_tag = static_cast<tagtype>(it->first); + dyn.d_un.d_val = static_cast<tagtype>(it->second); + + if (this->NeedSwap) { + ByteSwap(dyn); + } + + char* pdyn = reinterpret_cast<char*>(&dyn); + result.insert(result.end(), pdyn, pdyn + sizeof(ELF_Dyn)); + } + + return result; } template <class Types> @@ -752,6 +674,15 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( //============================================================================ // External class implementation. +const long cmELF::TagRPath = DT_RPATH; +const long cmELF::TagRunPath = DT_RUNPATH; + +#ifdef DT_MIPS_RLD_MAP_REL +const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL; +#else +const long cmELF::TagMipsRldMapRel = 0; +#endif + cmELF::cmELF(const char* fname) : Internal(CM_NULLPTR) { @@ -839,28 +770,31 @@ unsigned int cmELF::GetNumberOfSections() const return 0; } -unsigned int cmELF::GetDynamicEntryCount() const +unsigned long cmELF::GetDynamicEntryPosition(int index) const { if (this->Valid()) { - return this->Internal->GetDynamicEntryCount(); + return this->Internal->GetDynamicEntryPosition(index); } return 0; } -unsigned long cmELF::GetDynamicEntryPosition(int index) const +cmELF::DynamicEntryList cmELF::GetDynamicEntries() const { if (this->Valid()) { - return this->Internal->GetDynamicEntryPosition(index); + return this->Internal->GetDynamicEntries(); } - return 0; + + return cmELF::DynamicEntryList(); } -bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const +std::vector<char> cmELF::EncodeDynamicEntries( + const cmELF::DynamicEntryList& dentries) const { if (this->Valid()) { - return this->Internal->ReadBytes(pos, size, buf); + return this->Internal->EncodeDynamicEntries(dentries); } - return false; + + return std::vector<char>(); } bool cmELF::GetSOName(std::string& soname) diff --git a/Source/cmELF.h b/Source/cmELF.h index 7e7c1d6..763a240 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -7,6 +7,8 @@ #include <iosfwd> #include <string> +#include <utility> +#include <vector> #if !defined(CMAKE_USE_ELF_PARSER) #error "This file may be included only if CMAKE_USE_ELF_PARSER is enabled." @@ -61,22 +63,27 @@ public: int IndexInSection; }; + /** Represent entire dynamic section header */ + typedef std::vector<std::pair<long, unsigned long> > DynamicEntryList; + /** Get the type of the file opened. */ FileType GetFileType() const; /** Get the number of ELF sections present. */ unsigned int GetNumberOfSections() const; - /** Get the number of DYNAMIC section entries before the first - DT_NULL. Returns zero on error. */ - unsigned int GetDynamicEntryCount() const; - /** Get the position of a DYNAMIC section header entry. Returns zero on error. */ unsigned long GetDynamicEntryPosition(int index) const; - /** Read bytes from the file. */ - bool ReadBytes(unsigned long pos, unsigned long size, char* buf) const; + /** Get a copy of all the DYNAMIC section header entries. + Returns an empty vector on error */ + DynamicEntryList GetDynamicEntries() const; + + /** Encodes a DYNAMIC section header entry list into a char vector according + to the type of ELF file this is */ + std::vector<char> EncodeDynamicEntries( + const DynamicEntryList& entries) const; /** Get the SONAME field if any. */ bool GetSOName(std::string& soname); @@ -91,6 +98,10 @@ public: /** Print human-readable information about the ELF file. */ void PrintInfo(std::ostream& os) const; + /** Interesting dynamic tags. + If the tag is 0, it does not exist in the host ELF implementation */ + static const long TagRPath, TagRunPath, TagMipsRldMapRel; + private: friend class cmELFInternal; bool Valid() const; diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 629c5b6..360c852 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -60,7 +60,6 @@ void cmExtraCodeLiteGenerator::Generate() // loop projects and locate the root project. // and extract the information for creating the worspace // root makefile - const cmMakefile* rmf = CM_NULLPTR; for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator it = projectMap.begin(); it != projectMap.end(); ++it) { @@ -75,7 +74,6 @@ void cmExtraCodeLiteGenerator::Generate() workspaceFileName = workspaceOutputDir + "/"; workspaceFileName += workspaceProjectName + ".workspace"; this->WorkspacePath = it->second[0]->GetCurrentBinaryDirectory(); - rmf = it->second[0]->GetMakefile(); ; break; } @@ -89,7 +87,7 @@ void cmExtraCodeLiteGenerator::Generate() xml.Attribute("Name", workspaceProjectName); bool const targetsAreProjects = - rmf && rmf->IsOn("CMAKE_CODELITE_USE_TARGETS"); + this->GlobalGenerator->GlobalSettingIsOn("CMAKE_CODELITE_USE_TARGETS"); std::vector<std::string> ProjectNames; if (targetsAreProjects) { diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 02717a4..6cdb7f5 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -10,13 +10,21 @@ #include <cm_zlib.h> #endif -cmGeneratedFileStream::cmGeneratedFileStream() +cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) : cmGeneratedFileStreamBase() , Stream() { +#ifdef CMAKE_BUILD_WITH_CMAKE + if (encoding != codecvt::None) { + imbue(std::locale(getloc(), new codecvt(encoding))); + } +#else + static_cast<void>(encoding); +#endif } -cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet) +cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet, + Encoding encoding) : cmGeneratedFileStreamBase(name) , Stream(TempName.c_str()) { @@ -26,6 +34,13 @@ cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet) this->TempName.c_str()); cmSystemTools::ReportLastSystemError(""); } +#ifdef CMAKE_BUILD_WITH_CMAKE + if (encoding != codecvt::None) { + imbue(std::locale(getloc(), new codecvt(encoding))); + } +#else + static_cast<void>(encoding); +#endif } cmGeneratedFileStream::~cmGeneratedFileStream() diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h index 515954c..a027b01 100644 --- a/Source/cmGeneratedFileStream.h +++ b/Source/cmGeneratedFileStream.h @@ -5,6 +5,7 @@ #include <cmConfigure.h> +#include <cm_codecvt.hxx> #include <cmsys/FStream.hxx> #include <string> @@ -71,12 +72,13 @@ class cmGeneratedFileStream : private cmGeneratedFileStreamBase, { public: typedef cmsys::ofstream Stream; + typedef codecvt::Encoding Encoding; /** * This constructor prepares a default stream. The open method must * be used before writing to the stream. */ - cmGeneratedFileStream(); + cmGeneratedFileStream(Encoding encoding = codecvt::None); /** * This constructor takes the name of the file to be generated. It @@ -84,7 +86,8 @@ public: * file cannot be opened an error message is produced unless the * second argument is set to true. */ - cmGeneratedFileStream(const char* name, bool quiet = false); + cmGeneratedFileStream(const char* name, bool quiet = false, + Encoding encoding = codecvt::None); /** * The destructor checks the stream status to be sure the temporary diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e8d66a2..7eb0ebf 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4965,6 +4965,9 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { return false; } + if (this->GetProperty("BUILD_RPATH")) { + return true; + } if (cmLinkImplementationLibraries const* impl = this->GetLinkImplementationLibraries(config)) { return !impl->Libraries.empty(); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index a446862..7132ade 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1007,6 +1007,25 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, } } +const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const +{ + assert(!this->Makefiles.empty()); + return this->Makefiles[0]->GetDefinition(name); +} + +bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const +{ + assert(!this->Makefiles.empty()); + return this->Makefiles[0]->IsOn(name); +} + +const char* cmGlobalGenerator::GetSafeGlobalSetting( + std::string const& name) const +{ + assert(!this->Makefiles.empty()); + return this->Makefiles[0]->GetSafeDefinition(name); +} + bool cmGlobalGenerator::IgnoreFile(const char* ext) const { if (!this->GetLanguageFromExtension(ext).empty()) { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 4120b52..74b4547 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -10,6 +10,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" +#include "cm_codecvt.hxx" #include <iosfwd> #include <map> @@ -60,6 +61,12 @@ public: return this->GetName() == name; } + /** Get encoding used by generator for makefile files */ + virtual codecvt::Encoding GetMakefileEncoding() const + { + return codecvt::None; + } + /** Tell the generator about the target system. */ virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; } @@ -194,6 +201,10 @@ public: cmExportSetMap& GetExportSets() { return this->ExportSets; } + const char* GetGlobalSetting(std::string const& name) const; + bool GlobalSettingIsOn(std::string const& name) const; + const char* GetSafeGlobalSetting(std::string const& name) const; + /** Add a file to the manifest of generated targets for a configuration. */ void AddToManifest(std::string const& f); diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index f169e76..6eb2124 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -26,6 +26,12 @@ public: } static std::string GetActualName() { return "NMake Makefiles"; } + /** Get encoding used by generator for makefile files */ + codecvt::Encoding GetMakefileEncoding() const CM_OVERRIDE + { + return codecvt::ANSI; + } + /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 4a5cc77..daacef0 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -201,7 +201,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() this->GetCMakeInstance()->GetHomeOutputDirectory(); makefileName += cmake::GetCMakeFilesDirectory(); makefileName += "/Makefile2"; - cmGeneratedFileStream makefileStream(makefileName.c_str()); + cmGeneratedFileStream makefileStream(makefileName.c_str(), false, + this->GetMakefileEncoding()); if (!makefileStream) { return; } @@ -306,16 +307,12 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() // reset lg to the first makefile lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); - // Build the path to the cache file. - std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory(); - cache += "/CMakeCache.txt"; - std::string currentBinDir = lg->GetCurrentBinaryDirectory(); // Save the list to the cmake file. cmakefileStream << "# The top level Makefile was generated from the following files:\n" << "set(CMAKE_MAKEFILE_DEPENDS\n" - << " \"" << lg->ConvertToRelativePath(currentBinDir, cache) << "\"\n"; + << " \"CMakeCache.txt\"\n"; for (std::vector<std::string>::const_iterator i = lfiles.begin(); i != lfiles.end(); ++i) { cmakefileStream << " \"" << lg->ConvertToRelativePath(currentBinDir, *i) diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index 4d62f2b..a833a5f 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -79,7 +79,7 @@ cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\15.0\\Setup\\VC;" "ProductDir", vc15Express, cmSystemTools::KeyWOW64_32); - this->DefaultPlatformToolset = "v140"; + this->DefaultPlatformToolset = "v141"; this->Version = VS15; } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 4ff612d..75fc2e4 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3325,14 +3325,14 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p) { // We force conversion because Xcode breakpoints do not work unless // they are in a file named relative to the source tree. - return this->CurrentLocalGenerator->ConvertToRelativePath( - this->ProjectSourceDirectoryComponents, p, true); + return cmOutputConverter::ForceToRelativePath( + cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p); } std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p) { return this->CurrentLocalGenerator->ConvertToRelativePath( - this->ProjectOutputDirectoryComponents, p); + cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p); } std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index f24b717..2284cf9 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1248,6 +1248,14 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += this->Makefile->GetSafeDefinition(exportFlagVar); linkFlags += " "; } + + std::string cmp0065Flags = + this->GetLinkLibsCMP0065(linkLanguage, *target); + if (!cmp0065Flags.empty()) { + linkFlags += cmp0065Flags; + linkFlags += " "; + } + const char* targetLinkFlags = target->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { linkFlags += targetLinkFlags; @@ -1374,8 +1382,7 @@ std::string cmLocalGenerator::GetTargetFortranFlags( return std::string(); } -std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib, - OutputFormat format) +std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib) { #if defined(_WIN32) && !defined(__CYGWIN__) // Work-ardound command line parsing limitations in MSVC 6.0 @@ -1392,17 +1399,14 @@ std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib, // Append the rest of the path with no space. sp += lib.substr(pos); - // Convert to an output path. - return this->ConvertToOutputFormat(sp.c_str(), format); + return sp; } } } #endif // Normal behavior. - return this->ConvertToOutputFormat( - this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), lib), - format); + return this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), lib); } /** @@ -1428,59 +1432,15 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, } cmComputeLinkInformation& cli = *pcli; - // Collect library linking flags command line options. - std::string linkLibs; - std::string linkLanguage = cli.GetLinkLanguage(); + std::string linkLibs; + std::string libPathFlag = this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG"); std::string libPathTerminator = this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR"); - // Flags to link an executable to shared libraries. - if (tgt.GetType() == cmState::EXECUTABLE && - this->StateSnapshot.GetState()->GetGlobalPropertyAsBool( - "TARGET_SUPPORTS_SHARED_LIBS")) { - bool add_shlib_flags = false; - switch (tgt.GetPolicyStatusCMP0065()) { - case cmPolicies::WARN: - if (!tgt.GetPropertyAsBool("ENABLE_EXPORTS") && - this->Makefile->PolicyOptionalWarningEnabled( - "CMAKE_POLICY_WARNING_CMP0065")) { - std::ostringstream w; - /* clang-format off */ - w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0065) << "\n" - "For compatibility with older versions of CMake, " - "additional flags may be added to export symbols on all " - "executables regardless of their ENABLE_EXPORTS property."; - /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); - } - case cmPolicies::OLD: - // OLD behavior is to always add the flags - add_shlib_flags = true; - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - this->IssueMessage( - cmake::FATAL_ERROR, - cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065)); - case cmPolicies::NEW: - // NEW behavior is to only add the flags if ENABLE_EXPORTS is on - add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS"); - break; - } - - if (add_shlib_flags) { - std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; - linkFlagsVar += linkLanguage; - linkFlagsVar += "_FLAGS"; - linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar); - linkLibs += " "; - } - } - // Append the framework search path flags. std::string fwSearchFlagVar = "CMAKE_"; fwSearchFlagVar += linkLanguage; @@ -1517,7 +1477,8 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, continue; } if (li->IsPath) { - linkLibs += this->ConvertToLinkReference(li->Value, shellFormat); + linkLibs += this->ConvertToOutputFormat( + this->ConvertToLinkReference(li->Value), shellFormat); } else { linkLibs += li->Value; } @@ -1572,6 +1533,55 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, linkLibraries = fout.str(); } +std::string cmLocalGenerator::GetLinkLibsCMP0065( + std::string const& linkLanguage, cmGeneratorTarget& tgt) const +{ + std::string linkFlags; + + // Flags to link an executable to shared libraries. + if (tgt.GetType() == cmState::EXECUTABLE && + this->StateSnapshot.GetState()->GetGlobalPropertyAsBool( + "TARGET_SUPPORTS_SHARED_LIBS")) { + bool add_shlib_flags = false; + switch (tgt.GetPolicyStatusCMP0065()) { + case cmPolicies::WARN: + if (!tgt.GetPropertyAsBool("ENABLE_EXPORTS") && + this->Makefile->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0065")) { + std::ostringstream w; + /* clang-format off */ + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0065) << "\n" + "For compatibility with older versions of CMake, " + "additional flags may be added to export symbols on all " + "executables regardless of their ENABLE_EXPORTS property."; + /* clang-format on */ + this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + } + case cmPolicies::OLD: + // OLD behavior is to always add the flags + add_shlib_flags = true; + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->IssueMessage( + cmake::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065)); + case cmPolicies::NEW: + // NEW behavior is to only add the flags if ENABLE_EXPORTS is on + add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS"); + break; + } + + if (add_shlib_flags) { + std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; + linkFlagsVar += linkLanguage; + linkFlagsVar += "_FLAGS"; + linkFlags = this->Makefile->GetSafeDefinition(linkFlagsVar); + } + } + return linkFlags; +} + void cmLocalGenerator::AddArchitectureFlags(std::string& flags, cmGeneratorTarget const* target, const std::string& lang, diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 19469be..e16ddab 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -82,6 +82,9 @@ public: return this->GlobalGenerator; } + std::string GetLinkLibsCMP0065(std::string const& linkLanguage, + cmGeneratorTarget& tgt) const; + cmState* GetState() const; cmState::Snapshot GetStateSnapshot() const; @@ -367,9 +370,7 @@ protected: std::string& CreateSafeUniqueObjectFileName(const std::string& sin, std::string const& dir_max); - virtual std::string ConvertToLinkReference( - std::string const& lib, - cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL); + virtual std::string ConvertToLinkReference(std::string const& lib); /** Check whether the native build system supports the given definition. Issues a warning. */ diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 11b87e3..5736581 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -121,10 +121,9 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator() // Virtual protected methods. std::string cmLocalNinjaGenerator::ConvertToLinkReference( - std::string const& lib, cmOutputConverter::OutputFormat format) + std::string const& lib) { - std::string path = this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(lib); - return this->ConvertToOutputFormat(path, format); + return this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(lib); } std::string cmLocalNinjaGenerator::ConvertToIncludeReference( diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 875f8c6..3061b57 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -76,9 +76,7 @@ public: void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps); - std::string ConvertToLinkReference(std::string const& lib, - cmOutputConverter::OutputFormat format = - cmOutputConverter::SHELL) CM_OVERRIDE; + std::string ConvertToLinkReference(std::string const& lib) CM_OVERRIDE; void ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 8825b46..eb2852c 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -141,7 +141,7 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath() { // Compute the path to use when referencing the current output // directory from the top output directory. - this->HomeRelativeOutputPath = this->ConvertToRelativePath( + this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath( this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); if (this->HomeRelativeOutputPath == ".") { this->HomeRelativeOutputPath = ""; @@ -230,7 +230,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() // Open the rule file. This should be copy-if-different because the // rules may depend on this file itself. std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); - cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str()); + cmGeneratedFileStream ruleFileStream( + ruleFileNameFull.c_str(), false, + this->GlobalGenerator->GetMakefileEncoding()); if (!ruleFileStream) { return; } @@ -548,7 +550,8 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule( // Construct the left hand side of the rule. std::string tgt = cmSystemTools::ConvertToOutputPath( - this->ConvertToRelativePath(this->GetBinaryDirectory(), target).c_str()); + this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target) + .c_str()); const char* space = ""; if (tgt.size() == 1) { @@ -577,7 +580,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule( dep != depends.end(); ++dep) { replace = *dep; replace = cmSystemTools::ConvertToOutputPath( - this->ConvertToRelativePath(binDir, replace).c_str()); + this->MaybeConvertToRelativePath(binDir, replace).c_str()); os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n"; } } @@ -969,7 +972,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // working directory will be the start-output directory. bool had_slash = cmd.find('/') != cmd.npos; if (workingDir.empty()) { - cmd = this->ConvertToRelativePath(currentBinDir, cmd); + cmd = this->MaybeConvertToRelativePath(currentBinDir, cmd); } bool has_slash = cmd.find('/') != cmd.npos; if (had_slash && !has_slash) { @@ -994,8 +997,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( if (!outputs.empty()) { if (workingDir.empty()) { output = this->ConvertToOutputFormat( - this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), - outputs[0]), + this->MaybeConvertToRelativePath( + this->GetCurrentBinaryDirectory(), outputs[0]), cmOutputConverter::SHELL); } else { @@ -1082,14 +1085,15 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand( fout << "file(REMOVE_RECURSE\n"; for (std::vector<std::string>::const_iterator f = files.begin(); f != files.end(); ++f) { - std::string fc = this->ConvertToRelativePath(currentBinDir, *f); + std::string fc = this->MaybeConvertToRelativePath(currentBinDir, *f); fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n"; } fout << ")\n"; } std::string remove = "$(CMAKE_COMMAND) -P "; remove += this->ConvertToOutputFormat( - this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cleanfile), + this->MaybeConvertToRelativePath(this->GetCurrentBinaryDirectory(), + cleanfile), cmOutputConverter::SHELL); commands.push_back(remove); @@ -1415,7 +1419,9 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // because the make tool may try to reload it needlessly otherwise. std::string ruleFileNameFull = dir; ruleFileNameFull += "/depend.make"; - cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str()); + cmGeneratedFileStream ruleFileStream( + ruleFileNameFull.c_str(), false, + this->GlobalGenerator->GetMakefileEncoding()); ruleFileStream.SetCopyIfDifferent(true); if (!ruleFileStream) { return false; @@ -1427,7 +1433,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( std::string internalRuleFileNameFull = dir; internalRuleFileNameFull += "/depend.internal"; cmGeneratedFileStream internalRuleFileStream( - internalRuleFileNameFull.c_str()); + internalRuleFileNameFull.c_str(), false, + this->GlobalGenerator->GetMakefileEncoding()); if (!internalRuleFileStream) { return false; } @@ -1858,7 +1865,8 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( } for (std::vector<std::string>::iterator i = includes.begin(); i != includes.end(); ++i) { - cmakefileStream << " \"" << this->ConvertToRelativePath(binaryDir, *i) + cmakefileStream << " \"" + << this->MaybeConvertToRelativePath(binaryDir, *i) << "\"\n"; } cmakefileStream << " )\n"; @@ -1923,7 +1931,7 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall( if (!tgt.empty()) { // The make target is always relative to the top of the build tree. std::string tgt2 = - this->ConvertToRelativePath(this->GetBinaryDirectory(), tgt); + this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), tgt); // The target may have been written with windows paths. cmSystemTools::ConvertToOutputSlashes(tgt2); @@ -2095,3 +2103,13 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand( std::bind1st(std::plus<std::string>(), prefix)); } } + +std::string cmLocalUnixMakefileGenerator3::MaybeConvertToRelativePath( + std::string const& base, std::string const& path) +{ + if (!cmOutputConverter::ContainedInDirectory( + base, path, this->GetStateSnapshot().GetDirectory())) { + return path; + } + return cmOutputConverter::ForceToRelativePath(base, path); +} diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index fc5c8e7..c3ecda4 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -184,6 +184,9 @@ public: // Eclipse generator. void GetIndividualFileTargets(std::vector<std::string>& targets); + std::string MaybeConvertToRelativePath(std::string const& base, + std::string const& path); + protected: void WriteLocalMakefile(); diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index cb20117..79168d8 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -130,16 +130,16 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) targetFullPathPDB, cmOutputConverter::SHELL); // Convert to the output path to use in constructing commands. std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath), cmOutputConverter::SHELL); std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), cmOutputConverter::SHELL); std::string targetOutPathImport = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathImport), cmOutputConverter::SHELL); @@ -192,6 +192,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->AppendFlags( linkFlags, this->Makefile->GetDefinition(export_flag_var)); } + + this->LocalGenerator->AppendFlags(linkFlags, + this->LocalGenerator->GetLinkLibsCMP0065( + linkLanguage, *this->GeneratorTarget)); + if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) { this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed"); } @@ -215,27 +220,27 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct a list of files associated with this executable that // may need to be cleaned. std::vector<std::string> exeCleanFiles; - exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath)); #ifdef _WIN32 // There may be a manifest file for this target. Add it to the // clean set just in case. - exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), (targetFullPath + ".manifest").c_str())); #endif if (targetNameReal != targetName) { - exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal)); } if (!targetNameImport.empty()) { - exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport, implib)) { - exeCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } } @@ -243,7 +248,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // List the PDB for cleaning only when the whole target is // cleaned. We do not want to delete the .pdb file just before // linking the target. - this->CleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + this->CleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB)); // Add the pre-build and pre-link rules building but not when relinking. @@ -318,7 +323,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), cmOutputConverter::SHELL); vars.ObjectDir = objectDir.c_str(); @@ -326,7 +331,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) ? cmOutputConverter::WATCOMQUOTE : cmOutputConverter::SHELL; std::string target = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), output); vars.Target = target.c_str(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index b969bfb..8e25f43 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -305,20 +305,20 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( targetFullPathPDB, cmOutputConverter::SHELL); std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath), cmOutputConverter::SHELL); std::string targetOutPathSO = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO), cmOutputConverter::SHELL); std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), cmOutputConverter::SHELL); std::string targetOutPathImport = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathImport), cmOutputConverter::SHELL); @@ -366,24 +366,24 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Clean files associated with this library. std::vector<std::string> libCleanFiles; - libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath)); if (targetNameReal != targetName) { - libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal)); } if (targetNameSO != targetName && targetNameSO != targetNameReal) { - libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO)); } if (!targetNameImport.empty()) { - libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport, implib)) { - libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } } @@ -391,14 +391,14 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // List the PDB for cleaning only when the whole target is // cleaned. We do not want to delete the .pdb file just before // linking the target. - this->CleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + this->CleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB)); #ifdef _WIN32 // There may be a manifest file for this target. Add it to the // clean set just in case. if (this->GeneratorTarget->GetType() != cmState::STATIC_LIBRARY) { - libCleanFiles.push_back(this->LocalGenerator->ConvertToRelativePath( + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), (targetFullPath + ".manifest").c_str())); } @@ -537,7 +537,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), cmOutputConverter::SHELL); @@ -546,7 +546,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( ? cmOutputConverter::WATCOMQUOTE : cmOutputConverter::SHELL; std::string target = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), output); vars.Target = target.c_str(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index e70f09e..14102ef 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -110,7 +110,8 @@ void cmMakefileTargetGenerator::CreateRuleFile() // Open the rule file. This should be copy-if-different because the // rules may depend on this file itself. this->BuildFileStream = - new cmGeneratedFileStream(this->BuildFileNameFull.c_str()); + new cmGeneratedFileStream(this->BuildFileNameFull.c_str(), false, + this->GlobalGenerator->GetMakefileEncoding()); this->BuildFileStream->SetCopyIfDifferent(true); if (!this->BuildFileStream) { return; @@ -166,7 +167,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() for (std::vector<std::string>::const_iterator o = outputs.begin(); o != outputs.end(); ++o) { this->CleanFiles.push_back( - this->LocalGenerator->ConvertToRelativePath(currentBinDir, *o)); + this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, *o)); } } } @@ -209,8 +210,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( this->LocalGenerator - ->ConvertToRelativePath(this->LocalGenerator->GetBinaryDirectory(), - dependFileNameFull) + ->MaybeConvertToRelativePath( + this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull) .c_str()) << "\n\n"; @@ -221,7 +222,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( this->LocalGenerator - ->ConvertToRelativePath( + ->MaybeConvertToRelativePath( this->LocalGenerator->GetBinaryDirectory(), this->ProgressFileNameFull) .c_str()) @@ -231,7 +232,9 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() // make sure the depend file exists if (!cmSystemTools::FileExists(dependFileNameFull.c_str())) { // Write an empty dependency file. - cmGeneratedFileStream depFileStream(dependFileNameFull.c_str()); + cmGeneratedFileStream depFileStream( + dependFileNameFull.c_str(), false, + this->GlobalGenerator->GetMakefileEncoding()); depFileStream << "# Empty dependencies file for " << this->GeneratorTarget->GetName() << ".\n" << "# This may be replaced when dependencies are built." @@ -243,7 +246,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->FlagFileNameFull = this->TargetBuildDirectoryFull; this->FlagFileNameFull += "/flags.make"; this->FlagFileStream = - new cmGeneratedFileStream(this->FlagFileNameFull.c_str()); + new cmGeneratedFileStream(this->FlagFileNameFull.c_str(), false, + this->GlobalGenerator->GetMakefileEncoding()); this->FlagFileStream->SetCopyIfDifferent(true); if (!this->FlagFileStream) { return; @@ -256,8 +260,9 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( this->LocalGenerator - ->ConvertToRelativePath(this->LocalGenerator->GetBinaryDirectory(), - this->FlagFileNameFull) + ->MaybeConvertToRelativePath( + this->LocalGenerator->GetBinaryDirectory(), + this->FlagFileNameFull) .c_str()) << "\n\n"; } @@ -314,9 +319,9 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( output += "/"; output += cmSystemTools::GetFilenameName(input); this->Generator->CleanFiles.push_back( - this->Generator->LocalGenerator->ConvertToRelativePath( + this->Generator->LocalGenerator->MaybeConvertToRelativePath( this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output)); - output = this->Generator->LocalGenerator->ConvertToRelativePath( + output = this->Generator->LocalGenerator->MaybeConvertToRelativePath( this->Generator->LocalGenerator->GetBinaryDirectory(), output); // Create a rule to copy the content into the bundle. @@ -518,13 +523,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( } targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), cmOutputConverter::SHELL); targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat( targetFullPathPDB, cmOutputConverter::SHELL); targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathCompilePDB), cmOutputConverter::SHELL); @@ -550,13 +555,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( vars.Object = shellObj.c_str(); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), cmOutputConverter::SHELL); vars.ObjectDir = objectDir.c_str(); std::string objectFileDir = cmSystemTools::GetFilenamePath(obj); objectFileDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objectFileDir), cmOutputConverter::SHELL); vars.ObjectFileDir = objectFileDir.c_str(); @@ -904,7 +909,7 @@ bool cmMakefileTargetGenerator::WriteMakeRule( // Touch the extra output so "make" knows that it was updated, // but only if the output was acually created. std::string const out = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath(binDir, *o), + this->LocalGenerator->MaybeConvertToRelativePath(binDir, *o), cmOutputConverter::SHELL); std::vector<std::string> output_commands; @@ -1200,7 +1205,8 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( for (std::vector<std::string>::const_iterator i = this->ExternalObjects.begin(); i != this->ExternalObjects.end(); ++i) { - object = this->LocalGenerator->ConvertToRelativePath(currentBinDir, *i); + object = + this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, *i); *this->BuildFileStream << " " << lineContinue << "\n" << this->Makefile->GetSafeDefinition( "CMAKE_OBJECT_NAME"); @@ -1234,7 +1240,7 @@ public: { // Construct the name of the next object. this->NextObject = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), obj), cmOutputConverter::RESPONSE); @@ -1289,7 +1295,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule( this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget); std::string buildTargetRuleName = dir; buildTargetRuleName += relink ? "/preinstall" : "/build"; - buildTargetRuleName = this->LocalGenerator->ConvertToRelativePath( + buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName); // Build the list of target outputs to drive. @@ -1479,7 +1485,7 @@ void cmMakefileTargetGenerator::CreateLinkScript( // Create the makefile command to invoke the link script. std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script "; link_command += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName), cmOutputConverter::SHELL); link_command += " --verbose=$(VERBOSE)"; @@ -1716,14 +1722,14 @@ void cmMakefileTargetGenerator::GenDefFile( cmd, cmOutputConverter::SHELL); cmd += " -E __create_def "; cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file), cmOutputConverter::SHELL); cmd += " "; std::string objlist_file = name_of_def_file; objlist_file += ".objs"; cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), cmOutputConverter::SHELL); real_link_commands.insert(real_link_commands.begin(), cmd); @@ -1744,7 +1750,7 @@ void cmMakefileTargetGenerator::GenDefFile( linkFlags += " "; linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); linkFlags += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->ConvertToRelativePath( + this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file), cmOutputConverter::SHELL); linkFlags += " "; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index f40c8fa..ecb29cb 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -46,7 +46,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( this->LocalGenerator - ->ConvertToRelativePath( + ->MaybeConvertToRelativePath( this->LocalGenerator->GetBinaryDirectory(), this->ProgressFileNameFull) .c_str()) diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 2ef603b..84a433c 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -76,44 +76,35 @@ static bool cmOutputConverterNotAbove(const char* a, const char* b) cmSystemTools::IsSubDirectory(a, b)); } -std::string cmOutputConverter::ConvertToRelativePath( - const std::vector<std::string>& local, const std::string& in_remote, - bool force) const +bool cmOutputConverter::ContainedInDirectory(std::string const& local_path, + std::string const& remote_path, + cmState::Directory directory) { - std::string local_path = cmSystemTools::JoinPath(local); - return force ? this->ForceToRelativePath(local_path, in_remote) - : this->ConvertToRelativePath(local_path, in_remote); + const std::string relativePathTopBinary = + directory.GetRelativePathTopBinary(); + const std::string relativePathTopSource = + directory.GetRelativePathTopSource(); + + const bool bothInBinary = + cmOutputConverterNotAbove(local_path.c_str(), + relativePathTopBinary.c_str()) && + cmOutputConverterNotAbove(remote_path.c_str(), + relativePathTopBinary.c_str()); + + const bool bothInSource = + cmOutputConverterNotAbove(local_path.c_str(), + relativePathTopSource.c_str()) && + cmOutputConverterNotAbove(remote_path.c_str(), + relativePathTopSource.c_str()); + + return bothInSource || bothInBinary; } std::string cmOutputConverter::ConvertToRelativePath( std::string const& local_path, std::string const& remote_path) const { - // The paths should never be quoted. - assert(local_path[0] != '\"'); - assert(remote_path[0] != '\"'); - - // The local path should never have a trailing slash. - assert(local_path.empty() || local_path[local_path.size() - 1] != '/'); - - // If the path is already relative then just return the path. - if (!cmSystemTools::FileIsFullPath(remote_path.c_str())) { - return remote_path; - } - - // Skip conversion if the path and local are not both in the source - // or both in the binary tree. - if (!((cmOutputConverterNotAbove( - local_path.c_str(), - this->StateSnapshot.GetDirectory().GetRelativePathTopBinary()) && - cmOutputConverterNotAbove( - remote_path.c_str(), - this->StateSnapshot.GetDirectory().GetRelativePathTopBinary())) || - (cmOutputConverterNotAbove( - local_path.c_str(), - this->StateSnapshot.GetDirectory().GetRelativePathTopSource()) && - cmOutputConverterNotAbove( - remote_path.c_str(), - this->StateSnapshot.GetDirectory().GetRelativePathTopSource())))) { + if (!ContainedInDirectory(local_path, remote_path, + this->StateSnapshot.GetDirectory())) { return remote_path; } @@ -248,10 +239,11 @@ std::string cmOutputConverter::EscapeForShell(const std::string& str, if (this->GetState()->UseNMake()) { flags |= Shell_Flag_NMake; } + if (!this->GetState()->UseWindowsShell()) { + flags |= Shell_Flag_IsUnix; + } - return this->GetState()->UseWindowsShell() - ? Shell_GetArgumentForWindows(str.c_str(), flags) - : Shell_GetArgumentForUnix(str.c_str(), flags); + return Shell__GetArgument(str.c_str(), flags); } std::string cmOutputConverter::EscapeForCMake(const std::string& str) @@ -280,7 +272,7 @@ std::string cmOutputConverter::EscapeForCMake(const std::string& str) std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg, int shell_flags) { - return Shell_GetArgumentForWindows(arg, shell_flags); + return Shell__GetArgument(arg, shell_flags); } cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( @@ -366,10 +358,10 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c) (c == '>') || (c == '|') || (c == '^')); } -int cmOutputConverter::Shell__CharNeedsQuotes(char c, int isUnix, int flags) +int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) { /* On Windows the built-in command shell echo never needs quotes. */ - if (!isUnix && (flags & Shell_Flag_EchoWindows)) { + if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) { return 0; } @@ -378,7 +370,7 @@ int cmOutputConverter::Shell__CharNeedsQuotes(char c, int isUnix, int flags) return 1; } - if (isUnix) { + if (flags & Shell_Flag_IsUnix) { /* On UNIX several special characters need quotes to preserve them. */ if (Shell__CharNeedsQuotesOnUnix(c)) { return 1; @@ -436,8 +428,7 @@ flag later when we understand applications of this better. */ #define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0 -int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int isUnix, - int flags) +int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags) { /* The empty string needs quotes. */ if (!*in) { @@ -469,14 +460,14 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int isUnix, } /* Check whether this character needs quotes. */ - if (Shell__CharNeedsQuotes(*c, isUnix, flags)) { + if (Shell__CharNeedsQuotes(*c, flags)) { return 1; } } } /* On Windows some single character arguments need quotes. */ - if (!isUnix && *in && !*(in + 1)) { + if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) { char c = *in; if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) { return 1; @@ -486,8 +477,7 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int isUnix, return 0; } -std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix, - int flags) +std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) { std::ostringstream out; @@ -498,11 +488,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix, int windows_backslashes = 0; /* Whether the argument must be quoted. */ - int needQuotes = Shell__ArgumentNeedsQuotes(in, isUnix, flags); + int needQuotes = Shell__ArgumentNeedsQuotes(in, flags); if (needQuotes) { /* Add the opening quote for this argument. */ if (flags & Shell_Flag_WatcomQuote) { - if (isUnix) { + if (flags & Shell_Flag_IsUnix) { out << '"'; } out << '\''; @@ -534,7 +524,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix, } /* Check whether this character needs escaping for the shell. */ - if (isUnix) { + if (flags & Shell_Flag_IsUnix) { /* On Unix a few special characters need escaping even inside a quoted argument. */ if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') { @@ -631,7 +621,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix, /* Add the closing quote for this argument. */ if (flags & Shell_Flag_WatcomQuote) { out << '\''; - if (isUnix) { + if (flags & Shell_Flag_IsUnix) { out << '"'; } } else { @@ -641,15 +631,3 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int isUnix, return out.str(); } - -std::string cmOutputConverter::Shell_GetArgumentForWindows(const char* in, - int flags) -{ - return Shell__GetArgument(in, 0, flags); -} - -std::string cmOutputConverter::Shell_GetArgumentForUnix(const char* in, - int flags) -{ - return Shell__GetArgument(in, 1, flags); -} diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 5979eaa..71cacab 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -33,8 +33,7 @@ public: void SetLinkScriptShell(bool linkScriptShell); /** - * Flags to pass to Shell_GetArgumentForWindows or - * Shell_GetArgumentForUnix. These modify the generated + * Flags to pass to Shell_GetArgument. These modify the generated * quoting and escape sequences to work under alternative * environments. */ @@ -67,18 +66,10 @@ public: Shell_Flag_AllowMakeVariables = (1 << 6), /** The target shell quoting uses extra single Quotes for Watcom tools. */ - Shell_Flag_WatcomQuote = (1 << 7) - }; + Shell_Flag_WatcomQuote = (1 << 7), - /** - * Transform the given command line argument for use in a Windows or - * Unix shell. Returns a pointer to the end of the command line - * argument in the provided output buffer. Flags may be passed to - * modify the generated quoting and escape sequences to work under - * alternative environments. - */ - static std::string Shell_GetArgumentForWindows(const char* in, int flags); - static std::string Shell_GetArgumentForUnix(const char* in, int flags); + Shell_Flag_IsUnix = (1 << 8) + }; std::string EscapeForShell(const std::string& str, bool makeVars = false, bool forEcho = false, @@ -99,16 +90,9 @@ public: }; static FortranFormat GetFortranFormat(const char* value); - /** - * Convert the given remote path to a relative path with respect to - * the given local path. The local path must be given in component - * form (see SystemTools::SplitPath) without a trailing slash. The - * remote path must use forward slashes and not already be escaped - * or quoted. - */ - std::string ConvertToRelativePath(const std::vector<std::string>& local, - const std::string& in_remote, - bool force = false) const; + static bool ContainedInDirectory(std::string const& local_path, + std::string const& remote_path, + cmState::Directory directory); /** * Convert the given remote path to a relative path with respect to @@ -134,11 +118,11 @@ private: static int Shell__CharIsWhitespace(char c); static int Shell__CharNeedsQuotesOnUnix(char c); static int Shell__CharNeedsQuotesOnWindows(char c); - static int Shell__CharNeedsQuotes(char c, int isUnix, int flags); + static int Shell__CharNeedsQuotes(char c, int flags); static int Shell__CharIsMakeVariableName(char c); static const char* Shell__SkipMakeVariables(const char* c); - static int Shell__ArgumentNeedsQuotes(const char* in, int isUnix, int flags); - static std::string Shell__GetArgument(const char* in, int isUnix, int flags); + static int Shell__ArgumentNeedsQuotes(const char* in, int flags); + static std::string Shell__GetArgument(const char* in, int flags); private: cmState::Snapshot StateSnapshot; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 3d8fdf5..d800ef8 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2518,9 +2518,9 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, std::swap(se[0], se[1]); } - // Get the size of the dynamic section header. - unsigned int count = elf.GetDynamicEntryCount(); - if (count == 0) { + // Obtain a copy of the dynamic entries + cmELF::DynamicEntryList dentries = elf.GetDynamicEntries(); + if (dentries.empty()) { // This should happen only for invalid ELF files where a DT_NULL // appears before the end of the table. if (emsg) { @@ -2536,40 +2536,46 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, zeroSize[i] = se[i]->Size; } - // Get the range of file positions corresponding to each entry and - // the rest of the table after them. - unsigned long entryBegin[3] = { 0, 0, 0 }; - unsigned long entryEnd[2] = { 0, 0 }; - for (int i = 0; i < se_count; ++i) { - entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection); - entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection + 1); - } - entryBegin[se_count] = elf.GetDynamicEntryPosition(count); - - // The data are to be written over the old table entries starting at - // the first one being removed. - bytesBegin = entryBegin[0]; - unsigned long bytesEnd = entryBegin[se_count]; + // Get size of one DYNAMIC entry + unsigned long const sizeof_dentry = + elf.GetDynamicEntryPosition(1) - elf.GetDynamicEntryPosition(0); - // Allocate a buffer to hold the part of the file to be written. - // Initialize it with zeros. - bytes.resize(bytesEnd - bytesBegin, 0); - - // Read the part of the DYNAMIC section header that will move. - // The remainder of the buffer will be left with zeros which - // represent a DT_NULL entry. - char* data = &bytes[0]; - for (int i = 0; i < se_count; ++i) { - // Read data between the entries being removed. - unsigned long sz = entryBegin[i + 1] - entryEnd[i]; - if (sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data)) { - if (emsg) { - *emsg = "Failed to read DYNAMIC section header."; + // Adjust the entry list as necessary to remove the run path + unsigned long entriesErased = 0; + for (cmELF::DynamicEntryList::iterator it = dentries.begin(); + it != dentries.end();) { + if (it->first == cmELF::TagRPath || it->first == cmELF::TagRunPath) { + it = dentries.erase(it); + entriesErased++; + continue; + } else { + if (cmELF::TagMipsRldMapRel != 0 && + it->first == cmELF::TagMipsRldMapRel) { + // Background: debuggers need to know the "linker map" which contains + // the addresses each dynamic object is loaded at. Most arches use + // the DT_DEBUG tag which the dynamic linker writes to (directly) and + // contain the location of the linker map, however on MIPS the + // .dynamic section is always read-only so this is not possible. MIPS + // objects instead contain a DT_MIPS_RLD_MAP tag which contains the + // address where the dyanmic linker will write to (an indirect + // version of DT_DEBUG). Since this doesn't work when using PIE, a + // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this + // version contains a relative offset, moving it changes the + // calculated address. This may cause the dyanmic linker to write + // into memory it should not be changing. + // + // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If + // we move it up by n bytes, we add n bytes to the value of this tag. + it->second += entriesErased * sizeof_dentry; } - return false; + + it++; } - data += sz; } + + // Encode new entries list + bytes = elf.EncodeDynamicEntries(dentries); + bytesBegin = elf.GetDynamicEntryPosition(0); } // Open the file for update. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 54e0bea..13a4744 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -102,6 +102,7 @@ cmTarget::cmTarget(std::string const& name, cmState::TargetType type, this->SetPropertyDefault("ANDROID_JAR_DEPENDENCIES", CM_NULLPTR); this->SetPropertyDefault("ANDROID_ASSETS_DIRECTORIES", CM_NULLPTR); this->SetPropertyDefault("ANDROID_ANT_ADDITIONAL_OPTIONS", CM_NULLPTR); + this->SetPropertyDefault("BUILD_RPATH", CM_NULLPTR); this->SetPropertyDefault("INSTALL_NAME_DIR", CM_NULLPTR); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx new file mode 100644 index 0000000..869dd32 --- /dev/null +++ b/Source/cm_codecvt.cxx @@ -0,0 +1,215 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cm_codecvt.hxx" +#include <limits> + +#if defined(_WIN32) +#include <windows.h> +#undef max +#include <cmsys/Encoding.hxx> +#endif + +codecvt::codecvt(Encoding e) + : m_lastState(0) +#if defined(_WIN32) + , m_codepage(0) +#endif +{ + switch (e) { + case codecvt::ANSI: +#if defined(_WIN32) + m_noconv = false; + m_codepage = CP_ACP; + break; +#endif + // We don't know which ANSI encoding to use for other platforms than + // Windows so we don't do any conversion there + case codecvt::UTF8: + // Assume internal encoding is UTF-8 + case codecvt::None: + // No encoding + default: + m_noconv = true; + } +} + +codecvt::~codecvt(){}; + +bool codecvt::do_always_noconv() const throw() +{ + return m_noconv; +}; + +std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from, + const char* from_end, + const char*& from_next, char* to, + char* to_end, char*& to_next) const +{ + if (m_noconv) { + return noconv; + } + std::codecvt_base::result res = error; +#if defined(_WIN32) + from_next = from; + to_next = to; + bool convert = true; + size_t count = from_end - from; + const char* data = from; + unsigned int& stateId = reinterpret_cast<unsigned int&>(state); + if (count == 0) { + return codecvt::ok; + } else if (count == 1) { + if (stateId == 0) { + // decode first byte for UTF-8 + if ((*from & 0xF8) == 0xF0 || // 1111 0xxx; 4 bytes for codepoint + (*from & 0xF0) == 0xE0 || // 1110 xxxx; 3 bytes for codepoint + (*from & 0xE0) == 0xC0) // 110x xxxx; 2 bytes for codepoint + { + stateId = findStateId(); + codecvt::State& s = m_states.at(stateId - 1); + s.bytes[0] = *from; + convert = false; + if ((*from & 0xF8) == 0xF0) { + s.totalBytes = 4; + } else if ((*from & 0xF0) == 0xE0) { + s.totalBytes = 3; + } else if ((*from & 0xE0) == 0xC0) { + s.totalBytes = 2; + } + s.bytesLeft = s.totalBytes - 1; + }; + // else 1 byte for codepoint + } else { + codecvt::State& s = m_states.at(stateId - 1); + s.bytes[s.totalBytes - s.bytesLeft] = *from; + s.bytesLeft--; + data = s.bytes; + count = s.totalBytes - s.bytesLeft; + if ((*from & 0xC0) == 0x80) { // 10xx xxxx + convert = s.bytesLeft == 0; + } else { + // invalid multi-byte + convert = true; + } + if (convert) { + s.used = false; + if (stateId == m_lastState) { + m_lastState--; + } + stateId = 0; + } + } + if (convert) { + std::wstring wide = cmsys::Encoding::ToWide(std::string(data, count)); + int r = WideCharToMultiByte(m_codepage, 0, wide.c_str(), + static_cast<int>(wide.size()), to, + to_end - to, NULL, NULL); + if (r > 0) { + from_next = from_end; + to_next = to + r; + res = ok; + } + } else { + res = partial; + from_next = from_end; + to_next = to; + } + } +#else + static_cast<void>(state); + static_cast<void>(from); + static_cast<void>(from_end); + static_cast<void>(from_next); + static_cast<void>(to); + static_cast<void>(to_end); + static_cast<void>(to_next); + res = codecvt::noconv; +#endif + return res; +}; + +std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to, + char* to_end, + char*& to_next) const +{ + std::codecvt_base::result res = error; + to_next = to; +#if defined(_WIN32) + unsigned int& stateId = reinterpret_cast<unsigned int&>(state); + if (stateId > 0) { + codecvt::State& s = m_states.at(stateId - 1); + s.used = false; + if (stateId == m_lastState) { + m_lastState--; + } + stateId = 0; + std::wstring wide = cmsys::Encoding::ToWide( + std::string(s.bytes, s.totalBytes - s.bytesLeft)); + int r = WideCharToMultiByte(m_codepage, 0, wide.c_str(), + static_cast<int>(wide.size()), to, to_end - to, + NULL, NULL); + if (r > 0) { + to_next = to + r; + res = ok; + } + } else { + res = ok; + } +#else + static_cast<void>(state); + static_cast<void>(to_end); + res = ok; +#endif + return res; +}; + +int codecvt::do_max_length() const throw() +{ + return 4; +}; + +int codecvt::do_encoding() const throw() +{ + return 0; +}; + +unsigned int codecvt::findStateId() const +{ + unsigned int stateId = 0; + bool add = false; + const unsigned int maxSize = std::numeric_limits<unsigned int>::max(); + if (m_lastState >= maxSize) { + m_lastState = 0; + } + if (m_states.size() <= m_lastState) { + add = true; + } else { + unsigned int i = m_lastState; + while (i < maxSize) { + codecvt::State& s = m_states.at(i); + i++; + if (!s.used) { + m_lastState = i; + stateId = m_lastState; + s.used = true; + s.totalBytes = 0; + s.bytesLeft = 0; + break; + } + if (i >= m_states.size()) { + i = 0; + } + if (i == m_lastState) { + add = true; + break; + } + } + }; + if (add) { + codecvt::State s = { true, 0, 0, { 0, 0, 0, 0 } }; + m_states.push_back(s); + m_lastState = (unsigned int)m_states.size(); + stateId = m_lastState; + } + return stateId; +}; diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx new file mode 100644 index 0000000..5f16bd8 --- /dev/null +++ b/Source/cm_codecvt.hxx @@ -0,0 +1,57 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_codecvt_hxx +#define cm_codecvt_hxx + +#include <cmConfigure.h> // IWYU pragma: keep + +#include <locale> +#include <vector> + +class codecvt : public std::codecvt<char, char, mbstate_t> +{ +public: + enum Encoding + { + None, + UTF8, + ANSI + }; + +#ifdef CMAKE_BUILD_WITH_CMAKE + + codecvt(Encoding e); + +protected: + ~codecvt() CM_OVERRIDE; + bool do_always_noconv() const throw() CM_OVERRIDE; + result do_out(mbstate_t& state, const char* from, const char* from_end, + const char*& from_next, char* to, char* to_end, + char*& to_next) const CM_OVERRIDE; + result do_unshift(mbstate_t& state, char* to, char*, + char*& to_next) const CM_OVERRIDE; + int do_max_length() const throw() CM_OVERRIDE; + int do_encoding() const throw() CM_OVERRIDE; + +private: + typedef struct + { + bool used; + unsigned char totalBytes; + unsigned char bytesLeft; + char bytes[4]; + } State; + + unsigned int findStateId() const; + + bool m_noconv; + mutable std::vector<State> m_states; + mutable unsigned int m_lastState; +#if defined(_WIN32) + unsigned int m_codepage; +#endif + +#endif +}; + +#endif diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 1fb39ff..8ab17b9 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -163,11 +163,7 @@ int main(int argc, char const* const* argv) doc.SetSection("Name", cmDocumentationName); doc.SetSection("Usage", cmDocumentationUsage); doc.PrependSection("Options", cmDocumentationOptions); -#ifdef cout -#undef cout -#endif return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; -#define cout no_cout_use_cmCTestLog } } diff --git a/Tests/MacRuntimePath/A/CMakeLists.txt b/Tests/MacRuntimePath/A/CMakeLists.txt index ade0a3c..bf937e6 100644 --- a/Tests/MacRuntimePath/A/CMakeLists.txt +++ b/Tests/MacRuntimePath/A/CMakeLists.txt @@ -40,21 +40,30 @@ target_link_libraries(test3 framework) add_executable(test4 test1.cpp) target_link_libraries(test4 shared2) +# executable to test a shared library dependency with build rpath +add_executable(test5 test1.cpp) + +# avoid linking by 'target_link_libraries' so CMake +# will not be able to set correct RPATH automatically +add_dependencies(test5 shared) +target_link_libraries(test5 "$<TARGET_FILE:shared>") +set_target_properties(test5 PROPERTIES BUILD_RPATH "@loader_path/../lib") + set_target_properties(shared shared2 framework PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") -set_target_properties(test1 test2 test3 test4 PROPERTIES +set_target_properties(test1 test2 test3 test4 test5 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 + set_target_properties(test1 test2 test3 test4 test5 PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${CONFIG} "${CMAKE_CURRENT_BINARY_DIR}/${config}/bin") endforeach() -foreach(test test1 test2 test3 test4) +foreach(test test1 test2 test3 test4 test5) add_custom_target(${test}_run ALL COMMAND ${test} DEPENDS ${test} diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake index 7eac5d6..6ea0909 100644 --- a/Tests/RunCMake/Android/common.cmake +++ b/Tests/RunCMake/Android/common.cmake @@ -17,8 +17,8 @@ foreach(f endif() endforeach() -string(APPEND CMAKE_C_FLAGS " -Werror") -string(APPEND CMAKE_CXX_FLAGS " -Werror") +string(APPEND CMAKE_C_FLAGS " -Werror -Wno-attributes") +string(APPEND CMAKE_CXX_FLAGS " -Werror -Wno-attributes") string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-no-undefined") if(CMAKE_ANDROID_NDK) diff --git a/Tests/RunCMake/CPack/MAIN_COMPONENT.cmake b/Tests/RunCMake/CPack/MAIN_COMPONENT.cmake new file mode 100644 index 0000000..99c6cae --- /dev/null +++ b/Tests/RunCMake/CPack/MAIN_COMPONENT.cmake @@ -0,0 +1,14 @@ +set(CPACK_RPM_COMPONENT_INSTALL "ON") + +install(FILES CMakeLists.txt DESTINATION foo COMPONENT applications) +install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers) +install(FILES CMakeLists.txt DESTINATION bas COMPONENT libs) + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "invalid") + set(CPACK_RPM_MAIN_COMPONENT "") +else() + set(CPACK_RPM_MAIN_COMPONENT "applications") + set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT") +endif() + +set(CPACK_PACKAGE_NAME "main_component") diff --git a/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-ExpectedFiles.cmake b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-ExpectedFiles.cmake new file mode 100644 index 0000000..69603dd --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-ExpectedFiles.cmake @@ -0,0 +1,13 @@ +set(whitespaces_ "[\t\n\r ]*") + +set(EXPECTED_FILES_COUNT "0") + +if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "invalid") + set(EXPECTED_FILES_COUNT "3") + set(EXPECTED_FILE_1 "main_component-0.1.1-1.*.rpm") + set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/CMakeLists.txt$") + set(EXPECTED_FILE_2 "main_component*-headers.rpm") + set(EXPECTED_FILE_CONTENT_2 "^/usr/bar${whitespaces_}/usr/bar/CMakeLists.txt$") + set(EXPECTED_FILE_3 "main_component*-libs.rpm") + set(EXPECTED_FILE_CONTENT_3 "^/usr/bas${whitespaces_}/usr/bas/CMakeLists.txt$") +endif() diff --git a/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-found-stderr.txt b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-found-stderr.txt new file mode 100644 index 0000000..dff163d --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-found-stderr.txt @@ -0,0 +1,3 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/MAIN_COMPONENT-build-found-subtest/_CPack_Packages/.*/RPM/SPECS/main_component-headers.spec +CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/MAIN_COMPONENT-build-found-subtest/_CPack_Packages/.*/RPM/SPECS/main_component-libs.spec +CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/MAIN_COMPONENT-build-found-subtest/_CPack_Packages/.*/RPM/SPECS/main_component.spec$ diff --git a/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-invalid-stderr.txt b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-invalid-stderr.txt new file mode 100644 index 0000000..4d8ac6e --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/MAIN_COMPONENT-invalid-stderr.txt @@ -0,0 +1 @@ +CPACK_RPM_MAIN_COMPONENT set to non existing component. diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-ExpectedFiles.cmake b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-ExpectedFiles.cmake new file mode 100644 index 0000000..dc49343 --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-ExpectedFiles.cmake @@ -0,0 +1,30 @@ +set(whitespaces_ "[\t\n\r ]*") + +set(EXPECTED_FILES_COUNT "0") + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo") + set(EXPECTED_FILES_COUNT "4") + set(EXPECTED_FILE_1 "single_debuginfo-0.1.1-1.*.rpm") + set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/test_prog$") + set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm") + set(EXPECTED_FILE_CONTENT_2 "^/usr/bar${whitespaces_}/usr/bar/CMakeLists.txt$") + set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm") + set(EXPECTED_FILE_CONTENT_3 "^/usr/bas${whitespaces_}/usr/bas/libtest_lib.so$") + + set(EXPECTED_FILE_4 "single_debuginfo-debuginfo*.rpm") + set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo") + set(EXPECTED_FILES_COUNT "2") + set(EXPECTED_FILE_1 "single_debuginfo-0*-applications.rpm") + set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/test_prog$") + + set(EXPECTED_FILE_2 "single_debuginfo-applications-debuginfo*.rpm") + set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_components") + set(EXPECTED_FILES_COUNT "2") + set(EXPECTED_FILE_1 "single_debuginfo-0*.rpm") + set(EXPECTED_FILE_CONTENT_1 "^/usr/foo${whitespaces_}/usr/foo/test_prog$") + + set(EXPECTED_FILE_2 "single_debuginfo-debuginfo*.rpm") + set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*") +endif() diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_components-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_components-stderr.txt new file mode 100644 index 0000000..d80939f --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_components-stderr.txt @@ -0,0 +1 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_components-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$ diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_debuginfo-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_debuginfo-stderr.txt new file mode 100644 index 0000000..86396db --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_debuginfo-stderr.txt @@ -0,0 +1,3 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-headers.spec +CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-libs.spec +CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$ diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_main_component-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_main_component-stderr.txt new file mode 100644 index 0000000..454283c --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-no_main_component-stderr.txt @@ -0,0 +1 @@ +CPack Error: CPACK_RPM_MAIN_COMPONENT not set but it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE being set. diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component-stderr.txt new file mode 100644 index 0000000..080c4ff --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component-stderr.txt @@ -0,0 +1 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-one_component-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-applications.spec$ diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_main-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_main-stderr.txt new file mode 100644 index 0000000..665597c --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_main-stderr.txt @@ -0,0 +1 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-one_component_main-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$ diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_no_debuginfo-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_no_debuginfo-stderr.txt new file mode 100644 index 0000000..b64b1f5 --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-one_component_no_debuginfo-stderr.txt @@ -0,0 +1 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-one_component_no_debuginfo-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-applications.spec$ diff --git a/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-valid-stderr.txt b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-valid-stderr.txt new file mode 100644 index 0000000..f4c1bef --- /dev/null +++ b/Tests/RunCMake/CPack/RPM/SINGLE_DEBUGINFO-valid-stderr.txt @@ -0,0 +1,3 @@ +^CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-valid-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-headers.spec +CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-valid-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo-libs.spec +CPackRPM: Will use GENERATED spec file: .*/Tests/RunCMake/RPM/CPack/SINGLE_DEBUGINFO-build-valid-subtest/_CPack_Packages/.*/RPM/SPECS/single_debuginfo.spec$ diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 60d42ac..474ee33 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -12,11 +12,13 @@ run_cpack_test(DEPENDENCIES "RPM;DEB" true) run_cpack_test(EMPTY_DIR "RPM;DEB;TGZ" true) run_cpack_test(COMPONENTS_EMPTY_DIR "RPM;DEB;TGZ" true) run_cpack_test(CUSTOM_NAMES "RPM;DEB" true) +run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM" false) run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false) run_cpack_test(RPM_DIST "RPM" false) run_cpack_test(INSTALL_SCRIPTS "RPM" false) run_cpack_test(DEB_GENERATE_SHLIBS "DEB" true) run_cpack_test(DEB_GENERATE_SHLIBS_LDCONFIG "DEB" true) run_cpack_test(DEBUGINFO "RPM" true) +run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component;one_component;one_component_main;no_debuginfo;one_component_no_debuginfo;no_components;valid" "RPM" true) run_cpack_test(LONG_FILENAMES "DEB" false) run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false) diff --git a/Tests/RunCMake/CPack/SINGLE_DEBUGINFO.cmake b/Tests/RunCMake/CPack/SINGLE_DEBUGINFO.cmake new file mode 100644 index 0000000..ae4995e --- /dev/null +++ b/Tests/RunCMake/CPack/SINGLE_DEBUGINFO.cmake @@ -0,0 +1,56 @@ +set(CMAKE_BUILD_WITH_INSTALL_RPATH 1) + +# PGI compiler doesn't add build id to binaries by default +if(CMAKE_CXX_COMPILER_ID STREQUAL "PGI") + string(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--build-id") + string(APPEND CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id") +endif() + +if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "no_components") + set(CPACK_RPM_COMPONENT_INSTALL "ON") +endif() + +set(CMAKE_BUILD_TYPE Debug) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.hpp" + "int test_lib();\n") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp" + "#include \"test_lib.hpp\"\nint test_lib() {return 0;}\n") +add_library(test_lib SHARED "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp" + "#include \"test_lib.hpp\"\nint main() {return test_lib();}\n") +add_executable(test_prog "${CMAKE_CURRENT_BINARY_DIR}/main.cpp") +target_link_libraries(test_prog test_lib) + +install(TARGETS test_prog DESTINATION foo COMPONENT applications) + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_main_component" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo") + install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers) + install(TARGETS test_lib DESTINATION bas COMPONENT libs) +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo") + set(CPACK_COMPONENTS_ALL applications) +endif() + +set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo") + set(CPACK_RPM_MAIN_COMPONENT "applications") + set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT") +endif() + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_main_component" + OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component") + set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON) + set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON) +endif() + +set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/src") + +set(CPACK_PACKAGE_NAME "single_debuginfo") diff --git a/Utilities/GitSetup/config b/Utilities/GitSetup/config index b7d5423..d69a679 100644 --- a/Utilities/GitSetup/config +++ b/Utilities/GitSetup/config @@ -1,5 +1,5 @@ [hooks] - url = http://cmake.org/cmake.git + url = https://cmake.org/cmake.git [ssh] host = cmake.org key = id_git_cmake diff --git a/Utilities/Release/README b/Utilities/Release/README index ed1d52e..11de1c3 100644 --- a/Utilities/Release/README +++ b/Utilities/Release/README @@ -1,7 +1,7 @@ To create a cmake release, make sure the "release" tag is pointing to the expected git commit: -http://cmake.org/gitweb?p=cmake.git;a=shortlog;h=refs/heads/release +https://cmake.org/gitweb?p=cmake.git;a=shortlog;h=refs/heads/release Then as kitware@hythloth, using an up-to-date CMake: diff --git a/Utilities/Release/linux64_release.cmake b/Utilities/Release/linux64_release.cmake index b72fc12..b9447ca 100644 --- a/Utilities/Release/linux64_release.cmake +++ b/Utilities/Release/linux64_release.cmake @@ -2,6 +2,7 @@ set(PROCESSORS 4) set(BOOTSTRAP_ARGS "--docdir=doc/cmake") set(HOST linux64) set(MAKE_PROGRAM "make") +set(CPACK_BINARY_GENERATORS "STGZ TGZ") set(CC /opt/gcc-6.1.0/bin/gcc) set(CXX /opt/gcc-6.1.0/bin/g++) set(CFLAGS "") diff --git a/Utilities/Release/osx_release.cmake b/Utilities/Release/osx_release.cmake index 27c820f..88ea39b 100644 --- a/Utilities/Release/osx_release.cmake +++ b/Utilities/Release/osx_release.cmake @@ -4,7 +4,7 @@ set(BOOTSTRAP_ARGS "--prefix=/ --docdir=doc/cmake") set(HOST dragnipur) set(MAKE_PROGRAM "make") set(MAKE "${MAKE_PROGRAM} -j5") -set(CPACK_BINARY_GENERATORS "DragNDrop TGZ TZ") +set(CPACK_BINARY_GENERATORS "DragNDrop TGZ") set(CPACK_SOURCE_GENERATORS "TGZ TZ") set(CPACK_DMG_FORMAT "UDBZ") #build using bzip2 for smaller package size set(CC clang) |