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

[bug] check_c_source_compiles for openssl is not working with CMakeToolChain and Visual Studio generator #12012

Closed
fdgStilla opened this issue Sep 2, 2022 · 10 comments · Fixed by #16964
Milestone

Comments

@fdgStilla
Copy link
Contributor

Environment Details (include every applicable attribute)

  • Operating System+version: Windows 11
  • Compiler+version: Visual Studio 2019
  • Conan version: 1.51.3
  • Python version: 3.10.3

Steps to reproduce (Include if Applicable)

  • in the conanfile:
    • use CMakeToolChain to build the package
    • require openssl self.requires("openssl/1.1.1q")
  • in the cmakefile of the project:
    • link with openssl like LINK_LIBRARIES(OpenSSL::SSL OpenSSL::Crypto)
    • use check_c_source_compiles like
CHECK_C_SOURCE_COMPILES("#include <openssl/opensslv.h>
			#ifndef OPENSSL_VERSION_NUMBER
			#error No OPENSSL_VERSION_NUMBER defined
			#endif
			#if OPENSSL_VERSION_NUMBER < 0x10100000L
			#error This is not OpenSSL 1.1 or higher
			#endif
			int main(void) { return 0; }" PODOFO_HAVE_OPENSSL_1_1)

=> you get the following error:

C:/J/w/prod/BuildSingleReference/.conan/data/podofo/0.9.7/_/_/build/f8220457d46bfa1f3246ae8e28788767027bcd82/build/CMakeFiles/CMakeTmp/CMakeLists.txt:20 (add_executable):
  Target "cmTC_491e9" links to target
  "CONAN_LIB::openssl_OpenSSL_SSL_libssl_RELEASE" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

Note: the error does not appear if you use another generator like Ninja.

This error was found when working on this pull request: conan-io/conan-center-index#12615

@memsharded
Copy link
Member

Quick question: if not using check_c_source_compiles(), but just building a normal library or executable that target_link_libraries() the openssl targets, does it work?

@fdgStilla
Copy link
Contributor Author

Quick question: if not using check_c_source_compiles(), but just building a normal library or executable that target_link_libraries() the openssl targets, does it work?

Yes

@memsharded
Copy link
Member

From what I see in https://cmake.org/cmake/help/latest/module/CheckCSourceCompiles.html, check_c_source_compiles() executes as try_compile(), which is not the same context as the main project, and it requires to pass CMAKE_REQUIRED_INCLUDES, CMAKE_REQUIRED_LIBRARIES etc, but not the targets, so it could be related. No idea why it would work with some generators like Ninja and not the others. Ninja with the VS compiler (cl.exe) works fine? I assume that the above failure is with standard CMake "Visual Studio" generator?

@fdgStilla
Copy link
Contributor Author

The failure is only with the standard CMake "Visual Studio" generator, running manually the cmake project configured by conan with -G "Ninja" fix the issue.

@SpaceIm
Copy link
Contributor

SpaceIm commented Nov 1, 2022

related issue: #12180
More or less all CMake macros in https://cmake.org/cmake/help/latest/manual/cmake-modules.7.html#utility-modules like check_c_source_compiles, check_cxx_source_compiles, check_symbols_exists, check_cxx_symbols_exists, check_function_exists, check_include_file etc are broken with <name>_LIBRARIES variables created by CMakeDeps.

@bukulin
Copy link

bukulin commented May 18, 2023

I've experienced the same in the following context:

  • I've tried to make the recipe of libssh2 conan-2 compatible, it depends on OpenSSL
  • There is a check_function_exists call in the CMake code of libssh2, where we command cmake to link to openssl::openssl.
  • openssl::openssl depends on OpenSSL::SSL , OpenSSL::SSL depends on "micro target" CONAN_LIB::openssl_OpenSSL_SSL_libssl_RELEASE in turn
  • The targets openssl::openssl, OpenSSL::SSL are INTERFACE IMPORTED
  • The target CONAN_LIB::openssl_OpenSSL_SSL_libssl_RELEASE is UNKNOWN IMPORTED
  • The check_function_exists calls try_compile, what supports INTERFACE IMPORTED targets to link against, but it does not suport UNKNOWN IMPORTED targets. (cmake command line option --debug-trycompile is useful here)

The CONAN_LIB:XXX micro targets are defined in the function conan_package_library_targets in the generated file cmakedeps_macros.cmake somewhat like this:

function(conan_package_library_targets libraries package_libdir deps_target out_libraries_target config_suffix package_name)
    set(_out_libraries_target "")

    foreach(_LIBRARY_NAME ${libraries})
        find_library(CONAN_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_libdir}
                     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
        if(CONAN_FOUND_LIBRARY)
            message(VERBOSE "Conan: Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}")

            # Create a micro-target for each lib/a found
            # Allow only some characters for the target name
            string(REGEX REPLACE "[^A-Za-z0-9.+_-]" "_" _LIBRARY_NAME ${_LIBRARY_NAME})
            set(_LIB_NAME CONAN_LIB::${package_name}_${_LIBRARY_NAME}${config_suffix})
            if(NOT TARGET ${_LIB_NAME})
                # Create a micro-target for each lib/a found
                add_library(${_LIB_NAME} UNKNOWN IMPORTED)
            endif()
           # .....
endfunction()

If I change the library type to INTERFACE IMPORTED like this:
add_library(${_LIB_NAME} INTERFACE IMPORTED)
then try_compile properly "memoizes" this micro target, as well as OpenSSL::SSL, OpenSSL::Crypto and openssl::openssl, and it succeeds, so check_function_exists succeeds as well.

try_compile creates a temporary CMake project (again, --debug-trycompile helps), what contains a cmTC-<XXX>Targets.cmake file. In this file cmake memoizes all INTERFACE IMPORTED dependencies from the calling context, transitively.

Is it possible to define these micro-targets as INTERFACE IMPORTED libraries or it wrecks something else?

@timwoj
Copy link

timwoj commented Dec 13, 2023

I see this being pushed along the 1.x track of releases, but I wanted to report that this is happening with 2.0.14 as well. It's basically blocking us from being able to use OpenSSL as a dependency via conan unfortunately, which also blocks a number of other libraries (such as libcurl):

CMake Error at C:/<>/build/CMakeFiles/CMakeScratch/TryCompile-ncuco8/cmTC_33fd1Targets.cmake:42 (set_target_properties):
  The link interface of target "OpenSSL::SSL" contains:

    CONAN_LIB::openssl_OpenSSL_SSL_libssld_DEBUG

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.

Call Stack (most recent call first):
  C:/<>/build/CMakeFiles/CMakeScratch/TryCompile-ncuco8/CMakeLists.txt:18 (include)

@Ahajha
Copy link

Ahajha commented May 10, 2024

Should also mention: I ran into this issue while working on a Git recipe, due to this I am unable to use the provided CMake file.

@HappySeaFox
Copy link

I tried the following workaround and it works fine, at least with my recipe:

    tc = CMakeToolchain(self)

    ...

    # TODO: Remove after fixing https://github.com/conan-io/conan/issues/12012
    if is_msvc(self):
        tc.cache_variables["CMAKE_TRY_COMPILE_CONFIGURATION"] = str(self.settings.build_type)

@memsharded
Copy link
Member

We are releasing in Conan 2.9 a completely new CMakeDeps generator in #16964 that has closed this ticket, with many pending features and fixes:

  • Allow defining cpp_info.default_components and using that information to generate CMake targets by default for packages
  • Allow defining cpp_info.exe to model executable imported targed generation
  • Creating always actual SHARED/STATIC/INTERFACE imported targets, with their IMPORTED_LOCATION, the IMPORTED_IMPLIB, the IMPORTED_CONFIGURATIONS
  • This solves issues with try_compile and other CMake source-compiling checks
  • No artificial library or package targets
  • Allow using the package languages attribute or a new cpp_info.languages information to define IMPORTED_LINK_INTERFACE_LANGUAGES
  • Define config files for executable targets for the "build" context automatically, without any special configuration
  • Use the correct CONFIGURATION from the package instead of the consumer one
  • Generate a new conan_cmakedeps_paths.cmake file, that can be used for integrations that cannot use a CMakeToolchain, like cmake-conan
  • Allow using executable targets from the host context if not cross-building (and not tool-requires that would prioritize those executable targets)

Current known pending functionality (to be added soon):

  • Not managing Apple frameworks
  • Not generating find modules, only CMake Config files

The new CMakeDeps generator is intended for testing and validation only, being a transparent replacement of the old one, so it is behind a new conf. To use it, use the -c tools.cmake.cmakedeps:new=will_break_next, and that will use the new generator instead of the old one. Note the will_break_next value means exactly that, that value will change in next release to force a break, so no one can depend on this generator in production yet.

Your feedback is very important

As this is a major change, we will only remove the conf gate when we get confirmation from users that it works and solve the issues. Please try the new generator for your project, and let us know if it works. If it doesn't, please re-open this ticket and let us know what failed. Thanks very much!

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

Successfully merging a pull request may close this issue.

9 participants