# Linking to library retrieved with fetchContent

**URL:** <https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157>\
**Category:** Code\
**Created:** [February 22, 2024, 12:40pm UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157 "2024-02-22T12:40:04Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Oodini](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/db5fbb/32.png) [@Oodini](https://discourse.cmake.org/u/Oodini)\
**Post date:** [February 22, 2024, 12:40pm UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157/1 "2024-02-22T12:40:04Z")

</div>

Hello,

I put a library on a server, and I retrieve it with `FetchContent` :

```auto
cmake_minimum_required(VERSION 3.17.3)

project("TestMyLib")

include(FetchContent)
FetchContent_Declare(MyLibrary URL "https://../../MyLibrary.zip")
FetchContent_MakeAvailable(MyLibrary)

FetchContent_GetProperties(MyLibrary)
if(NOT mylibrary_POPULATED)
	message(STATUS "Not populated !") # Not displayed
endif()

add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
    PRIVATE
        main.cpp
)

target_link_libraries(${PROJECT_NAME} PRIVATE MyLibrary)

```

The zipped archive is a CMake package in config mode, so it contains :

- a **cmake** directory with all the cmake config files  
(MyLibraryConfig.cmake,MyLibraryConfigVersion.cmake, MyLibraryTargets.cmake, MyLibraryTargets-debug.cmake, MyLibraryTargets-release.cmake)
- an **include** directory, with one directory inside (the library name), and inside all the expected .h
- a **lib** directory, with the two binaries (release and debug)

I do generate the project for Visual Studio. Everyting seems fine.  
The dowloaded archive is put in :  
`build\_deps\mylibrary-subbuild\mylibrary-populate-prefix\src`,  
and its content uncompressed in  
`build\_deps\mylibrary-src`.

But in the Visual Studio project of the client code, the includes and binaries directories of the library are not set. The library binary is set, but the configuration is not correctely set (the reference is to the release configuration instead of debug).

It is not clear for me to understand what I am supposed to do, and what I should expect from `FetchContent_MakeAvailable()` to make this CMakeLists.txt do what I want.

Note that before retrieving remote artefacts, I used `find_package` to get the same resource stored locally. And then, when calling `target_link_libraries()`, I had to refer to the library through a namespace : `MyLibrary::MyLibrary`. But when using `FetchContent`, I have to remove the namespace, else I get an error when running CMake (target bot found).

---

<div class="post-metadata">

**Author:** ![Oodini](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/db5fbb/32.png) [@Oodini](https://discourse.cmake.org/u/Oodini)\
**Post date:** [February 22, 2024, 3:43pm UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157/2 "2024-02-22T15:43:38Z")

</div>

I added the following lines :

```auto
FetchContent_GetProperties(MyLibrary SOURCE_DIR mylibrary_SOURCE_DIR)

target_include_directories(${PROJECT_NAME}
    PRIVATE
        ${mylibrary_SOURCE_DIR}/include)

target_link_directories(${PROJECT_NAME}
    PRIVATE
        ${mylibrary_SOURCE_DIR}/lib)

```

It does work, but I don’t know if it is the good practice, because these two points still need to be resolved (I probably don’t take advantages of some automatic features) :

- the Debug configuration doesn’t use the Debug configuration of the library (it was automatic when using `find_package()` on a local package)
- `target_link_libraries()` doesn’t have to mention anymore the namespace. I don’t understand why.

---

<div class="post-metadata">

**Author:** ![Oodini](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/db5fbb/32.png) [@Oodini](https://discourse.cmake.org/u/Oodini)\
**Post date:** [February 22, 2024, 4:46pm UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157/3 "2024-02-22T16:46:42Z")

</div>

> the Debug configuration doesn’t use the Debug configuration of the library (it was automatic when using `find_package()` on a local package)

@craig.scott Is this problem related to [this issue](https://gitlab.kitware.com/cmake/cmake/-/issues/23177) ? If so, do you see any workaround ?

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [March 23, 2024, 7:18am UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157/4 "2024-03-23T07:18:11Z")

</div>

You wouldn’t normally use FetchContent to bring in a pre-built binary library. It can be made to work, but it is unusual. Part of the difficulty is that the package will be platform-specific, so your logic would have to provide a platform-specific URL to the `FetchContent_Declare()` call. Again, that’s doable, but not normal.

FetchContent would normally bring in the sources and build the dependency as part of your main build. If you really do want to have it bring in a pre-built binary instead, then you need to account for the different way that affects the build. `FetchContent_MakeAvailable()` will look for a `CMakeLists.txt` in the top level of the downloaded .zip file, but in your case there won’t be one. Your project then becomes responsible for knowing what that unpacked .zip file contains and where to find things within it. Since you mentioned that the .zip file contains a `MyLibraryConfig.cmake` file, you should be able to call `find_package()` with the PATHS hard-coded, and that should be all you need to add your pre-built library to your main project. Something like the following should get you close:

```cmake
cmake_minimum_required(VERSION 3.17.3)
project(TestMyLib)

include(FetchContent)
FetchContent_Declare(MyLibrary URL "https://../../MyLibrary.zip")
FetchContent_MakeAvailable(MyLibrary)

find_package(MyLibrary
    REQUIRED
    NO_DEFAULT_PATH
    PATHS ${mylibrary_SOURCE_DIR}/path/to/dir/containing/*Config.cmake
)

add_executable(TestMyLib main.cpp)
target_link_libraries(TestMyLib PRIVATE MyLibrary::MyLibrary)

```

---

<div class="post-metadata">

**Author:** ![Oodini](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/o/db5fbb/32.png) [@Oodini](https://discourse.cmake.org/u/Oodini)\
**Post date:** [March 25, 2024, 2:54pm UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157/5 "2024-03-25T14:54:22Z")

</div>

> You wouldn’t normally use FetchContent to bring in a pre-built binary library. It can be made to work, but it is unusual. Part of the difficulty is that the package will be platform-specific, so your logic would have to provide a platform-specific URL to the `FetchContent_Declare()` call. Again, that’s doable, but not normal.

Well, do you mean before Conan, the right way was always to build all your dependencies, or install them by hand before calling `find_package()` ? And in the last case, you also have to adapt your logic according the platform.

> `PATHS ${mylibrary_SOURCE_DIR}/path/to/dir/containing/*.config `

I don’t have \*.config file, only \*.cmake files.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [March 26, 2024, 9:22pm UTC](https://discourse.cmake.org/t/linking-to-library-retrieved-with-fetchcontent/10157/6 "2024-03-26T21:22:06Z")

</div>

> [@Oodini](#):
>
> I don’t have \*.config file, only \*.cmake files.

Sorry, I made a typo in my example, which I’ve now edited to fix the error. It was meant to refer to a `*Config.cmake` or `*-config.cmake` file.
