# Precompile library, .a with header, included with the source? Embedded target.

**URL:** <https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150>\
**Category:** Code\
**Created:** [October 7, 2023, 4:27am UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150 "2023-10-07T04:27:21Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![apullin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/apullin/32/1576_2.png) [@apullin](https://discourse.cmake.org/u/apullin)\
**Post date:** [October 7, 2023, 4:27am UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150/1 "2023-10-07T04:27:21Z")

</div>

OK, I wanted to get some feedback on something.

I am using CMake to build for embedded targets, and ran into something that was surprisingly challenging to do.  
It is not uncommon to be given pre-compiled libraries as `.a` files, along with an interface in `.h` files.

The first results that turn up on google, I just could NOT get them to work.

For example, lets say if I have a “libvendor”, distributed as a `libvendor_arm.a` and `vendor.h`.

Like this, as it’s own `CMakeLists.txt` files in `libs/libvendor/`,  
with `add_subdirectory( libs/libvendor )` added to my base cmake script.

```auto
add_library(vendor STATIC IMPORTED)
set_target_properties(cbt PROPERTIES
        IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libvendor_arm.a
        INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}
)

```

Using that, and linking `vendor` to my main exe target, include paths do not seem to get added, and builds fail with:  
`cannot find -lvendor: No such file or directory`

Eventually, I settled on this:

```auto
add_library( vendor INTERFACE )
target_sources( vendor INTERFACE vendor.h )
target_include_directories( vendor INTERFACE
        ${CMAKE_CURRENT_SOURCE_DIR} )

add_library(vendor_arm STATIC IMPORTED)
set_target_properties(vendor_arm
        PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libvendor_arm.a )
target_link_libraries(vendor INTERFACE vendor_arm )

```

Have I … overlooked something? Is this idiomatically correct, such that I can then do:  
`target_link_libraries( app.elf PUBLIC vendor )`, and get the header interface AND linking to the `.a` ?

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [October 7, 2023, 12:16pm UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150/2 "2023-10-07T12:16:27Z")

</div>

`IMPORTED` libraries are scoped. By making it in a subdirectory, it is not “visible” to the parent directory. You can either:

- use a `FindVendor.cmake` file and `find_package(Vendor)` and do this logic (my recommendation);
- use `add_library(vendor STATIC IMPORTED GLOBAL)` to make the target globally visible.

---

<div class="post-metadata">

**Author:** ![apullin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/apullin/32/1576_2.png) [@apullin](https://discourse.cmake.org/u/apullin)\
**Post date:** [October 7, 2023, 4:58pm UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150/3 "2023-10-07T16:58:24Z")

</div>

Oh. Ok. Would I use `find_package` even if it is something inside the repo, and not a package installed somewhere else in the system, or provided by the OS?

I am trying some versions of this, but just cannot get it to work …

```auto
# Try to find the library
find_path(VENDOR_INCLUDE_DIR NAMES vendor.h PATHS ${PROJECT_SOURCE_DIR}/libs/libvendor )
find_library(VENDOR_LIBRARY NAMES libvendor_arm.a PATHS ${PROJECT_SOURCE_DIR}/libs/libvendor )

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(VENDOR DEFAULT_MSG VENDOR_LIBRARY VENDOR_INCLUDE_DIR)

if(VENDOR_FOUND)
    set(VENDOR_LIBRARIES ${VENDOR_LIBRARY})
    set(VENDOR_INCLUDE_DIRS ${VENDOR_INCLUDE_DIR})
endif()

```

However, it just refuses to pick up anything for `VENDOR_INCLUDE_DIR`, even when using an absolute path to search …

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [October 7, 2023, 5:33pm UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150/4 "2023-10-07T17:33:43Z")

</div>

Oh, if you vendor it, just make it `GLOBAL` (there’s nothing to `find_*` as you “know” the paths). It’s basically “your” target anyways at that point.

---

<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:** [October 7, 2023, 8:23pm UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150/5 "2023-10-07T20:23:02Z")

</div>

> [@apullin](#):
>
> ```auto
> add_library(vendor STATIC IMPORTED)
> set_target_properties(cbt PROPERTIES
> 
> ```

This contains a typo. You’ve used a different target when you define the library (`vendor`) and when you set properties (`cbt`). Does your real project have that typo too?

---

<div class="post-metadata">

**Author:** ![apullin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/apullin/32/1576_2.png) [@apullin](https://discourse.cmake.org/u/apullin)\
**Post date:** [October 7, 2023, 11:13pm UTC](https://discourse.cmake.org/t/precompile-library-a-with-header-included-with-the-source-embedded-target/9150/6 "2023-10-07T23:13:13Z")

</div>

whoops it does  
in my script, it’s all `libcbt`, but I was anonymizing that for the post, changing everything back to “vendor” this and that.

BUT I think that typo is not too relevant - the issue there will be that the library is not exported to the global scope, as Ben informed me of.
