diff --git a/scripts/cmake/vcpkg_fixup_pkgconfig.cmake b/scripts/cmake/vcpkg_fixup_pkgconfig.cmake index a9b9723e002..3f37099a71c 100644 --- a/scripts/cmake/vcpkg_fixup_pkgconfig.cmake +++ b/scripts/cmake/vcpkg_fixup_pkgconfig.cmake @@ -45,122 +45,115 @@ Still work in progress. If there are more cases which can be handled here feel f * [brotli](https://github.com/Microsoft/vcpkg/blob/master/ports/brotli/portfile.cmake) #]===] -function(z_vcpkg_fixup_pkgconfig_check_files file config) - set(path_suffix_debug /debug) - set(path_suffix_release "") +function(vcpkg_fixup_pkgconfig_check_files pkg_cfg_cmd _file _config) + set(PATH_SUFFIX_DEBUG /debug) + set(PATH_SUFFIX_RELEASE) + set(PKGCONFIG_INSTALLED_DIR "${CURRENT_INSTALLED_DIR}${PATH_SUFFIX_${_config}}/lib/pkgconfig") + set(PKGCONFIG_INSTALLED_SHARE_DIR "${CURRENT_INSTALLED_DIR}/share/pkgconfig") + set(PKGCONFIG_PACKAGES_DIR "${CURRENT_PACKAGES_DIR}${PATH_SUFFIX_${_config}}/lib/pkgconfig") + set(PKGCONFIG_PACKAGES_SHARE_DIR "${CURRENT_PACKAGES_DIR}/share/pkgconfig") if(DEFINED ENV{PKG_CONFIG_PATH}) - set(backup_env_pkg_config_path "$ENV{PKG_CONFIG_PATH}") + set(BACKUP_ENV_PKG_CONFIG_PATH "$ENV{PKG_CONFIG_PATH}") else() - unset(backup_env_pkg_config_path) + unset(BACKUP_ENV_PKG_CONFIG_PATH) endif() - - vcpkg_list(SET pkg_config_path - "${CURRENT_INSTALLED_DIR}${PATH_SUFFIX_${_config}}/lib/pkgconfig" - "${CURRENT_INSTALLED_DIR}/share/pkgconfig" - "${CURRENT_PACKAGES_DIR}${PATH_SUFFIX_${_config}}/lib/pkgconfig" - "${CURRENT_PACKAGES_DIR}/share/pkgconfig" - ) if(DEFINED ENV{PKG_CONFIG_PATH} AND NOT ENV{PKG_CONFIG_PATH} STREQUAL "") - vcpkg_list(APPEND pkg_config_path "$ENV{PKG_CONFIG_PATH}") + set(ENV{PKG_CONFIG_PATH} "${PKGCONFIG_INSTALLED_DIR}${VCPKG_HOST_PATH_SEPARATOR}${PKGCONFIG_INSTALLED_SHARE_DIR}${VCPKG_HOST_PATH_SEPARATOR}${PKGCONFIG_PACKAGES_DIR}${VCPKG_HOST_PATH_SEPARATOR}${PKGCONFIG_PACKAGES_SHARE_DIR}${VCPKG_HOST_PATH_SEPARATOR}$ENV{PKG_CONFIG_PATH}") + else() + set(ENV{PKG_CONFIG_PATH} "${PKGCONFIG_INSTALLED_DIR}${VCPKG_HOST_PATH_SEPARATOR}${PKGCONFIG_INSTALLED_SHARE_DIR}${VCPKG_HOST_PATH_SEPARATOR}${PKGCONFIG_PACKAGES_DIR}${VCPKG_HOST_PATH_SEPARATOR}${PKGCONFIG_PACKAGES_SHARE_DIR}") endif() - vcpkg_list(JOIN pkg_config_path "${VCPKG_PATH_SEPARATOR}" pkg_config_path) - set(ENV{PKG_CONFIG_PATH} "${pkg_config_path}") # First make sure everything is ok with the package and its deps - cmake_path(GET file STEM package_name) - debug_message("Checking package (${config}): ${package_name}") - execute_process( - COMMAND "${PKGCONFIG}" --print-errors --exists "${package_name}" - WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" - RESULT_VARIABLE error_var - OUTPUT_VARIABLE output - ERROR_VARIABLE output - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE - ) - if(NOT "${error_var}" EQUAL "0") - message(FATAL_ERROR "${PKGCONFIG} --exists ${package_name} failed with error code: ${error_var} - ENV{PKG_CONFIG_PATH}: \"$ENV{PKG_CONFIG_PATH}\" - output: ${output}" - ) + get_filename_component(_package_name "${_file}" NAME_WLE) + debug_message("Checking package (${_config}): ${_package_name}") + execute_process(COMMAND "${pkg_cfg_cmd}" --print-errors --exists ${_package_name} + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" + RESULT_VARIABLE _pkg_error_var + OUTPUT_VARIABLE _pkg_output + ERROR_VARIABLE _pkg_error_out + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) + if(NOT _pkg_error_var EQUAL 0) + message(STATUS "pkg_cfg_cmd call with:${pkg_cfg_cmd} --exists ${_package_name} failed") + message(STATUS "ENV{PKG_CONFIG_PATH}:$ENV{PKG_CONFIG_PATH}") + message(STATUS "pkg-config call failed with error code:${_pkg_error_var}") + message(STATUS "pkg-config output:${_pkg_output}") + message(FATAL_ERROR "pkg-config error output:${_pkg_error_out}") else() - debug_message("pkg-config --exists ${package_name} output: ${output}") + debug_message("pkg-config returned:${_pkg_error_var}") + debug_message("pkg-config output:${_pkg_output}") + debug_message("pkg-config error output:${_pkg_error_out}") endif() - if(DEFINED backup_env_pkg_config_path) - set(ENV{PKG_CONFIG_PATH} "${backup_env_pkg_config_path}") + if(DEFINED BACKUP_ENV_PKG_CONFIG_PATH) + set(ENV{PKG_CONFIG_PATH} "${BACKUP_ENV_PKG_CONFIG_PATH}") else() unset(ENV{PKG_CONFIG_PATH}) endif() endfunction() function(vcpkg_fixup_pkgconfig) - cmake_parse_arguments(PARSE_ARGV 0 arg - "SKIP_CHECK" - "" - "RELEASE_FILES;DEBUG_FILES;SYSTEM_LIBRARIES;SYSTEM_PACKAGES;IGNORE_FLAGS" - ) + # parse parameters such that semicolons in options arguments to COMMAND don't get erased + cmake_parse_arguments(PARSE_ARGV 0 _vfpkg "SKIP_CHECK" "" "RELEASE_FILES;DEBUG_FILES;SYSTEM_LIBRARIES;SYSTEM_PACKAGES;IGNORE_FLAGS") - if(DEFINED arg_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} was passed extra arguments: ${arg_UNPARSED_ARGUMENTS}") + if(_vfpkg_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "vcpkg_fixup_pkgconfig() was passed extra arguments: ${_vfct_UNPARSED_ARGUMENTS}") endif() - if(DEFINED arg_RELEASE_FILES AND NOT DEFINED arg_DEBUG_FILES) - message(FATAL_ERROR "DEBUG_FILES must be specified if RELEASE_FILES was specified.") - endif() - if(NOT DEFINED arg_RELEASE_FILES AND DEFINED arg_DEBUG_FILES) - message(FATAL_ERROR "RELEASE_FILES must be specified if DEBUG_FILES was specified.") + if((DEFINED _vfpkg_RELEASE_FILES AND NOT DEFINED _vfpkg_DEBUG_FILES) OR (NOT DEFINED _vfpkg_RELEASE_FILES AND DEFINED _vfpkg_DEBUG_FILES)) + message(FATAL_ERROR "vcpkg_fixup_pkgconfig() requires both or neither of DEBUG_FILES and RELEASE_FILES") endif() - if(NOT DEFINED arg_RELEASE_FILES) - file(GLOB_RECURSE arg_RELEASE_FILES "${CURRENT_PACKAGES_DIR}/**/*.pc") - file(GLOB_RECURSE arg_DEBUG_FILES "${CURRENT_PACKAGES_DIR}/debug/**/*.pc") - foreach(debug_file IN LISTS arg_DEBUG_FILES) - vcpkg_list(REMOVE_ITEM arg_RELEASE_FILES "${debug_file}") - endforeach() + if(NOT DEFINED _vfpkg_RELEASE_FILES) + file(GLOB_RECURSE _vfpkg_RELEASE_FILES "${CURRENT_PACKAGES_DIR}/**/*.pc") + file(GLOB_RECURSE _vfpkg_DEBUG_FILES "${CURRENT_PACKAGES_DIR}/debug/**/*.pc") + if(_vfpkg_DEBUG_FILES) + list(REMOVE_ITEM _vfpkg_RELEASE_FILES ${_vfpkg_DEBUG_FILES}) + endif() endif() vcpkg_find_acquire_program(PKGCONFIG) debug_message("Using pkg-config from: ${PKGCONFIG}") - string(REGEX REPLACE "^([a-zA-Z]):/" [[/\1/]] unix_packages_dir "${CURRENT_PACKAGES_DIR}") - string(REGEX REPLACE "^([a-zA-Z]):/" [[/\1/]] unix_installed_dir "${CURRENT_INSTALLED_DIR}") + #Absolute Unix like paths + string(REGEX REPLACE "([a-zA-Z]):/" "/\\1/" _VCPKG_PACKAGES_DIR "${CURRENT_PACKAGES_DIR}") + string(REGEX REPLACE "([a-zA-Z]):/" "/\\1/" _VCPKG_INSTALLED_DIR "${CURRENT_INSTALLED_DIR}") - foreach(config IN ITEMS RELEASE DEBUG) - debug_message("${config} Files: ${arg_${config}_FILES}") - if("${VCPKG_BUILD_TYPE}" STREQUAL "debug" AND "${config}" STREQUAL "RELEASE") + foreach(CONFIG RELEASE DEBUG) + debug_message("${CONFIG} Files: ${_vfpkg_${CONFIG}_FILES}") + if(VCPKG_BUILD_TYPE STREQUAL "debug" AND CONFIG STREQUAL "RELEASE") continue() endif() - if("${VCPKG_BUILD_TYPE}" STREQUAL "release" AND "${config}" STREQUAL "DEBUG") + if(VCPKG_BUILD_TYPE STREQUAL "release" AND CONFIG STREQUAL "DEBUG") continue() endif() - foreach(file IN LISTS "arg_${config}_FILES") - message(STATUS "Fixing pkgconfig file: ${file}") - cmake_path(GET file PARENT_PATH pkg_lib_search_path) - if("${config}" STREQUAL "DEBUG") - set(relative_pc_path "${CURRENT_PACKAGES_DIR}/debug") - cmake_path(RELATIVE_PATH relative_pc_path BASE_DIRECTORY "${pkg_lib_search_path}") + foreach(_file ${_vfpkg_${CONFIG}_FILES}) + message(STATUS "Fixing pkgconfig file: ${_file}") + get_filename_component(PKG_LIB_SEARCH_PATH "${_file}" DIRECTORY) + if(CONFIG STREQUAL "DEBUG") + file(RELATIVE_PATH RELATIVE_PC_PATH "${PKG_LIB_SEARCH_PATH}" "${CURRENT_PACKAGES_DIR}/debug/") else() - set(relative_pc_path "${CURRENT_PACKAGES_DIR}") - cmake_path(RELATIVE_PATH relative_pc_path BASE_DIRECTORY "${pkg_lib_search_path}") + file(RELATIVE_PATH RELATIVE_PC_PATH "${PKG_LIB_SEARCH_PATH}" "${CURRENT_PACKAGES_DIR}") endif() + # strip trailing slash + string(REGEX REPLACE "/$" "" RELATIVE_PC_PATH "${RELATIVE_PC_PATH}") #Correct *.pc file - file(READ "${file}" contents) - - string(REPLACE "${CURRENT_PACKAGES_DIR}" [[${prefix}]] contents "${contents}") - string(REPLACE "${CURRENT_INSTALLED_DIR}" [[${prefix}]] contents "${contents}") - string(REPLACE "${unix_packages_dir}" [[${prefix}]] contents "${contents}") - string(REPLACE "${unix_installed_dir}" [[${prefix}]] contents "${contents}") - - string(REGEX REPLACE "(^|\n)prefix[\t ]*=[^\n]*" "" contents "${contents}") - if("${config}" STREQUAL "DEBUG") - # prefix points at the debug subfolder - string(REPLACE [[${prefix}/debug]] [[${prefix}]] contents "${contents}") - string(REPLACE [[${prefix}/include]] [[${prefix}/../include]] contents "${contents}") - string(REPLACE [[${prefix}/share]] [[${prefix}/../share]] contents "${contents}") + file(READ "${_file}" _contents) + string(REPLACE "${CURRENT_PACKAGES_DIR}" "\${prefix}" _contents "${_contents}") + string(REPLACE "${CURRENT_INSTALLED_DIR}" "\${prefix}" _contents "${_contents}") + string(REPLACE "${_VCPKG_PACKAGES_DIR}" "\${prefix}" _contents "${_contents}") + string(REPLACE "${_VCPKG_INSTALLED_DIR}" "\${prefix}" _contents "${_contents}") + string(REGEX REPLACE "(^|\n)prefix[\t ]*=[^\n]*" "" _contents "${_contents}") + if(CONFIG STREQUAL "DEBUG") + string(REPLACE "}/debug" "}" _contents "${_contents}") + # Prefix points at the debug subfolder + string(REPLACE "\${prefix}/include" "\${prefix}/../include" _contents "${_contents}") + string(REPLACE "\${prefix}/share" "\${prefix}/../share" _contents "${_contents}") endif() - # quote -L, -I, and -l paths starting with `${blah}` - string(REGEX REPLACE " -([LIl])(\\\${[^}]*}[^ \n\t]*)" [[ -\1"\2"]] contents "${contents}") + string(REGEX REPLACE " -L(\\\${[^}]*}[^ \n\t]*)" " -L\"\\1\"" _contents "${_contents}") + string(REGEX REPLACE " -I(\\\${[^}]*}[^ \n\t]*)" " -I\"\\1\"" _contents "${_contents}") + string(REGEX REPLACE " -l(\\\${[^}]*}[^ \n\t]*)" " -l\"\\1\"" _contents "${_contents}") # This section fuses XYZ.private and XYZ according to VCPKG_LIBRARY_LINKAGE # # Pkgconfig searches Requires.private transitively for Cflags in the dynamic case, @@ -168,51 +161,33 @@ function(vcpkg_fixup_pkgconfig) # # Once this transformation is complete, users of vcpkg should never need to pass # --static. - if("${VCPKG_LIBRARY_LINKAGE}" STREQUAL "static") - # how this works: - # we want to transform: - # Libs: $1 - # Libs.private: $2 - # into - # Libs: $1 $2 - # and the same thing for Requires and Requires.private - - set(libs_line "") - set(requires_line "") - if("${contents}" MATCHES "Libs: *([^\n]*)") - string(APPEND libs_line " ${CMAKE_MATCH_1}") - endif() - if("${contents}" MATCHES "Libs.private: *([^\n]*)") - string(APPEND libs_line " ${CMAKE_MATCH_1}") - endif() - if("${contents}" MATCHES "Requires: *([^\n]*)") - string(APPEND requires_line " ${CMAKE_MATCH_1}") - endif() - if("${contents}" MATCHES "Requires.private: *([^\n]*)") - string(APPEND requires_line " ${CMAKE_MATCH_1}") - endif() - - string(REGEX REPLACE "(^|\n)(Requires|Libs)(\\.private)?:[^\n]*\n" [[\1]] contents "${contents}") - - if(NOT "${libs_line}" STREQUAL "") - string(APPEND contents "Libs:${libs_line}\n") - endif() - if(NOT "${requires_line}" STREQUAL "") - string(APPEND contents "Requires:${requires_line}\n") - endif() + if(VCPKG_LIBRARY_LINKAGE STREQUAL "static") + # Libs comes before Libs.private + string(REGEX REPLACE "(^|\n)(Libs: *[^\n]*)(.*)\nLibs.private:( *[^\n]*)" "\\1\\2\\4\\3" _contents "${_contents}") + # Libs.private comes before Libs + string(REGEX REPLACE "(^|\n)Libs.private:( *[^\n]*)(.*\nLibs: *[^\n]*)" "\\3\\2" _contents "${_contents}") + # Only Libs.private + string(REGEX REPLACE "(^|\n)Libs.private: *" "\\1Libs: " _contents "${_contents}") + # Requires comes before Requires.private + string(REGEX REPLACE "(^|\n)(Requires: *[^\n]*)(.*)\nRequires.private:( *[^\n]*)" "\\1\\2\\4\\3" _contents "${_contents}") + # Requires.private comes before Requires + string(REGEX REPLACE "(^|\n)Requires.private:( *[^\n]*)(.*\nRequires: *[^\n]*)" "\\3\\2" _contents "${_contents}") + # Only Requires.private + string(REGEX REPLACE "(^|\n)Requires.private: *" "\\1Requires: " _contents "${_contents}") endif() - file(WRITE "${file}" "prefix=\${pcfiledir}/${relative_pc_path}\n${contents}") + file(WRITE "${_file}" "prefix=\${pcfiledir}/${RELATIVE_PC_PATH}\n${_contents}") + unset(PKG_LIB_SEARCH_PATH) endforeach() - if(NOT arg_SKIP_CHECK) # The check can only run after all files have been corrected! - foreach(file IN LISTS "arg_${config}_FILES") - z_vcpkg_fixup_pkgconfig_check_files("${PKGCONFIG}" "${file}" "${config}") + if(NOT _vfpkg_SKIP_CHECK) # The check can only run after all files have been corrected! + foreach(_file ${_vfpkg_${CONFIG}_FILES}) + vcpkg_fixup_pkgconfig_check_files("${PKGCONFIG}" "${_file}" "${CONFIG}") endforeach() endif() endforeach() debug_message("Fixing pkgconfig --- finished") - set(Z_VCPKG_FIXUP_PKGCONFIG_CALLED TRUE CACHE INTERNAL "See below" FORCE) + set(VCPKG_FIXUP_PKGCONFIG_CALLED TRUE CACHE INTERNAL "See below" FORCE) # Variable to check if this function has been called! # Theoreotically vcpkg could look for *.pc files and automatically call this function # or check if this function has been called if *.pc files are detected.