gz-cmake
gz-cmake copied to clipboard
Informing tests of their own directory location
Original report (archived issue) by Michael Grey (Bitbucket: mxgrey, GitHub: mxgrey).
We frequently need to provide tests with the full path of their own build directory. This may be necessary for a test so that it can run a helper program or find a plugin library at run time.
Historically, we have solved this by generating a test_config.h
file at configuration time, and providing it with a macro named something like IGN_CONFIG_PATH
. However, this cannot work for multi-configuration generator types, such as the Visual Studio generators. The reason is the header gets created at configuration time, but a multi-configuration generator cannot know what directory a binary will be built in until generation time (which comes after configuration time).
To make ign-common
plugins testable in Visual Studio, I came up with a gross solution where we create a custom command that injects text into a file. Custom commands in cmake are able to use generator expresisons, so the path can be identified and supplied at generation time. I was never satisfied with this solution, but I couldn't think of a better one at the time.
I recently came up with something that might be a little nicer: Instead of generating a header, we can use target_compile_definitions(~)
to provide the tests with this path information. target_compile_definitions(~)
is able to handle generator expressions, so we don't need to do weird things with configuring headers at generation time using add_custom_command(~)
.
To do this, we could simply add the following line into the loop inside of ign_build_tests(~)
:
target_compile_definitions(${BINARY_NAME} PRIVATE IGN_BINARY_PATH="$<TARGET_FILE_DIR:${BINARY_NAME}>")
At that point, each test can know what its own directory path is by invoking the macro IGN_BINARY_PATH
.
If certain specific tests need to know the paths of other targets, that can be handled on a case-by-case basis by doing:
target_compile_definitions(<specific_test_target_name> PRIVATE IGN_PATH_TO_OTHER_THING="$<TARGET_FILE_DIR:${OTHER_THING}>")
as long as we ensure that the name IGN_PATH_TO_OTHER_THING
does not collide with any other compile definitions.
I think this would be the most robust and elegant way to ensure that our tests work regardless of what type of generator is used to configure and build them.
The one downside (that I can think of) is that the definitions (nay, the very existence) of these macros would be hard for developers to be aware of unless they're using a pretty good IDE (e.g. Qt Creator).
If anyone else likes this idea, I can move forward on it. I'd be able to use ign-common
as a good example for usage.