2 # vcpkg_fixup_pkgconfig
4 Fix common paths in *.pc files and make everything relative to $(prefix)
9 [RELEASE_FILES <PATHS>...]
10 [DEBUG_FILES <PATHS>...]
17 Specifies a list of files to apply the fixes for release paths.
18 Defaults to every *.pc file in the folder ${CURRENT_PACKAGES_DIR} without ${CURRENT_PACKAGES_DIR}/debug/
21 Specifies a list of files to apply the fixes for debug paths.
22 Defaults to every *.pc file in the folder ${CURRENT_PACKAGES_DIR}/debug/
25 Skips the library checks in vcpkg_fixup_pkgconfig. Only use if the script itself has unhandled cases.
27 ### SYSTEM_PACKAGES (deprecated)
28 This argument has been deprecated and has no effect.
30 ### SYSTEM_LIBRARIES (deprecated)
31 This argument has been deprecated and has no effect.
33 ### IGNORE_FLAGS (deprecated)
34 This argument has been deprecated and has no effect.
37 Still work in progress. If there are more cases which can be handled here feel free to add them
41 * [brotli](https://github.com/Microsoft/vcpkg/blob/master/ports/brotli/portfile.cmake)
44 function(vcpkg_fixup_pkgconfig_check_files pkg_cfg_cmd _file _config)
45 set(PATH_SUFFIX_DEBUG /debug)
46 set(PATH_SUFFIX_RELEASE)
47 set(PKGCONFIG_INSTALLED_DIR "${CURRENT_INSTALLED_DIR}${PATH_SUFFIX_${_config}}/lib/pkgconfig")
48 set(PKGCONFIG_INSTALLED_SHARE_DIR "${CURRENT_INSTALLED_DIR}/share/pkgconfig")
49 set(PKGCONFIG_PACKAGES_DIR "${CURRENT_PACKAGES_DIR}${PATH_SUFFIX_${_config}}/lib/pkgconfig")
50 set(PKGCONFIG_PACKAGES_SHARE_DIR "${CURRENT_PACKAGES_DIR}/share/pkgconfig")
52 if(DEFINED ENV{PKG_CONFIG_PATH})
53 set(BACKUP_ENV_PKG_CONFIG_PATH "$ENV{PKG_CONFIG_PATH}")
55 unset(BACKUP_ENV_PKG_CONFIG_PATH)
57 if(DEFINED ENV{PKG_CONFIG_PATH} AND NOT ENV{PKG_CONFIG_PATH} STREQUAL "")
58 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}")
60 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}")
63 # First make sure everything is ok with the package and its deps
64 get_filename_component(_package_name "${_file}" NAME_WLE)
65 debug_message("Checking package (${_config}): ${_package_name}")
66 execute_process(COMMAND "${pkg_cfg_cmd}" --print-errors --exists ${_package_name}
67 WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}"
68 RESULT_VARIABLE _pkg_error_var
69 OUTPUT_VARIABLE _pkg_output
70 ERROR_VARIABLE _pkg_error_out
71 OUTPUT_STRIP_TRAILING_WHITESPACE
72 ERROR_STRIP_TRAILING_WHITESPACE
74 if(NOT _pkg_error_var EQUAL 0)
75 message(STATUS "pkg_cfg_cmd call with:${pkg_cfg_cmd} --exists ${_package_name} failed")
76 message(STATUS "ENV{PKG_CONFIG_PATH}:$ENV{PKG_CONFIG_PATH}")
77 message(STATUS "pkg-config call failed with error code:${_pkg_error_var}")
78 message(STATUS "pkg-config output:${_pkg_output}")
79 message(FATAL_ERROR "pkg-config error output:${_pkg_error_out}")
81 debug_message("pkg-config returned:${_pkg_error_var}")
82 debug_message("pkg-config output:${_pkg_output}")
83 debug_message("pkg-config error output:${_pkg_error_out}")
85 if(DEFINED BACKUP_ENV_PKG_CONFIG_PATH)
86 set(ENV{PKG_CONFIG_PATH} "${BACKUP_ENV_PKG_CONFIG_PATH}")
88 unset(ENV{PKG_CONFIG_PATH})
92 function(vcpkg_fixup_pkgconfig)
93 # parse parameters such that semicolons in options arguments to COMMAND don't get erased
94 cmake_parse_arguments(PARSE_ARGV 0 _vfpkg "SKIP_CHECK" "" "RELEASE_FILES;DEBUG_FILES;SYSTEM_LIBRARIES;SYSTEM_PACKAGES;IGNORE_FLAGS")
96 if(_vfpkg_UNPARSED_ARGUMENTS)
97 message(FATAL_ERROR "vcpkg_fixup_pkgconfig() was passed extra arguments: ${_vfct_UNPARSED_ARGUMENTS}")
100 if((DEFINED _vfpkg_RELEASE_FILES AND NOT DEFINED _vfpkg_DEBUG_FILES) OR (NOT DEFINED _vfpkg_RELEASE_FILES AND DEFINED _vfpkg_DEBUG_FILES))
101 message(FATAL_ERROR "vcpkg_fixup_pkgconfig() requires both or neither of DEBUG_FILES and RELEASE_FILES")
104 if(NOT DEFINED _vfpkg_RELEASE_FILES)
105 file(GLOB_RECURSE _vfpkg_RELEASE_FILES "${CURRENT_PACKAGES_DIR}/**/*.pc")
106 file(GLOB_RECURSE _vfpkg_DEBUG_FILES "${CURRENT_PACKAGES_DIR}/debug/**/*.pc")
107 if(_vfpkg_DEBUG_FILES)
108 list(REMOVE_ITEM _vfpkg_RELEASE_FILES ${_vfpkg_DEBUG_FILES})
112 vcpkg_find_acquire_program(PKGCONFIG)
113 debug_message("Using pkg-config from: ${PKGCONFIG}")
115 #Absolute Unix like paths
116 string(REGEX REPLACE "([a-zA-Z]):/" "/\\1/" _VCPKG_PACKAGES_DIR "${CURRENT_PACKAGES_DIR}")
117 string(REGEX REPLACE "([a-zA-Z]):/" "/\\1/" _VCPKG_INSTALLED_DIR "${CURRENT_INSTALLED_DIR}")
119 foreach(CONFIG RELEASE DEBUG)
120 debug_message("${CONFIG} Files: ${_vfpkg_${CONFIG}_FILES}")
121 if(VCPKG_BUILD_TYPE STREQUAL "debug" AND CONFIG STREQUAL "RELEASE")
124 if(VCPKG_BUILD_TYPE STREQUAL "release" AND CONFIG STREQUAL "DEBUG")
127 foreach(_file ${_vfpkg_${CONFIG}_FILES})
128 message(STATUS "Fixing pkgconfig file: ${_file}")
129 get_filename_component(PKG_LIB_SEARCH_PATH "${_file}" DIRECTORY)
130 if(CONFIG STREQUAL "DEBUG")
131 file(RELATIVE_PATH RELATIVE_PC_PATH "${PKG_LIB_SEARCH_PATH}" "${CURRENT_PACKAGES_DIR}/debug/")
133 file(RELATIVE_PATH RELATIVE_PC_PATH "${PKG_LIB_SEARCH_PATH}" "${CURRENT_PACKAGES_DIR}")
135 # strip trailing slash
136 string(REGEX REPLACE "/$" "" RELATIVE_PC_PATH "${RELATIVE_PC_PATH}")
138 file(READ "${_file}" _contents)
139 string(REPLACE "${CURRENT_PACKAGES_DIR}" "\${prefix}" _contents "${_contents}")
140 string(REPLACE "${CURRENT_INSTALLED_DIR}" "\${prefix}" _contents "${_contents}")
141 string(REPLACE "${_VCPKG_PACKAGES_DIR}" "\${prefix}" _contents "${_contents}")
142 string(REPLACE "${_VCPKG_INSTALLED_DIR}" "\${prefix}" _contents "${_contents}")
143 string(REGEX REPLACE "(^|\n)prefix[\t ]*=[^\n]*" "" _contents "${_contents}")
144 if(CONFIG STREQUAL "DEBUG")
145 string(REPLACE "}/debug" "}" _contents "${_contents}")
146 # Prefix points at the debug subfolder
147 string(REPLACE "\${prefix}/include" "\${prefix}/../include" _contents "${_contents}")
148 string(REPLACE "\${prefix}/share" "\${prefix}/../share" _contents "${_contents}")
150 string(REGEX REPLACE " -L(\\\${[^}]*}[^ \n\t]*)" " -L\"\\1\"" _contents "${_contents}")
151 string(REGEX REPLACE " -I(\\\${[^}]*}[^ \n\t]*)" " -I\"\\1\"" _contents "${_contents}")
152 string(REGEX REPLACE " -l(\\\${[^}]*}[^ \n\t]*)" " -l\"\\1\"" _contents "${_contents}")
153 # This section fuses XYZ.private and XYZ according to VCPKG_LIBRARY_LINKAGE
155 # Pkgconfig searches Requires.private transitively for Cflags in the dynamic case,
156 # which prevents us from removing it.
158 # Once this transformation is complete, users of vcpkg should never need to pass
160 if(VCPKG_LIBRARY_LINKAGE STREQUAL "static")
161 # Libs comes before Libs.private
162 string(REGEX REPLACE "(^|\n)(Libs: [^\n]*)(.*)\nLibs.private:( [^\n]*)" "\\1\\2\\4\\3" _contents "${_contents}")
163 # Libs.private comes before Libs
164 string(REGEX REPLACE "(^|\n)Libs.private:( [^\n]*)(.*\nLibs: [^\n]*)" "\\3\\2" _contents "${_contents}")
166 string(REGEX REPLACE "(^|\n)Libs.private: " "\\1Libs: " _contents "${_contents}")
167 # Requires comes before Requires.private
168 string(REGEX REPLACE "(^|\n)(Requires: [^\n]*)(.*)\nRequires.private:( [^\n]*)" "\\1\\2\\4\\3" _contents "${_contents}")
169 # Requires.private comes before Requires
170 string(REGEX REPLACE "(^|\n)Requires.private:( [^\n]*)(.*\nRequires: [^\n]*)" "\\3\\2" _contents "${_contents}")
171 # Only Requires.private
172 string(REGEX REPLACE "(^|\n)Requires.private: " "\\1Requires: " _contents "${_contents}")
174 file(WRITE "${_file}" "prefix=\${pcfiledir}/${RELATIVE_PC_PATH}\n${_contents}")
175 unset(PKG_LIB_SEARCH_PATH)
178 if(NOT _vfpkg_SKIP_CHECK) # The check can only run after all files have been corrected!
179 foreach(_file ${_vfpkg_${CONFIG}_FILES})
180 vcpkg_fixup_pkgconfig_check_files("${PKGCONFIG}" "${_file}" "${CONFIG}")
184 debug_message("Fixing pkgconfig --- finished")
186 set(VCPKG_FIXUP_PKGCONFIG_CALLED TRUE CACHE INTERNAL "See below" FORCE)
187 # Variable to check if this function has been called!
188 # Theoreotically vcpkg could look for *.pc files and automatically call this function
189 # or check if this function has been called if *.pc files are detected.
190 # The same is true for vcpkg_fixup_cmake_targets