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
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?
Using imported targets with
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.
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
Otherwise we could add another option to those functions, instead of
LINK_LIBRARIES something like
USE_TARGETS. For consistency, though, I’d just do it the same way as with
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?
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.
Why not something like
extern size_t sizeofClass; and then
size_t sizeofClass = sizeof(Class); in the implementation of
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_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.
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…
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.
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.
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?
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.
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.