conan icon indicating copy to clipboard operation
conan copied to clipboard

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

Open fdgStilla opened this issue 2 years ago • 9 comments

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: https://github.com/conan-io/conan-center-index/pull/12615

fdgStilla avatar Sep 02 '22 10:09 fdgStilla

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?

memsharded avatar Sep 02 '22 11:09 memsharded

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

fdgStilla avatar Sep 02 '22 12:09 fdgStilla

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?

memsharded avatar Sep 02 '22 20:09 memsharded

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.

fdgStilla avatar Sep 05 '22 06:09 fdgStilla

related issue: https://github.com/conan-io/conan/issues/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.

SpaceIm avatar Nov 01 '22 20:11 SpaceIm

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?

bukulin avatar May 18 '23 09:05 bukulin

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)

timwoj avatar Dec 13 '23 19:12 timwoj

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.

Ahajha avatar May 10 '24 07:05 Ahajha