I am new to Cmake and learning. I am using Ubuntu 20
I am not allowed to make changes CMakeLists.txt file. I am trying to use -DIMPORTED_LOCATION=/home/map/third_party for linking external library(libdlt.so) which is present in a user-defined location instead of the default location. But with this command, I am getting the following error
/usr/bin/ld: cannot find -ldlt
collect2: error: ld returned 1 exit status
Could you please help to clarify why it is not picking this parameter? If this library(libdlt.so) is at default location(/etc/local/lib) then CMake is working correctly.
Thanks <
You can't do this only with command line parameters.
The IMPORTED_LOCATION
is a target property. This means it only has meaning to CMake when applying it to a CMake target.
Dependencies in CMake usually are managed with imported targets, which has the IMPORTED_LOCATION
property.
It would be done like this:
find_path(DLT_INCLUDE_DIRECTORY dlt/dlt.h)
find_library(DLT_LIBRARY NAMES dlt)
add_library(dlt::dlt IMPORTED)
set_target_properties(dlt::dlt PROPERTIES
IMPORTED_LOCATION ${DLT_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${DLT_INCLUDE_DIRECTORY}
)
# then, later in your CMake scripts...
target_link_libraries(yourExecutable PUBLIC dlt::dlt)
You first find the paths. Include directory and library path.
Then, you create an imported target and set the path as its properties.
Then call CMake with the right prefix path so the find_*
command search in the right directory:
cmake .. -DCMAKE_PREFIX_PATH=/home/map/third_party
Now as you mentionned in the comments, you cannot change the CMakeLists file.
If you're using a library that has this broken CMake script, I would suggest forking it and fix their CMake file to not be hardcoded.
If you insist on not modifying the CMake file, there's a couple of things you can do.
You can create your own CMakeLists.txt
, and use it instead. Yes you can do that! It is hackish but allows you to have a modifiable CMakeLists.txt
that you can fix its behavior.
Create a sibling directory to the unmodifiable project, and add a CMakeLists.txt
in it and a build/
directory.
In those CMake, use relative paths like this:
add_library(yourlib STATIC)
target_sources(yourlib ../yourproject/file1.cpp ../yourproject/file2.cpp)
Then, use proper find_XXX
function so CMake can have a chance to find the right library instead of an hardcoded path.
There's another hack, but it's a bit more hackish.
You can replace the link program that CMake uses with a custom one with a command line argument:
cmake .. -DCMAKE_LINKER=/path/to/linker -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"
You can replace /path/to/linker
with a script that will replace the hardcoded flags with the good ones instead.
This is very hackish. Expect things to break or not behave correctly.
If you cannot create a separated CMakeLists script and replacing the link program is not an option either, there's another hack you can do. This is incredibly hackish, hard to create, hard to maintain, beginner unfriendly solution, and also very brittle and can break easily.
I must warn you, this is much worse than applying a patch to a third party library, and this is much much worse than creating your own CMake script. I woudln't recommend it to anyone. Also it deals with the worst part of CMake.
You can inject a CMake file in a script using the cmd with CMAKE_PROJECT_INCLUDE
:
cmake .. -DCMAKE_PROJECT_INCLUDE=myfile.cmake
In myfile.cmake
, you can write cmake code.
At that point, you can patch CMake builtin command with a macro to catch the unwanted behaviour and replace it with the wanted one.
macro(link_libraries)
# find and replace in ARGV
endmacro()
If you cannot write a CMake file replacing CMake commands, I will assume your filesystem is immutable and your bug cannot be fixed ;)