Skip to content

Reuse gtest on system #1493

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

Merged
merged 5 commits into from
Mar 6, 2023
Merged

Reuse gtest on system #1493

merged 5 commits into from
Mar 6, 2023

Conversation

pemensik
Copy link
Contributor

Try to use gtest on the system if found.

@pemensik
Copy link
Contributor Author

This will use gtest detected by pkg-config and avoid downloading it during build. Is required on Fedora package, which does not have internet access during build and check phases.

@yhirose
Copy link
Owner

yhirose commented Feb 14, 2023

@sum01, @jimmy-park, could you review the change? It looks good to me, but I would like to check with CMake experts. :)

@jimmy-park
Copy link
Contributor

@pemensik FetchContent_Declare(FIND_PACKAGE_ARGS) will not work on older versions of CMake (it requires CMake 3.24+). Related suggestion #1468 (comment) was mentioned by @Tachi107 recently. I think find_package(GTest) before FetchContent is more appropriate in this case. I will soon open a pull request for an updated test/CMakeLists.txt which addresses this issue also.

@Tachi107
Copy link
Contributor

Tachi107 commented Feb 14, 2023

@pemensik alternatively you could use Meson, which already uses the system-installed GTest version, produces a more portable pkg-config file, etc ;)

Try to use gtest on the system if found. Avoid using recent CMake
features.
@pemensik
Copy link
Contributor Author

@jimmy-park feel free to push into my branch, I have allowed that. Pushed modification, is that what you meant?

@Tachi107 my project is using cmake, which requires cpp-httplib. If I build it with meson, I will not have cmake module to use. Just pkg-config module, which requires modification. It is unfortunate used build system causes built output to be different. Especially when both variants generate exclusive content and no build system generates both ways compatible with any of them.

@Tachi107
Copy link
Contributor

@Tachi107 my project is using cmake, which requires cpp-httplib. If I build it with meson, I will not have cmake module to use. Just pkg-config module, which requires modification. It is unfortunate used build system causes built output to be different. Especially when both variants generate exclusive content and no build system generates both ways compatible with any of them.

It's not that hard to generate a CMake Config file from Meson, but really the issue is that CMake's find_package() does not provide a way to automatically use .pc files, which are the closest thing we have to a standard for C and C++ dependency discovery. I'll eventually send a patch to add this extra functionality to the meson.build file, but in the mean time I'd suggest you to just use drop this Find Module in your CMake project; it tries to find cpp-httplib using a CMake Config file, and falls back to pkg-config otherwise.

@jimmy-park
Copy link
Contributor

@pemensik yes, that's what I thought. I will add a small change to move some variables.

@jimmy-park
Copy link
Contributor

@pemensik I couldn't push to this branch because of permission denial. Could you please check it again? or my git settings have some problem.

@pemensik
Copy link
Contributor Author

Allow edits and access to secrets by maintainers is checked. Not sure how it is supposed to work. Do you have write access into this repository?

@Tachi107
Copy link
Contributor

No, yhirose is the only one with write access. Maybe you can give @jimmy-park write access to your fork, though

@sum01
Copy link
Contributor

sum01 commented Feb 14, 2023

I've never used GTest with Cmake, but just at a glance, the docs seem to specify different variables based on the version.

For example:

v3.14 Latest release (v3.26)
GTEST_FOUND GTest_FOUND
GTest::Main GTest::Main is deprecated, now uses GTest::gtest_main

Even though this is kind of silly, won't this cause some issues if the builder has an older Cmake version?

@jimmy-park
Copy link
Contributor

jimmy-park commented Feb 15, 2023

@sum01 hmm.. apparently they deprecated those targets since version 3.20. I'm not sure this workaround works on older versions.

find_package(GTest)

if(GTest_FOUND OR GTEST_FOUND)
    if(TARGET GTest::Main AND NOT TARGET GTest::gtest_main)
        add_library(GTest::gtest_main INTERFACE IMPORTED)
        target_link_libraries(GTest::gtest_main INTERFACE GTest::Main)
    endif()
else()
    # FetchContent routine
endif()

@eli-schwartz
Copy link
Contributor

eli-schwartz commented Feb 15, 2023

If I build it with meson, I will not have cmake module to use. Just pkg-config module, which requires modification.

What is wrong with:

include(FindPkgConfig)
pkg_search_module(HTTPLIB IMPORTED_TARGET GLOBAL cpp-httplib)

Then simply link to PkgConfig::HTTPLIB.

I've never used GTest with Cmake, but just at a glance, the docs seem to specify different variables based on the version.

What is wrong with:

include(FindPkgConfig)
pkg_search_module(GTEST_MAIN IMPORTED_TARGET GLOBAL gtest_main)

Then simply link to PkgConfig::GTEST_MAIN.

@sum01
Copy link
Contributor

sum01 commented Feb 15, 2023

While PkgConf is nice, I guess since it's not commonly installed on things like Windows (and maybe macOS?) it Just requires more workarounds. That's why the built-in modules that come with Cmake are useful.

Just more things to keep in mind stemming from trying to do multi-platform Cmake I suppose.

@eli-schwartz
Copy link
Contributor

Well, at the very least it should be a solution for fedora... For @pemensik's cmake project which depends on httplib, for example.

Although really, cmake isn't commonly installed either -- but people who need it, install it, and the same applies to pkg-config. It's trivially available in macOS via e.g. homebrew, and automatically wrapped on Windows by vcpkg.

@pemensik
Copy link
Contributor Author

I think the option would be to generate also pkg-config file from cmake build. For example by configure_file cmake statement and a template. That would make pkg-config generated always, maybe just with minor differences. I think generating cmake config from Meson would be more difficult. But at least one way present always would be useful.

But the main topic of this PR is different, maybe separate issue should be created for cmake module vs pkg-config file and discuss it there.

@sum01
Copy link
Contributor

sum01 commented Feb 15, 2023

Although really, cmake isn't commonly installed either -- but people who need it, install it, and the same applies to pkg-config. It's trivially available in macOS via e.g. homebrew, and automatically wrapped on Windows by vcpkg.

@eli-schwartz

Well the main difference is you need Cmake to build with Cmake, which means the built-ins are guarnteed to be available, whereas adding PkgConf to the mix means you need to also make sure the user has that too. Just an unnecessary complication if Cmake already has a module to use.


@pemensik I'd suggest implementing some form of this #1493 (comment) to avoid the issues I mentioned in #1493 (comment)

I'm also not sure trying to generate PkgConf files with Cmake is a good idea, if the internet is to be believed (see here) considering the loss of information vs Cmake. You'd probably have better luck writing your own PkgConf file than generating one.

@Tachi107
Copy link
Contributor

@sum01 GTest::Main is guaranteed to always be available when using find_package(GTest) for compatibility reasons (it's defined by CMake's FindGTest built-in module before calling the upstream GTestConfig)

@sum01
Copy link
Contributor

sum01 commented Feb 15, 2023

@sum01 GTest::Main is guaranteed to always be available when using find_package(GTest) for compatibility reasons (it's defined by CMake's FindGTest built-in module before calling the upstream GTestConfig)

My impression was that since it's listed as "deprecated since v3.20" it'll eventually disappear, and OP may as well take action now instead of waiting for vX.Y.Z when it's gone.

@eli-schwartz
Copy link
Contributor

I'm also not sure trying to generate PkgConf files with Cmake is a good idea, if the internet is to be believed (see here) considering the loss of information vs Cmake.

What loss of information? The information was never present in cmake to begin with -- cmake doesn't even try to detect e.g. openssl, zlib, brotli via pkg-config in order to write proper "requires" metadata so one pkg-config file can depend on another pkg-config file.

And cmake itself is doing considerably worse and dropping information all over the place. The cmake-generated export Targets file provides INTERFACE_LINK_LIBRARIES for ZLIB::ZLIB, OpenSSL::SSL, OpenSSL::Crypto, Brotli::encoder, Brotli::decoder, etc. -- but never defines them, which is why httplibConfig.cmake.in has to go to some very verbose double-handling of this.

With pkg-config it's very simple, try to find the pkg-config dependency "foo", if it is found then link to PkgConfig::FOO and add "foo" to a list pc_requires. Format the pkg-config file with Requires: @pc_requires@. It's the same information in both places.

If you found a dependency using find_package() instead of pkg_check_modules() then you need to write out its -lfoo flags instead.

You'd probably have better luck writing your own PkgConf file than generating one.

No, you absolutely want to sync it with cmake's found packages state, which means encoding the information about what to include in the pkg-config file as CMakeLists.txt logic.

@yhirose
Copy link
Owner

yhirose commented Feb 19, 2023

@pemensik, what is the status of this pull request? It seems like two comments from @jimmy-park are not resolved, yet.

@yhirose
Copy link
Owner

yhirose commented Mar 2, 2023

@pemensik, @jimmy-park, it's hanging here for a while. Can I merge this pull request, or should I close it? Please let me know.

@pemensik
Copy link
Contributor Author

pemensik commented Mar 2, 2023

Yes, I think those changes are ready to be merged. Remaining questions were just unimportant details, marked them as resolved.

@jimmy-park
Copy link
Contributor

@sum01 hmm.. apparently they deprecated those targets since version 3.20. I'm not sure this workaround works on older versions.

find_package(GTest)

if(GTest_FOUND OR GTEST_FOUND)
    if(TARGET GTest::Main AND NOT TARGET GTest::gtest_main)
        add_library(GTest::gtest_main INTERFACE IMPORTED)
        target_link_libraries(GTest::gtest_main INTERFACE GTest::Main)
    endif()
else()
    # FetchContent routine
endif()

@pemensik How about applying this workaround? I think #1493 (comment) should be handled in this pull request for the backward compatibility.

@yhirose
Copy link
Owner

yhirose commented Mar 2, 2023

@pemensik, please let me know when you apply the above @jimmy-park's comment.

@pemensik
Copy link
Contributor Author

pemensik commented Mar 3, 2023

Is that forward or backward compatibility? I have looked into our gtest package for RHEL8, version 1.8.0 does not yet have any cmake module. RHEL9 version 1.11.0 does have only gtest_main target. Latest release on https://github.com/google/googletest is 1.13.0. The same is in Fedora Rawhide and it produces still only GTest::gtest_main target. I haven't found GTest::Main in the whole google organization. Can you provide link to version without GTest::gtest_main target, @jimmy-park ?

Older versions provided only GTest::Main target, not currently used
gtest_main. Provide backward compatibility also to old cmake versions.
@pemensik
Copy link
Contributor Author

pemensik commented Mar 3, 2023

Oh, found that, it is part of cmake-data package for older versions. RHEL8 has version barely required for modern targets, RHEL7 does not even parse main CMakeLists.txt. So RHEL is not a good distribution to test the legacy target. Okay, it may not hurt providing additional target.

Copy link
Contributor

@Tachi107 Tachi107 left a comment

Choose a reason for hiding this comment

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

Two minor nitpicks

Comment on lines +6 to +7
add_library(GTest::gtest_main INTERFACE IMPORTED)
target_link_libraries(GTest::gtest_main INTERFACE GTest::Main)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't you create an ALIAS library instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

@yhirose
Copy link
Owner

yhirose commented Mar 6, 2023

It's pretty hard for me to keep track of this thread... So is it now ready for merge?

@jimmy-park
Copy link
Contributor

@yhirose Yes, I think it is okay to merge. I have no further discussion about this pull request.

@yhirose yhirose merged commit 7b69999 into yhirose:master Mar 6, 2023
@yhirose
Copy link
Owner

yhirose commented Mar 6, 2023

Thanks all!

@pemensik pemensik deleted the gtest-from-system branch April 14, 2023 11:00
ExclusiveOrange pushed a commit to ExclusiveOrange/cpp-httplib-exor that referenced this pull request May 2, 2023
* Reuse gtest on the system

Try to use gtest on the system if found. Avoid using recent CMake
features.

* Set CMP0135 only when using FetchContent

* Add /bigobj option for MSVC

* Support also cmake between 3.14 and 3.20

Older versions provided only GTest::Main target, not currently used
gtest_main. Provide backward compatibility also to old cmake versions.

* Remove redundant variable checking

---------

Co-authored-by: Jiwoo Park <[email protected]>
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.

6 participants