# try\_compile/try\_run link against target

**URL:** <https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189>\
**Category:** Code\
**Created:** [January 4, 2023, 9:39am UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189 "2023-01-04T09:39:29Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![martijntje](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/838e76/32.png) [@martijntje](https://discourse.cmake.org/u/martijntje)\
**Post date:** [January 4, 2023, 9:39am UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/1 "2023-01-04T09:39:29Z")

</div>

I’m executing a `try_run` command where I need to link against a target. My initial hope was that it would act like `target_link_libraries` and take things like the include directories and compiler flags and add them to the compilation.

Apparantly it does none of this, it only adds a _link flag_ and thus compilation fails. I think to make this work I’ll need to do the following:

- Retrieve all the include paths and compiler flags from the target.
- Recurse through all dependencies the target has and retrieve those flags as well.
- Feed these flags to `try_run` like `-DCMAKE_FLAGS=-DINCLUDE_DIRECTORIES...`

The first one is definitely doable I think, but I cannot find a way to get the dependencies a target has (e.g. introduced using a `target_link_libraries`). Is this possible? Am I missing another obvious way of doing this?

---

<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:** [January 4, 2023, 7:08pm UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/2 "2023-01-04T19:08:41Z")

</div>

Using imported targets with `try_compile` and `try_run` is difficult. Maybe we could dump all imported targets into the test project, but knowing which targets need to go is the difficult part.

Cc: @brad.king

---

<div class="post-metadata">

**Author:** ![martijntje](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/838e76/32.png) [@martijntje](https://discourse.cmake.org/u/martijntje)\
**Post date:** [January 5, 2023, 9:36am UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/3 "2023-01-05T09:36:43Z")

</div>

Well, elsewhere CMake automatically detects when it’s a target and will act accordingly.

So, if you do something like this:

`target_link_libraries(my_executable PUBLIC abc)`

Then, if CMake knows `abc` as a target it will correctly use things like include paths and other options on the target for `my_executable`, but if it’s not then it simply adds a linker option, like `-labc` for most linkers. It’s probably best to use that same behaviour for `try_compile` and `try_run`.

Otherwise we could add another option to those functions, instead of `LINK_LIBRARIES` something like `LINK_TARGETS` or `USE_TARGETS`. For consistency, though, I’d just do it the same way as with `target_link_libraries`.

---

<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:** [January 5, 2023, 1:07pm UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/4 "2023-01-05T13:07:35Z")

</div>

CMake would need to push the knowledge of the imported targets into the generated project for this to work. @Matthew_Woehlke, do you know how much work this might be?

---

<div class="post-metadata">

**Author:** ![martijntje](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/838e76/32.png) [@martijntje](https://discourse.cmake.org/u/martijntje)\
**Post date:** [January 5, 2023, 1:37pm UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/5 "2023-01-05T13:37:24Z")

</div>

It’s not just imported targets. I’m trying to use it with a mix of targets - some of which are regular libraries I define just above.

My goal is to write a set of generated files, the first of which includes a header that defines a given class and then writes the size of the class in bytes to `std::cout`. That information is then used to create a header that forward-declares the class and defines a buffer of the right size to hold. The class is then constructed using placement-new. That way you can reap the compiler speedup of forward declarations without incurring the overhead of pointer indirection.

---

<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:** [January 6, 2023, 6:08pm UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/6 "2023-01-06T18:08:19Z")

</div>

Why not something like `extern size_t sizeofClass;` and then `size_t sizeofClass = sizeof(Class);` in the implementation of `Class`?

---

<div class="post-metadata">

**Author:** ![Matthew\_Woehlke](https://discourse.cmake.org/user_avatar/discourse.cmake.org/matthew_woehlke/32/2345_2.png) [@Matthew\_Woehlke](https://discourse.cmake.org/u/Matthew_Woehlke)\
**Post date:** [January 6, 2023, 6:35pm UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/7 "2023-01-06T18:35:41Z")

</div>

> I’m trying to use [`try_run`] with […] regular libraries I define just above.

Well, that’s not going to work. `try_run` happens at configure time; your own libraries don’t exist then. Depending on how you’re using the result, you might be better off refactoring to use a custom command rather than `try_run`. (If I understand your use-case correctly, this sounds like the right approach, if Ben’s approach won’t work.)

I don’t know how much work it would be to export targets to `try_compile`/`try_run`. It would depend on whether we write _everything_ (which will slow down all calls even though almost none will _use_ all imported targets), or only targets that are needed.

---

<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:** [January 7, 2023, 3:07am UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/8 "2023-01-07T03:07:54Z")

</div>

> [@Matthew\_Woehlke](#):
>
> Depending on how you’re using the result, you might be better off refactoring to use a custom command rather than `try_run`.

I don’t think this will work; only the compiler can truly answer some `sizeof` questions and then the command won’t be part of target the class is a part of because it needs linked before you can use a compile command to answer such questions…

> [@Matthew\_Woehlke](#):
>
> or only targets that are needed.

This is an unsolvable problem with link usage requirements like `$<$<C_COMPILER:GNU>:iberty>` which (perhaps misguidedly) ask the C compiler’s name and add a link to `iberty` even if the target itself is C++ or whatever.

---

<div class="post-metadata">

**Author:** ![martijntje](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/838e76/32.png) [@martijntje](https://discourse.cmake.org/u/martijntje)\
**Post date:** [January 7, 2023, 7:21am UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/9 "2023-01-07T07:21:06Z")

</div>

That won’t work, unfortunately. The size needs to be a _compile-time constant_. So it works when defining something like `constexpr std::size_t sizeOfClass = ...;`, but that cannot be extern.

---

<div class="post-metadata">

**Author:** ![martijntje](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/838e76/32.png) [@martijntje](https://discourse.cmake.org/u/martijntje)\
**Post date:** [January 7, 2023, 7:25am UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/10 "2023-01-07T07:25:06Z")

</div>

Maybe I’m missing something here, but when it comes to compiling sources in a target we don’t need all linked libraries to be linked at that point, right? We just need to know which include paths and compiler flags they set.

Only for linking the final library do we need all dependencies to be fully linked. To know the `sizeof` for a class I don’t need the libraries to be linked, either. I just need to know the right compiler flags to use so that I get the correct answer from `sizeof`. That’s basically what CMake already does when you’re compiling sources, right?

---

<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:** [January 7, 2023, 2:49pm UTC](https://discourse.cmake.org/t/try-compile-try-run-link-against-target/7189/11 "2023-01-07T14:49:22Z")

</div>

> [@martijntje](#):
>
> We just need to know which include paths and compiler flags they set.

CMake does not yet have a way to say this. I’ve wanted a `$<COMPILE_ONLY>` genex, but it doesn’t exist yet. Even so, the safe route is to wait for it to have linked so that any generated sources or headers are guaranteed to exist.

> [@martijntje](#):
>
> I just need to know the right compiler flags to use so that I get the correct answer from `sizeof`. That’s basically what CMake already does when you’re compiling sources, right?

CMake knows how to give it to a compiler, but not an arbitrary tool (like codegen). See one way of doing something like it in [this code](https://gitlab.kitware.com/vtk/vtk/-/blob/f758b85a649d6c2d2095f786233d213f1999d3fe/CMake/vtkModuleWrapPython.cmake#L164-172).
