Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake custom command to copy and rename

Tags:

command

cmake

I have an existing cmake file that generates a .so library. I want to modify it so that it will then make a copy of the .so named something else. This is roughly what I have:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7)
PROJECT(test1)

SET(TEST_SOURCES f1.c)
ADD_LIBRARY(test SHARED ${TEST_SOURCES})
ADD_CUSTOM_COMMAND(
    OUTPUT custom1
    COMMAND cp libtest.so custom1
    DEPENDS libtest.so)

I realise there are better ways than hardcoding the library name, I'm just doing this while I try and figure out how to make it work at all. What's the thing I'm missing that will cause my copy/rename custom command to run? Note: this is not an install-time thing. Thanks

like image 699
gimmeamilk Avatar asked Sep 03 '13 10:09

gimmeamilk


People also ask

What is Cmake_command?

The full path to the cmake(1) executable. This is the full path to the CMake executable cmake(1) which is useful from custom commands that want to use the cmake -E option for portable system commands. ( e.g. /usr/local/bin/cmake )

What is glob CMake?

GLOB will generate a list of all files that match the globbing expressions and store it into the variable. Globbing expressions are similar to regular expressions, but much simpler. If RELATIVE flag is specified for an expression, the results will be returned as a relative path to the given path.

How do you define a variable in CMake?

Options and variables are defined on the CMake command line like this: $ cmake -DVARIABLE=value path/to/source You can set a variable after the initial `CMake` invocation to change its value. You can also undefine a variable: $ cmake -UVARIABLE path/to/source Variables are stored in the `CMake` cache.

How do you clean after CMake?

Simply delete the CMakeFiles/ directory inside your build directory. rm -rf CMakeFiles/ cmake --build . This causes CMake to rerun, and build system files are regenerated. Your build will also start from scratch.


1 Answers

I'd stick with your original idea of using add_custom_command. However, I'd recommend you use the add_custom_command(TARGET ...) form rather than add_custom_command(OUTPUT ...).

The OUTPUT version is designed to have the output file used as a source file in a different CMake target in the same CMakeLists.txt. The custom command is invoked when this target is built (right at the start), since the target needs the file to exist at that point.

In your case, no target depends on your file - it's a product of the build process.

If you use add_custom_command(TARGET ...), this guarantees the command is executed every time the target is rebuilt. Using add_custom_target requires you to remember to build this if the original target (test in this case) is updated. It also needlessly adds to your list of targets - maybe not an issue for a tiny project, but it can be for larger projects.

Here's how I'd set up the command:

SET(COPY_TO_PATH custom1)
ADD_CUSTOM_COMMAND(TARGET test POST_BUILD
                   COMMAND ${CMAKE_COMMAND} -E copy
                       $<TARGET_FILE:test>
                       ${COPY_TO_PATH}
                   COMMENT "Copying 'test' library to '${COPY_TO_PATH}'")

This adds the command as a post-build event of test's. As you rightly identified, hard-coding library names isn't great; hence CMake provides "generator expressions" to handle this. The generator expression $<TARGET_FILE:test> resolves to the full path of the library created by test, regardless of platform or compiler. Note that generator expressions can only be used in the COMMAND argument; you couldn't use them in the COMMENT part for example.

The actual command is invoking CMake itself (${CMAKE_COMMAND}) with its -E command line option. This provides a cross-platform way to achieve the copy, since cp isn't a Windows command. To see all -E options, run cmake -E help.

like image 101
Fraser Avatar answered Sep 17 '22 13:09

Fraser