[CMake] Relink on library rebuild dilema
Michael Hertling
mhertling at online.de
Sat Nov 27 01:13:08 EST 2010
On 11/26/2010 05:00 PM, Sebastian Schaetz wrote:
> Hi,
>
> I have a somewhat weird setup to build binaries for the Cell processor:
>
> |-- CMakeLists.txt
> |-- kernels
> | |-- CMakeLists.txt
> | `-- kernel.cpp
> `-- main.cpp
>
> From the main.cpp in the root directory the executable is built.
>
> In the kernels folder strange things (have to) happen: first the kernel.cpp is
> compiled with a custom compiler (I use a combination of SET, CMAKE_C_COMPILER
> and ADD_EXECUTABLE), then this binary is converted into a library using a custom
> POST_BUILD command that calls a special tool to do just that. If the binary is
> called kernel_executable_bin, the custom command generates a file
> libkernel_executable.a
>
> Now I have to link this library to my main executable (built from main.cpp).
> What I did so far is to put in the kernels/CMakeLists.txt file:
>
> add_dependencies(main_target kernel_executable_bin)
>
> and in the /CMakeLists.txt file:
>
> link_directories("${CMAKE_CURRENT_BINARY_DIR}/kernels/")
> target_link_libraries(main_target kernel_executable)
>
> This works as expected for one ugly flaw: if I only change kernels/kernel.cpp it
> won't relink the main_target. I have thus far been unsuccessful in getting this
> to work. I've tried various combinations of add_library(STATIC IMPORTED) and
> add_custom_target(DEPENDS) but it won't work.
>
> Any ideas would be greatly appreciated.
Despite TARGET_LINK_LIBRARIES(), there's no dependency of main_target
on libkernel_executable.a, so main_target isn't relinked if the kernel
stuff is rebuilt. Nevertheless, there're some approaches I could offer:
1) In the top-level CMakeLists.txt, you might say
SET_SOURCE_FILES_PROPERTIES(
main.cpp PROPERTIES OBJECT_DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/kernels/libkernel_executable.a
)
When libkernel_executable.a has changed, this results in recompiling
main.cpp - a penalty - and the desired relinking of main_target. If
main.cpp's recompilation is expensive you may possibly add an empty
cpp file to main_target's sources and impose the property on that.
2) In kernels/CMakeLists.txt, add the following lines
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/empty.c)
ADD_LIBRARY(empty STATIC empty.c)
ADD_CUSTOM_COMMAND(TARGET kernel_executable_bin POST_BUILD COMMAND
${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/empty.c
)
or enhance the custom command which creates libkernel_executable.a from
kernel_executable_bin by the "cmake -E touch" shown above. Finally, in
the top-level CMakeLists.txt, say:
TARGET_LINK_LIBRARIES(main_target kernel_executable empty)
When kernels/kernel.cpp has changed the kernel_executable_bin and
libkernel_executable.a are rebuilt as usual, but kernels/empty.c is
touched by the way. This results in rebuilding libempty.a which in turn
makes main_target be relinked since it depends on the empty library. If
there's trouble with an empty static library just write some dummy code
in kernels/empty.c that you don't refer to from anywhere in the project.
3) If you get along with Makefiles you may possibly use a script in
junction with the RULE_LAUNCH_LINK target property to generate the
libkernel_executable.a from kernel_executable_bin as an actual
target like
ADD_LIBRARY(kernel_executable STATIC "")
ADD_DEPENDENCIES(kernel_executable kernel_executable_bin)
so the TARGET_LINK_LIBRARIES(main_target kernel_executable) in the
top-level CMakeLists.txt should be sufficient to trigger the linker.
'hope that helps.
Regards,
Michael
More information about the CMake
mailing list