conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
7.95k stars 951 forks source link

[question] Building test package: how to find the includes of the library under test? #16504

Closed PauloCarvalhoRJ closed 1 week ago

PauloCarvalhoRJ commented 1 week ago

Hello,

So, I'm porting the recipes of a large project and a lot of the API was changed in Conan 2. I have this CMakeLists.txt (test package for zlib) (I commented out code that used to work in Conan 1):

cmake_minimum_required(VERSION 3.19)
project(test_package C)

# include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
# conan_basic_setup(TARGETS)

find_package(zlib CONFIG REQUIRED)

# FIXME: Where are the includes in zlib's package?
include_directories(${ZLIB_INCLUDE_DIR})
message( ----->  ZLIB_INCLUDE_DIR="${ZLIB_INCLUDE_DIR}")

add_executable(test_zlib test.c)
# target_link_libraries(test_zlib CONAN_PKG::zlib)
target_link_libraries(test_zlib zlib)
set_target_properties(test_zlib PROPERTIES OUTPUT_NAME "test")

if(WITH_MINIZIP)
  add_executable(test_minizip test_minizip.c)
#  target_link_libraries(test_minizip CONAN_PKG::zlib)
  target_link_libraries(test_minizip zlib)
endif()

The problem is that ZLIB_INCLUDE_DIR is blank, even though the find_package(...) seems to work. This results in compiler errors reporting header files not being found. ZLIB_INCLUDE_DIR was supposed to contain the directory where Conan put zlib's headers in zlib package. What am I missing?

thank you,

PC

Have you read the CONTRIBUTING guide?

memsharded commented 1 week ago

Hi @PauloCarvalhoRJ

ZLIB_INCLUDE_DIR is legacy CMake, not really specific a Conan thing. Conan new CMakeDeps generator is following "modern" CMake practices, which basically means that everything is a target and should be treated like it. Global include_directories(${ZLIB_INCLUDE_DIR}) is not a good practice anymore, in the same sense that global variables are discouraged while coding.

The generated ZLIB::ZLIB target that is created when find_package(ZLIB) contains all the necessary information, including the headers location. All is necessary is to do target_link_libraries(mytarget ZLIB::ZLIB) and that will automatically also define the necessary headers location.

PauloCarvalhoRJ commented 1 week ago

Hello, @memsharded ,

Yes... I wish I could spend months wading through hundreds of decade-old CMakeLists.txt's and make them compliant with the current good practices. So, please, expect a lot of legacy code that will be replaced on demand.

A question: how can one know the exact names of the target (e.g. ZLIB::ZLIB) to use?

thanks,

PC

memsharded commented 1 week ago

Yes... I wish I could spend months wading through hundreds of decade-old CMakeLists.txt's and make them compliant with the current good practices. So, please, expect a lot of legacy code that will be replaced on demand.

For legacy global variables, the generator CMakeDeps is still generating some of them:

{% for prefix in additional_variables_prefixes %}
set({{ prefix }}_VERSION_STRING "{{ version }}")
set({{ prefix }}_INCLUDE_DIRS {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )
set({{ prefix }}_INCLUDE_DIR {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )
set({{ prefix }}_LIBRARIES {{ pkg_var(pkg_name, 'LIBRARIES', config_suffix) }} )
set({{ prefix }}_DEFINITIONS {{ pkg_var(pkg_name, 'DEFINITIONS', config_suffix) }} )

{% endfor %}

By default, the additional_variables_prefixes will be just the package name, by default the package name or the cmake_file_name, which in case of zlib is ZLIB. So ZLIB_INCLUDE_DIRS will be defined. Maybe you can check your generated ZLIB-Config.cmake file and check what variables are defined there?

One of the problems is that the find_package() must be uppercase too like find_package(ZLIB). This is printed in the output of conan install too.

A question: how can one know the exact names of the target (e.g. ZLIB::ZLIB) to use?

It is printed in the output when using CMakeDeps, colored, when doing a conan install

PauloCarvalhoRJ commented 1 week ago

Maybe you can check your generated ZLIB-Config.cmake file and check what variables are defined there?

Here:

set(zlib_VERSION_STRING "1.2.11")
set(zlib_INCLUDE_DIRS ${zlib_INCLUDE_DIRS_RELEASE} )
set(zlib_INCLUDE_DIR ${zlib_INCLUDE_DIRS_RELEASE} )
set(zlib_LIBRARIES ${zlib_LIBRARIES_RELEASE} )
set(zlib_DEFINITIONS ${zlib_DEFINITIONS_RELEASE} )

One of the problems is that the find_package() must be uppercase too like find_package(ZLIB)

Indeed by the letter case of the definitions names in zlib-config.cmake (not ZLIB-Config.cmake here). I need to observe whether this will be a problem in Linux.

memsharded commented 5 days ago

Indeed by the letter case of the definitions names in zlib-config.cmake (not ZLIB-Config.cmake here). I need to observe whether this will be a problem in Linux.

Note the cmake_additional_variables_prefixes property of CMakeDeps allow to define different variables, with different casing, if necessary to adapt for the consumers: https://docs.conan.io/2/reference/tools/cmake/cmakedeps.html