Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake: Generate pkg-config files for all Windows builds #396

Open
wants to merge 3 commits into
base: libpng16
Choose a base branch
from

Conversation

fanc999
Copy link

@fanc999 fanc999 commented Sep 30, 2021

Hi,

This PR is opened to support generating pkg-config files also for native (non-Cygwin) Windows builds, in addition to MinGW/mingw-w64 builds, since the Meson build system (which uses pkg-config and CMake to find dependencies for most packages) is becoming more widespread for building items such as Cairo and the GNOME/GTK stack and the current CMake config files generated by the CMake builds are not usable by Meson as a consequence of #179, which should be fixed in a PR of its own.

With blessings, thank you!

@ctruta
Copy link
Member

ctruta commented Sep 10, 2022

Thank you, looks neat, but could you please fix the following build error? I tested it on macOS, and it fails with the Ninja generator and the Release target, as follows:

CMake Error at cmake_install.cmake:90 (file):
  file INSTALL cannot find
  "/Users/ctruta/src/libpng/build/libpng16-config": No such file
  or directory.

FAILED: CMakeFiles/install.util

@BotellaA
Copy link

Any update on this? It will be very helpful!

@fanc999
Copy link
Author

fanc999 commented Oct 20, 2022

Hi @ctruta,

Sorry for the delay, as I was away and this PR was out for some time... I rebased some items, so I think things should probably be remedied, hopefully, since I don't have a macOS devenv.

Copy link
Member

@ctruta ctruta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall comment: this pull request appears to be carefully developed, and I like it a lot. There are just a few comments to be addressed.

CMakeLists.txt Outdated
else()
STRING (TOLOWER "${CMAKE_BUILD_TYPE}" config_lower)
if (config_lower STREQUAL "debug")
set(LIBS "${ZLIB_LIBRARY_DEBUG} ${M_LIBRARY}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert at how CMake libraries are being exported and imported. My understanding from other people is that there shouldn't be a ZLIB_LIBRARY or a ZLIB_INCLUDE_DIR (or a ZLIB_LIBRARY_DEBUG, etc.), but rather a symbol named ZLIB_LIBRARIES and another symbol named ZLIB_INCLUDE_DIRS.

For that reason, I am asking: are you sure that we shouldn't just have the following:

  set(LIBS "${ZLIB_LIBRARIES} ${M_LIBRARY}"

I can imagine that there are pros and cons to each side, but I would like to know your opinion also.

Moreover, take a look at line 598, further up in this CMake file:

  target_link_libraries(png ${ZLIB_LIBRARIES} ${M_LIBRARY})

I'd like to be sure that there won't be breakages due to this inconsistency.

Copy link

@PatTheMav PatTheMav Feb 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct way would be to have a target like ZLib::ZLib with properties INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_OPTIONS (if any present), and at least IMPORTED_LOCATION set (there's also properties for correctly using SONAME, and VERSION as well as SOVERSION.

If build configuration variants are present, they are supposed to be set as IMPORTED_LOCATION_RELEASE, IMPORTED_LOCATION_DEBUG, etc. with the IMPORTED_CONFIGURATIONS property set to the actual variants available. This will ensure CMake picks the correct variant (and usually falls back on the Release variant for RelWithDebInfo and MinSizeRel if present).

(On Windows you should also use IMPORTED_LIBNAME and its configuration-specific variants for the .lib file and if a .DLL exists set that as IMPORTED_LOCATION.)

With that you just run target_link_libraries(png <PRIVATE|PUBLIC> ZLib::ZLib).

Rule of Thumb with CMake 3 is: Use targets, target names, and target properties - don't use variables.

EDIT: It should be noted that this is precisely what CMake's FindZLib.cmake does: If config-specific variants are found, their properties are set and IMPORTED_CONFIGURATIONS will be set accordingly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

Sadly, using ${ZLIB_LIBRARIES} in the pkg-config file generating won't work, because you will have all the variants inside there. Will look for a cleaner solution.

Copy link
Author

@fanc999 fanc999 Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

I updated the CMakeLists.txt to reflect on the suggestions that were raised purely on the part that this PR attempts to cover, so I did not replace the occurences of ZLIB_LIBRARIES with ZLIB::ZLIB in any way but instead grabbed the library names for our pkg-config files with get_target_property(ZLIB_LIB ZLIB::ZLIB IMPORTED_LOCATION[_xxx]).

Please note that there is, however, no IMPORTED_IMPLIB[_$<CONFIG>] property from CMake's FindZLIB.cmake, even with DLL builds of ZLib, somehow.

CMakeLists.txt Outdated

# Set up links.
if(PNG_SHARED)
set_target_properties(png PROPERTIES
VERSION ${PNGLIB_SHARED_VERSION}
SOVERSION ${PNGLIB_SHARED_SOVERSION}
CLEAN_DIRECT_OUTPUT 1)
if(WIN32 AND NOT CYGWIN AND NOT MINGW)
foreach (pc_file ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc)
FILE(READ ${pc_file} png_pc_orig)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please use lowercase CMake commands (file, string, etc.), for the sake of stylistic consistency?

The Meson build system makes use of pkg-config files or CMake to find most of
the dependencies via its "built-in" dependency search system.  As libpng is a
very widely used package, this makes the CMake build system generate pkg-config
files for libpng even for non-Cygwin/non-MinGW Windows builds, so that Meson
could locate libpng via pkg-config as well even on Visual Studio builds, for
instance.

We also do the following on native, non-MinGW Windows builds:

*  Replace -lpngXX with libpngXX.lib, for the libpng library that we link to
*  Use the correct ZLib library .lib name for `libs.private`.
*  Replace `Requires.private: zlib` with `Requires.private:`, since we already
   say in `libs.private` that we are linking to ZLib
Use all-lowercase for CMake commands
@fanc999 fanc999 force-pushed the cmake-win32-pkgconfig branch 2 times, most recently from 11fcfbd to edf3ac9 Compare February 8, 2023 08:04
Use the target properties of ZLIB::ZLIB to get the library names for the
pkg-config files that we generate, and unify things with other builds.
We need to use the IMPORT_LOCATION[_$<CONFIG>] for ZLib since it does not
define IMPORT_IMPLIB[_$<CONFIG>] even on Windows DLL builds, and assume
that the $<CONFIG> we use above is RELEASE for both MinSizeRel and
RelWithDebInfo builds.
@ctruta
Copy link
Member

ctruta commented Feb 8, 2023

Hi, here's a heads-up,

I am currently applying refactoring changes in order to clean up the CMakefile and to make Clang on Windows work correctly, without regressing other platforms. Your contributions from this pull request may or may not break because of these upcoming changes.

On the positive side of the news, this pull request is next on my to-do list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants