Git Product home page Git Product logo

Comments (9)

memsharded avatar memsharded commented on July 18, 2024 1

You are missing linking core -> common.
the following fixes it:

diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 65a29e5..a329800 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -18,6 +18,7 @@ string(REPLACE ";" "$<SEMICOLON>" dirs "${core_build_include_dirs}")
 add_library(core ${SOURCES})
 add_library(my_algorithm::core ALIAS core)

+target_link_libraries(core PUBLIC common)
 #target_include_directories(core PUBLIC include)

 message("CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")

from conan.

memsharded avatar memsharded commented on July 18, 2024

Hi @Isaacwhyuenac

Thanks for your question.

If common is a header-only library then the following line is incorrect:

self.cpp_info.components["common"].libs = ["common"]

That means that there is a compiled library called libcommon.a or common.lib depending on the system, but this is not the case.

  1. How can I build and export both libraries (header-only and non-header-only) in this modular setup? Since there are consumers that may want to require just the common header-only library but not together with the core library.

You were almost there, I think just fixing the above it should work, and consumers could link with just the header-only library if they want to.

If I have to include other packages like fmt in my common library (header-only library), how can I set up my cmake and conan configuration?

Typically with something like:

requires = "fmt/version"

def package_info(self):
    ...
    # check the target, I am just guessing fmt::fmt, I haven't checked
    self.cpp_info.components["common"].requires = ["fmt::fmt"] 

If (2) is possible, is it possible that the consumer (like the core library here) install the fmt library right away and the consumer libraries do not have to each specify the requirements in conan and findPackage in cmake for example?

Yes, Conan will handle transitivity from components too. That means that find_package(mypkg ...) and then target_link_libraries(.... test_foundation::core) will include transtively the common and if common does requires=[fmt::fmt], then fmt will also be transitively included.

from conan.

Isaacwhyuenac avatar Isaacwhyuenac commented on July 18, 2024

@memsharded Thank you for your reply.

If I have to include other packages like fmt in my common library (header-only library), how can I set up my cmake and conan configuration?

I have updated the conanfile.py

        self.cpp_info.components["common"].requires = ["fmt::fmt", "spdlog::spdlog"]

And on my common/CMakeLists.txt,

I have references

find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)

file(GLOB HEADERS include/*.h include/**/*.h)

add_library(common INTERFACE)
add_library(my_algorithm::common ALIAS common)

target_link_libraries(common INTERFACE fmt::fmt spdlog::spdlog)

target_include_directories(
        common INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

But I built my project with the following errors

.conan2/p/b/my_alaeb574bf0f0d3/b/common/include/common/algorithm.h:8:10: fatal error: 'spdlog/spdlog.h' file not found
#include <spdlog/spdlog.h>

The package is not properly linked to my header-only library (common folder). Do you know how I can link the package to my solution?

from conan.

memsharded avatar memsharded commented on July 18, 2024

If the headers of fmt and others are visible through the dependency, that means, the public headers of your package include the headers of those dependencies, then it is necessary first to specify that in the requires as:

def requirements(self):
     self.requires("fmt/version", transitive_headers=True)

The default is to assume that dependencies are "implementation detail" of the packages, and are not propagated through the package headers, this is why it is necessary to explicitly tell that they should be propagated to consumers. Check about it in https://docs.conan.io/2/reference/conanfile/methods/requirements.html#requirement-traits. Note that transitive_libs=True is not necessary in most cases, as Conan knows how to propagate that when necessary.

Please try that and let me know.

from conan.

Isaacwhyuenac avatar Isaacwhyuenac commented on July 18, 2024

Hi @memshared. Thanks for the reply. I added the transitive_header=True option to my fmt and spdlog packages that the header-only library (common) depends on it. But I cannot this header-only library.

When I run conan create . -v,

.conan2/p/b/my_al1414ac9f90079/b/common/include/common/algorithm.h:8:10: fatal error: 'spdlog/spdlog.h' file not found
#include <spdlog/spdlog.h>
         ^~~~~~~~~~~~~~~~~

Currently I have added the following configuration to build the header-only library.

find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)

FILE(GLOB HEADERS include/*.h include/**/*.h)

add_library(common INTERFACE)
add_library(my_algorithm::common ALIAS common)

message(STATUS "HEADERS: ${HEADERS}")

target_include_directories(
        common INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include> ##
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

target_link_libraries(common INTERFACE fmt::fmt spdlog::spdlog)

include(CMakePackageConfigHelpers)
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
        VERSION ${PROJECT_VERSION}
        COMPATIBILITY SameMajorVersion)

install(TARGETS common
        EXPORT ${PROJECT_NAME}_Targets
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

configure_package_config_file(
        "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in"
        "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
        INSTALL_DESTINATION
        ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) # CHANGE HERE

install(EXPORT ${PROJECT_NAME}_Targets
        FILE ${PROJECT_NAME}Targets.cmake
        NAMESPACE ${PROJECT_NAME}::
        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) # CHANGE HERE

install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
        "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)

install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

I linked my library with the packages target_link_libraries(common INTERFACE fmt::fmt spdlog::spdlog) and included instructions to make the proper Cnfig.cmake and ConfigVersion.cmake for the consumer to find the my library. But conan is telling it cannot find the fmt and spdlog headers.

What have I done wrong?

from conan.

memsharded avatar memsharded commented on July 18, 2024

Hi @memshared. Thanks for the reply. I added the transitive_header=True option to my fmt and spdlog packages that the header-only library (common) depends on it. But I cannot this header-only library.

Aren't you using the ConanCenter recipes? do you have your own recipes?

We might need a full (minimal) reproducible example, I think we start to have too many moving pieces. If the recipes are your own, maybe is it possible that some headers are not being correctly packaged? There would be some things to check. For example it is not clear at all at this point if you are using the Conan CMakeDeps generated cmake files for dependencies, or you are trying to use the xxx-config.cmake bundled inside the packages.

If we can reproduce with your repo and the recipes from ConanCenter, can you please make sure the repo contains the latest code and provide the exact commands to reproduce it?

from conan.

Isaacwhyuenac avatar Isaacwhyuenac commented on July 18, 2024

I am using the spdlog and fmt recipes from ConanCenter.

from conan.

Isaacwhyuenac avatar Isaacwhyuenac commented on July 18, 2024

You are missing linking core -> common. the following fixes it:

diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 65a29e5..a329800 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -18,6 +18,7 @@ string(REPLACE ";" "$<SEMICOLON>" dirs "${core_build_include_dirs}")
 add_library(core ${SOURCES})
 add_library(my_algorithm::core ALIAS core)

+target_link_libraries(core PUBLIC common)
 #target_include_directories(core PUBLIC include)

 message("CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")

I thought the lines

get_target_property(common_LIB_INCLUDE_DIRS common INTERFACE_INCLUDE_DIRECTORIES)

set(core_build_include_dirs
        "${HEADERS}"
        "${common_LIB_INCLUDE_DIRS}")

include_directories(${core_build_include_dirs})

was doing the job. 😭 It is working now, thank you so much @memsharded

from conan.

memsharded avatar memsharded commented on July 18, 2024

include_directories

No, please note that in the majority of cases, doing things like what you are doing there with get_target_property and include_directories() is not recommended. Targets already contain information about headers, that should be enough to use the headers from other targets. Make sure that every target has its property for its header set, and just let target_link_libraries() deal with it.

It is working now, thank you so much @memsharded

I am closing the ticket as solved then, happy to help! :)

from conan.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.