OUTPUT_NAME containing a slash is not diagnosed
Example
Consider the following project:
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.19)
project(subdir-test)
add_subdirectory(subdir)
subdir/CMakeLists.txt
:
add_executable(hello main.c)
set_target_properties(hello PROPERTIES
OUTPUT_NAME ../hello
INSTALL_RPATH just/some/example
)
install(TARGETS hello)
Here is the full example: https://git.sr.ht/~thestr4ng3r/cmake-bug-rpath
Note that the OUTPUT_NAME
of the target is set to be in the parent directory. One might want to do this for example to bring the main executable of a project into the root build dir for convenience. It may be considered bad practice but is allowed by cmake.
When installing this, the INSTALL_RPATH
set on the target is ignored and the rpath of the installed executable is unchanged:
$ otool -l install/bin/hello | grep RPATH -A2
$
This behavior is caused by the aforementioned OUTPUT_NAME
. If hello
is used there instead of ../hello
, it works as expected:
$ otool -l install/bin/hello | grep RPATH -A2
cmd LC_RPATH
cmdsize 32
path just/some/example (offset 12)
Cause
The cause of this becomes apparent when looking at the generated subdir/cmake_install.cmake
:
...
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/Users/florian/devp/cmake-bug-rpath/build/subdir/../hello")
if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/../hello" AND
NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/../hello")
execute_process(COMMAND /usr/bin/install_name_tool
-add_rpath "just/some/example"
"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/../hello")
if(CMAKE_INSTALL_DO_STRIP)
execute_process(COMMAND "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip" -u -r "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/../hello")
endif()
endif()
...
First, the file(INSTALL ...
copies the file from build/subdir/../hello
to ${CMAKE_INSTALL_PREFIX}/bin
, which results in the file <prefix>/bin/hello
. But then the install_name_tool
and strip
commands are actually run on <prefix>/bin/../hello
. This is especially sneaky because the install still succeeds and not even an error is printed.