[poppler] Requires.private field missing in poppler.pc

suzuki toshiya mpsuzuki at hiroshima-u.ac.jp
Thu Mar 29 08:17:47 UTC 2018


Hi,

I've posted my question to cmake mailing list, asking for
2 features to help the construction of pkg-config pc files.

https://cmake.org/pipermail/cmake/2018-March/067289.html

But it seems that nobody could remember appropriate and
existing solutions; on the other hand, the majority of the
responses to my question were suggesting to get rid of
pkg-config and native cmake package system.

So, here I post my current patch. The patch itself is
attached, but I want to explain in detail.

Regards,
mpsuzuki

> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index efa6c3f..361951e 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -10,6 +10,43 @@ include(MacroOptionalFindPackage)
>  find_package(PkgConfig)
>  include(MacroEnsureVersion)
>  include(MacroBoolTo01)
> +
> +#
> +# PKG_SEARCH_AVAILABLE_MODULE([var-name-of-found-module] [modules])
> +# 
> +# there is pkg_search_module(), but it does not clarify
> +# which module was found.
> +#
> +# this function does not set xxx_CFLAGS xxx_LIBS etc.
> +#
> +function(PKG_SEARCH_AVAILABLE_MODULE _found_pkg pkg_list)
> +  set(_PKG_FOUND FALSE)
> +  foreach(_pkg IN LISTS pkg_list)
> +    pkg_check_modules(_PKG "${_pkg}")
> +    if (_PKG_FOUND)
> +      set("${_found_pkg}_FOUND" TRUE PARENT_SCOPE)
> +      set("${_found_pkg}_MODULE_NAME" "${_pkg}" PARENT_SCOPE)
> +      return()
> +    endif()
> +  endforeach(_pkg)
> +endfunction(PKG_SEARCH_AVAILABLE_MODULE)

above is the function to find the first available module
from a list. pkg_check_modules() or pkg_search_module()
can do similar, but we have to write same list twice
(please find my example in
https://cmake.org/pipermail/cmake/2018-March/067292.html ).
to reduce the maintainability, I defined this function.

> +#
> +# MAKE_LDFLAGS_FROM_LIBPATH([var-ldflags+libs] [libpath])
> +#
> +function(MAKE_LDFLAGS_FROM_LIBPATHS _ldflags _libpaths)
> +  foreach(_libpath IN LISTS _libpaths)
> +    get_filename_component(_libdir "${_libpath}" DIRECTORY)
> +    get_filename_component(_lib "${_libpath}" NAME)
> +
> +    string(REGEX REPLACE "(\\${CMAKE_STATIC_LIBRARY_SUFFIX}|\\${CMAKE_SHARED_LIBRARY_SUFFIX})$" "" _lib "${_lib}")
> +    string(REGEX REPLACE "^lib" "" _lib "${_lib}")
> +
> +    set(__ldflags "${__ldflags} ${CMAKE_LIBRARY_PATH_FLAG}${_libdir} ${CMAKE_LINK_LIBRARY_FLAG}${_lib}")
> +  endforeach(_libpath)
> +  set("${_ldflags}" "${__ldflags}" PARENT_SCOPE)
> +endfunction(MAKE_LDFLAGS_FROM_LIBPATH)

above is the function to divide full pathname of the library
into its dirname and its basename, and constructs LDFLAGS
and LIBS style string.

> @@ -188,6 +225,7 @@ if(ENABLE_CPP)
>  endif()
>  if(ENABLE_ZLIB)
>    find_package(ZLIB)
> +  pkg_check_modules(PC_ZLIB zlib)
>    set(ENABLE_ZLIB ${ZLIB_FOUND})
>  endif()
>  if(ENABLE_ZLIB_UNCOMPRESS AND NOT ENABLE_ZLIB)

FindZLIB.cmake does not check the availability of
pkg-config module "zlib", so here I check. not to
bother current building setting, the prefix is set
to PC_ZLIB.

> @@ -197,6 +235,7 @@ endif()
>  set(WITH_OPENJPEG FALSE)
>  if(ENABLE_LIBOPENJPEG STREQUAL "openjpeg2")
>    find_package(LIBOPENJPEG2)
> +  pkg_check_modules(PC_LIBOPENJP2 libopenjp2)
>    set(WITH_OPENJPEG ${LIBOPENJPEG2_FOUND})
>    if(NOT LIBOPENJPEG2_FOUND)
>      message(FATAL_ERROR "Install libopenjpeg2 before trying to build poppler. You can also decide to use the internal unmaintained JPX decoder or none at all.")

If LIBOPENJPEG2_LIBRARIES and LIBOPENJPEG2_INCLUDE_DIR
are set manually, FindLIBOPENJP2.cmake sets
LIBOPENJPEG2_FOUND true without check the existence
of pkg-config module for libopenjpeg2 (so we cannot
know pkg-config moule exists or not from LIBOPENJP2_FOUND).
Thus, here I inserted a variable just checking module
availability, PC_LIBOPENJP2.

> @@ -221,6 +260,7 @@ endif()
>  if(ENABLE_LIBCURL)
>    find_package(CURL)
>    if(CURL_FOUND)
> +    pkg_check_modules(PC_LIBCURL libcurl)
>      include_directories(${CURL_INCLUDE_DIR})
>      set(POPPLER_HAS_CURL_SUPPORT ON)
>    else()


FindCURL.cmake does not use pkg-config, so we check
the module availability explicitly (as zlib case).

> @@ -262,13 +302,16 @@ if (NSS3_FOUND)
>  endif()
>  if(JPEG_FOUND)
>    include_directories(${JPEG_INCLUDE_DIR})
> +  PKG_SEARCH_AVAILABLE_MODULE(PC_LIBJPEG "libjpeg;libjpeg8-turbo;libjpeg8;libjpeg9;libjpeg62")
>  endif()

FindJPEG.cmake does not use pkg-config, so we check
the module availability explicitly (as zlib case).

>  if(PNG_FOUND)
>    include_directories(${PNG_INCLUDE_DIR})
> +  PKG_SEARCH_AVAILABLE_MODULE(PC_LIBPNG "libpng;libpng16;libpng12")
>    set(ENABLE_LIBPNG ON)
>  endif()

FindPNG.cmake does not use pkg-config, so...

>  if(TIFF_FOUND)
>    include_directories(${TIFF_INCLUDE_DIR})
> +  PKG_SEARCH_AVAILABLE_MODULE(PC_LIBTIFF "libtiff;libtiff-4")
>    set(ENABLE_LIBTIFF ON)
>  endif()

FindTIFF.cmake does not use pkg-config, so...

> @@ -676,12 +719,175 @@ if(PKG_CONFIG_EXECUTABLE)
>    exec_program(${PKG_CONFIG_EXECUTABLE} ARGS --version RETURN_VALUE _return_VALUE OUTPUT_VARIABLE _output_VAR)
>    macro_ensure_version("0.18" "${_output_VAR}" PKG_CONFIG_VERSION_0_18)
>  endif()
> -if(PKG_CONFIG_VERSION_0_18)
> -  set(PC_REQUIRES "")
> -  set(PC_REQUIRES_PRIVATE "Requires.private: poppler = ${POPPLER_VERSION}")
> -else()
> -  set(PC_REQUIRES "poppler = ${POPPLER_VERSION}")
> -  set(PC_REQUIRES_PRIVATE "")

The Requires & Libs are constructed from now, so
the pkg-config version checks would be postponed.

> +
> +# if archive library of poppler is being built, it cannot hold
> +# the dependency. collect dependencies managed by pkg-config,
> +# write to Requires. other dependencies (e.g. no appropriate
> +# pkg-config module is found), write to Libs.
> +
> +set(cmake_pc_requires "")
> +set(cmake_pc_libs "")
> +

The empty skeletons are prepared.

> +#
> +# dependencies checked by pkg-config only
> +#
> +# FindNSS3 just invokes pkg-config, returns cmake list of --libs
> +if (NSS3_FOUND)
> +  set(cmake_pc_requires "${cmake_pc_requires} nss")
> +endif()

NSS is just checked by pkg-config, so just pass the known
name to additional Requires.

> +# FindLIBOPENJPEG2 just invokes pkg-config, if LIBOPENJPEG2_xxx are not given.
> +if (LIBOPENJPEG2_FOUND)
> +  if (PC_LIBOPENJP2_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} libopenjp2")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_libopenjpeg2_ldflags "${LIBOPENJPEG2_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_libopenjpeg2_ldflags}")
> +  endif()
> +endif()

Even if OpenJPEG2 pkg-config module is not found, manual setting
of LIBOPENJPEG2_LIBRARIES can help. For such case (non-pkg-config
OpenJPEG2 is found), LDFLAGS + LIBS are constructed by
LIBOPENJPEG2_LIBRARIES.

> +#
> +# dependencies checked by pkg-config but sometimes different
> +#
> +
> +# FindFontconfig tries pkg-config too, but constructs library pathname
> +#  even if PC_FONTCONFIG_FOUND is false, FONTCONFIG_FOUND could be true.
> +#
> +if (FONTCONFIG_FOUND)
> +  if (PC_FONTCONFIG_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} fontconfig")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_fontconfig_ldflags "${FONTCONFIG_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_fontconfig_ldflags}")
> +  endif()
> +endif()

As OpenJPEG2, even if pkg-config cannot find fontconfig,
FONTCONFIG_LIBRARIES can help. Do same as OpenJPEG2 case.

> +# FindLCMS2 tries pkg-config too, but constructs library pathname
> +#  even if PC_LCMS2_FOUND is false, LCMS2_FOUND could be true.
> +#
> +if (LCMS2_FOUND)
> +  if (PC_LCMS2_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} lcms2")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_lcms2_ldflags "${LCMS2_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_lcms2_ldflags}")
> +  endif()
> +endif()

For lcms2, even if pkg-config cannot find it, and no
LCMS2_LIBRARIES is specified, FindLCMS2 search the library
by itself. So, if pkg-config cannot find it, some tweaks are
expected.

> +#
> +# dependencies checked without pkg-config
> +#
> +
> +# find_package(ZLIB) constructs library pathname
> +if (ENABLE_ZLIB)
> +  if (PC_ZLIB_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} zlib")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_zlib_ldflags "${ZLIB_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_zlib_ldflags}")
> +  endif()
> +endif()

FindZLIB.cmake does not use pkg-config at all. Do as
previous cases.

> +# FindCURL does not use pkg-config, constructs library pathname
> +if (CURL_FOUND)
> +  if (PC_LIBCURL_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} libcurl")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_curl_ldflags "${CURL_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_curl_ldflags}")
> +  endif()
> +endif()

FindCURL.cmake does not use pkg-config at all. Do as
previous cases.

> +# FindJPEG does not use pkg-config, constructs library pathname
> +if (WITH_JPEG)
> +  if (PC_LIBJPEG_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} ${PC_LIBJPEG_MODULE_NAME}")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_jpeg_ldflags "${JPEG_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_jpeg_ldflags}")
> +  endif()
> +endif()

FindJPEG.cmake does not use pkg-config at all. Do as
previous cases.

> +# FindTIFF does not use pkg-config, constructs library pathname
> +if (WITH_TIFF)
> +  if (PC_LIBTIFF_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} ${PC_LIBTIFF_MODULE_NAME}")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_tiff_ldflags "${TIFF_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_tiff_ldflags}")
> +  endif()
> +endif()

FindJPEG.cmake does not use pkg-config at all. Do as
previous cases.

> +# FindPNG does not use pkg-config, constructs library pathname
> +if (WITH_PNG)
> +  if (PC_LIBPNG_FOUND)
> +    set(cmake_pc_requires "${cmake_pc_requires} ${PC_LIBPNG_MODULE_NAME}")
> +  else()
> +    MAKE_LDFLAGS_FROM_LIBPATHS(_png_ldflags "${PNG_LIBRARIES}")
> +    set(cmake_pc_libs "${cmake_pc_libs} ${_png_ldflags}")
> +  endif()
> +endif()

FindJPEG.cmake does not use pkg-config at all. Do as
previous cases.

> +# extra dependencies without no pc files are provided
> +if (ICONV_FOUND)
> +  # remove uneeded -lc from ICONV_LIBRARIES (the pathname of libiconv, not -liconv)
> +  set(_iconv_libraries "${ICONV_LIBRARIES}")
> +  string(REGEX REPLACE "^.*/[Ll][Ii][Bb][Cc]\\${CMAKE_SHARED_LIBRARY_SUFFIX}\$" "" _iconv_libraries "${_iconv_libraries}")
> +  string(REGEX REPLACE "^.*/[Ll][Ii][Bb][Cc]\\${CMAKE_STATIC_LIBRARY_SUFFIX}\$" "" _iconv_libraries "${_iconv_libraries}")
> +  MAKE_LDFLAGS_FROM_LIBPATHS(_iconv_ldflags "${_iconv_libraries}")
> +  set(cmake_pc_cpp_libs "${cmake_pc_cpp_libs} ${_iconv_ldflags}")
> +endif()

In the case that libc itself has built-in iconv(),
like GNU libc, ${ICONV_LIBRARIES} could be "/usr/lib/libc.so".
It is not needed.

> +if (CMAKE_USE_PTHREADS_INIT)
> +  string(FIND "/libpthread${CMAKE_SHARED_LIBRARY_SUFFIX}" "${poppler_LIBS}" _pos)
> +  if (_pos LESS 0)
> +    string(FIND "/libpthread${CMAKE_STATIC_LIBRARY_SUFFIX}" "${poppler_LIBS}" _pos)
> +  endif()
> +
> +  if (_pos LESS 0)
> +    set(cmake_pc_libs "${cmake_pc_libs} -pthread")
> +  else()
> +    set(cmake_pc_libs "${cmake_pc_libs} -lpthread")
> +  endif()
> +endif()

If poppler_LIBS includes the full pathnames of libpthread,
convert it to LDFLAGS + LIBS styles.

> +string(REPLACE " -lc " "" cmake_pc_libs " ${cmake_pc_libs} ")
> +string(REPLACE " -lc " "" cmake_pc_cpp_libs " ${cmake_pc_cpp_libs} ")

Remove unexpected linker flags.

> +string(STRIP "${cmake_pc_libs}" cmake_pc_libs)
> +string(STRIP "${cmake_pc_cpp_libs}" cmake_pc_cpp_libs)

Remove beginning & following spaces.

> +string(REPLACE ";" " " cmake_pc_requires "${cmake_pc_requires}")
> +string(REPLACE ";" " " cmake_pc_libs     "${cmake_pc_libs}")
> +string(REPLACE ";" " " cmake_pc_cpp_libs "${cmake_pc_cpp_libs}")

If there is special linker flags, it could be separated
by ";" to pack as list in cmake.


> +# 
> +# to guarantee "pkg-config --libs poppler" always valid,
> +# we use Requires + Libs instead of Requires.private,
> +# if archive library is being built.
> +#
> +if(WIN32)
> +
> +elseif(BUILD_SHARED_LIBS AND PKG_CONFIG_VERSION_0_18)
> +  #
> +  # too old pkg-config-0.18 cannot hold private values
> +  #
> +  set(POPPLER_REQUIRES_PRIVATE      "Requires.private: ${cmake_pc_requires}")
> +  set(POPPLER_LIBS_PRIVATE          "Libs.private: ${cmake_pc_libs}")
> +  set(POPPLER_CPP_REQUIRES_PRIVATE  "Requires.private: poppler = ${POPPLER_VERSION} ${cmake_pc_cpp_requires}")
> +  set(POPPLER_CPP_LIBS_PRIVATE      "Libs.private: ${cmake_pc_cpp_libs}")
> +  set(POPPLER_GLIB_REQUIRES_PRIVATE "Requires.private: poppler = ${POPPLER_VERSION}")
> +  set(POPPLER_QT5_REQUIRES_PRIVATE  "Requires.private: poppler = ${POPPLER_VERSION}")
> +
> +elseif(NOT(BUILD_SHARED_LIBS))
> +  set(POPPLER_REQUIRES "Requires: ${cmake_pc_requires}")
> +  set(POPPLER_LIBS_EXTRA "${cmake_pc_libs}")
> +
> +  set(POPPLER_CPP_REQUIRES_EXTRA  "poppler = ${POPPLER_VERSION} ${cmake_pc_cpp_requires}")
> +  set(POPPLER_CPP_LIBS_EXTRA      "${cmake_pc_cpp_libs}")
> +  set(POPPLER_GLIB_REQUIRES_EXTRA "poppler = ${POPPLER_VERSION}")
> +  set(POPPLER_QT5_REQUIRES_EXTRA  "poppler = ${POPPLER_VERSION}")
> +
>  endif()

Finally expand to pkg-config files.

>  poppler_create_install_pkgconfig(poppler.pc ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
> diff --git a/poppler-cpp.pc.cmake b/poppler-cpp.pc.cmake
> index 3eb68b3..e91ffd8 100644
> --- a/poppler-cpp.pc.cmake
> +++ b/poppler-cpp.pc.cmake
> @@ -5,8 +5,9 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
>  Name: poppler-cpp
>  Description: cpp backend for Poppler PDF rendering library
>  Version: @POPPLER_VERSION@
> -Requires: @PC_REQUIRES@
> - at PC_REQUIRES_PRIVATE@
> +Requires: @POPPLER_CPP_REQUIRES_EXTRA@
> + at POPPLER_CPP_REQUIRES_PRIVATE@
>  
> -Libs: -L${libdir} -lpoppler-cpp
>  Cflags: -I${includedir}/poppler/cpp
> +Libs: -L${libdir} -lpoppler-cpp @POPPLER_CPP_LIBS_EXTRA@
> + at POPPLER_CPP_LIBS_PRIVATE@
> diff --git a/poppler-glib.pc.cmake b/poppler-glib.pc.cmake
> index ac24819..e3040fc 100644
> --- a/poppler-glib.pc.cmake
> +++ b/poppler-glib.pc.cmake
> @@ -5,8 +5,9 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
>  Name: poppler-glib
>  Description: GLib wrapper for poppler
>  Version: @POPPLER_VERSION@
> -Requires: glib-2.0 >= @GLIB_REQUIRED@ gobject-2.0 >= @GLIB_REQUIRED@ cairo >= @CAIRO_VERSION@
> - at PC_REQUIRES_PRIVATE@
> +Requires: glib-2.0 >= @GLIB_REQUIRED@ gobject-2.0 >= @GLIB_REQUIRED@ cairo >= @CAIRO_VERSION@ @POPPLER_GLIB_REQUIRES_EXTRA@
> + at POPPLER_GLIB_REQUIRES_PRIVATE@
>  
> -Libs: -L${libdir} -lpoppler-glib
>  Cflags: -I${includedir}/poppler/glib
> +Libs: -L${libdir} -lpoppler-glib @POPPLER_GLIB_LIBS_EXTRA@
> + at POPPLER_GLIB_LIBS_PRIVATE@
> diff --git a/poppler-qt5.pc.cmake b/poppler-qt5.pc.cmake
> index 9463689..1ac5809 100644
> --- a/poppler-qt5.pc.cmake
> +++ b/poppler-qt5.pc.cmake
> @@ -5,8 +5,9 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
>  Name: poppler-qt5
>  Description: Qt5 bindings for poppler
>  Version: @POPPLER_VERSION@
> -Requires: @PC_REQUIRES@
> - at PC_REQUIRES_PRIVATE@
> +Requires: @POPPLER_QT5_REQUIRES_EXTRA@
> + at POPPLER_QT5_REQUIRES_PRIVATE@
>  
> -Libs: -L${libdir} -lpoppler-qt5
>  Cflags: -I${includedir}/poppler/qt5
> +Libs: -L${libdir} -lpoppler-qt5 @POPPLER_QT5_LIBS_EXTRA@
> + at POPPLER_QT5_LIBS_PRIVATE@
> diff --git a/poppler.pc.cmake b/poppler.pc.cmake
> index 00b7348..ab3aeee 100644
> --- a/poppler.pc.cmake
> +++ b/poppler.pc.cmake
> @@ -5,6 +5,9 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
>  Name: poppler
>  Description: PDF rendering library
>  Version: @POPPLER_VERSION@
> + at POPPLER_REQUIRES@
> + at POPPLER_REQUIRES_PRIVATE@
>  
> -Libs: -L${libdir} -lpoppler
>  Cflags: -I${includedir}/poppler
> +Libs: -L${libdir} -lpoppler @POPPLER_LIBS_EXTRA@
> + at POPPLER_LIBS_PRIVATE@



-------------- next part --------------
A non-text attachment was scrubbed...
Name: fix-pc-for-static-build_20180329-1650.diff
Type: text/x-patch
Size: 15456 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/poppler/attachments/20180329/d664a6d0/attachment-0001.bin>


More information about the poppler mailing list