Browse Source

FindPkgConfig: fix handling of frameworks

Rolf Eike Beer 6 years ago
parent
commit
95ead38375

+ 37 - 0
Modules/FindPkgConfig.cmake

@@ -212,7 +212,13 @@ function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path)
   endif()
 
   unset(_search_paths)
+  unset(_next_is_framework)
   foreach (flag IN LISTS ${_prefix}_LDFLAGS)
+    if (_next_is_framework)
+      list(APPEND _libs "-framework ${flag}")
+      unset(_next_is_framework)
+      continue()
+    endif ()
     if (flag MATCHES "^-L(.*)")
       list(APPEND _search_paths ${CMAKE_MATCH_1})
       continue()
@@ -220,6 +226,9 @@ function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path)
     if (flag MATCHES "^-l(.*)")
       set(_pkg_search "${CMAKE_MATCH_1}")
     else()
+      if (flag STREQUAL "-framework")
+        set(_next_is_framework TRUE)
+      endif ()
       continue()
     endif()
 
@@ -379,6 +388,30 @@ macro(_pkg_restore_path_internal)
   unset(_pkgconfig_path_old)
 endmacro()
 
+# pkg-config returns frameworks in --libs-only-other
+# they need to be in ${_prefix}_LIBRARIES so "-framework a -framework b" does
+# not incorrectly be combined to "-framework a b"
+function(_pkgconfig_extract_frameworks _prefix)
+  set(ldflags "${${_prefix}_LDFLAGS_OTHER}")
+  list(FIND ldflags "-framework" FR_POS)
+  list(LENGTH ldflags LD_LENGTH)
+
+  # reduce length by 1 as we need "-framework" and the next entry
+  math(EXPR LD_LENGTH "${LD_LENGTH} - 1")
+  while (FR_POS GREATER -1 AND LD_LENGTH GREATER FR_POS)
+    list(REMOVE_AT ldflags ${FR_POS})
+    list(GET ldflags ${FR_POS} HEAD)
+    list(REMOVE_AT ldflags ${FR_POS})
+    math(EXPR LD_LENGTH "${LD_LENGTH} - 2")
+
+    list(APPEND LIBS "-framework ${HEAD}")
+
+    list(FIND ldflags "-framework" FR_POS)
+  endwhile ()
+  set(${_prefix}_LIBRARIES ${${_prefix}_LIBRARIES} ${LIBS} PARENT_SCOPE)
+  set(${_prefix}_LDFLAGS_OTHER "${ldflags}" PARENT_SCOPE)
+endfunction()
+
 ###
 macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _prefix)
   _pkgconfig_unset(${_prefix}_FOUND)
@@ -517,6 +550,10 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma
       _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS             ""        --libs )
       _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER       ""        --libs-only-other )
 
+      if (APPLE AND "-framework" IN_LIST ${_prefix}_LDFLAGS_OTHER)
+        _pkgconfig_extract_frameworks("${_prefix}")
+      endif()
+
       _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS        "(^| )-I" --cflags-only-I )
       _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS              ""        --cflags )
       _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER        ""        --cflags-only-other )

+ 13 - 0
Tests/RunCMake/FindPkgConfig/FindPkgConfig_extract_frameworks.cmake

@@ -0,0 +1,13 @@
+find_package(PkgConfig)
+
+set(foobar_LDFLAGS_OTHER "-Wl,xy;-framework;bar;-Wl,other-framework;-framework;baz;-Wl,abc;-framework;gosh;-frameworkcrap;-frame;j;-framework;nix;-Wl,def")
+set(foobar_LIBRARIES "-lz;-lm")
+
+_pkgconfig_extract_frameworks("foobar")
+
+if (NOT foobar_LDFLAGS_OTHER STREQUAL "-Wl,xy;-Wl,other-framework;-Wl,abc;-frameworkcrap;-frame;j;-Wl,def")
+  message(SEND_ERROR "foobar_LDFLAGS_OTHER did not match: ${foobar_LDFLAGS_OTHER}")
+endif ()
+if (NOT foobar_LIBRARIES STREQUAL "-lz;-lm;-framework bar;-framework baz;-framework gosh;-framework nix")
+  message(SEND_ERROR "foobar_LIBRARIES did not match: ${foobar_LIBRARIES}")
+endif ()

+ 29 - 0
Tests/RunCMake/FindPkgConfig/FindPkgConfig_extract_frameworks_target.cmake

@@ -0,0 +1,29 @@
+# Prepare environment to reuse bletch.pc
+file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pc-bletch/lib/pkgconfig" PC_PATH)
+if(UNIX)
+  string(REPLACE "\\ " " " PC_PATH "${PC_PATH}")
+endif()
+set(ENV{PKG_CONFIG_PATH} "${PC_PATH}")
+
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(Bletch IMPORTED_TARGET REQUIRED bletch-framework)
+
+if (Bletch_LDFLAGS_OTHER)
+  message(SEND_ERROR "Bletch_LDFLAGS_OTHER should be empty, but is '${Bletch_LDFLAGS_OTHER}'")
+endif ()
+
+if (NOT Bletch_LINK_LIBRARIES STREQUAL "-framework foo;-framework bar;bletch;-framework baz")
+  message(SEND_ERROR "Bletch_LINK_LIBRARIES has wrong value '${Bletch_LINK_LIBRARIES}'")
+endif ()
+
+foreach (prop IN ITEMS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_OPTIONS INTERFACE_COMPILE_OPTIONS)
+  get_target_property(prop_value PkgConfig::Bletch ${prop})
+  if (prop_value)
+    message(SEND_ERROR "target property ${prop} should not be set, but is '${prop_value}'")
+  endif ()
+endforeach ()
+
+get_target_property(prop_value PkgConfig::Bletch INTERFACE_LINK_LIBRARIES)
+if (NOT prop_value STREQUAL Bletch_LINK_LIBRARIES)
+  message(SEND_ERROR "target property INTERFACE_LINK_LIBRARIES has wrong value '${prop_value}'")
+endif ()

+ 2 - 0
Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake

@@ -6,8 +6,10 @@ run_cmake(FindPkgConfig_NO_PKGCONFIG_PATH)
 run_cmake(FindPkgConfig_PKGCONFIG_PATH)
 run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH)
 run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH)
+run_cmake(FindPkgConfig_extract_frameworks)
 
 if(APPLE)
+  run_cmake(FindPkgConfig_extract_frameworks_target)
   run_cmake(FindPkgConfig_CMAKE_FRAMEWORK_PATH)
   run_cmake(FindPkgConfig_CMAKE_APPBUNDLE_PATH)
 endif()

+ 9 - 0
Tests/RunCMake/FindPkgConfig/pc-bletch/lib/pkgconfig/bletch-framework.pc

@@ -0,0 +1,9 @@
+prefix=/opt/bletch
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: Bletch
+Description: Dummy packaget to test variable support
+Version: 1.3
+Libs: -L${libdir} -framework foo -framework bar -lbletch -framework baz