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
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 )
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.
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.
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With