CMAKE How to get Target File Location

2019-04-29 10:59发布

I'm trying to get the location of a static library of another project. I tried

get_property(target_name TARGET Test PROPERTY LOCATION) but CMAKE gives the following error

CMake Error at project.cmake:6 (get_property):
The LOCATION property may not be read from target "A".
Use the target name directly with add_custom_command, or use the generator
expression $<TARGET_FILE>, as appropriate.

I tried to use the generator expression mentioned in the error message with no success.

MESSAGE($<TARGET_FILE:A>)

just outputs the exact same string, so the generator expression doesn't seem to be evaluated at all:

$<TARGET_FILE:A>

I read the Documentation. In the first lines it mentions:

Generator expressions are evaluated during build system generation to produce information specific to each build configuration.

If I'm understanding this correctly then at the time the message function is evaluated the generator expressions are not evaluated anymore? So what am I supposed to be doing in this case?

I committed a minimal example of this problem on GitHub

EDIT:

I'm sorry to have asked the question in such a roundabout way without a clear explanation of my intentions:

My Aim is to get CMake to build a single (!) static library for my project, which someone else (who doesn't use CMake) can use. I would still use the "normal" resolution of dependencies for my project, but the other person - who doesn't use CMake - would have to manualy link multiple libraries to his project, which is somewhat inconvenient. A single library would solve this.

On my way of trying to get CMake to staticly link two static libraries, I read somewhere (sorry, I haven't saved a link) that at least when using Visual Studio as a compiler you can get the result I want if I append the full path of the static library to be linked to the static linker flags like that:

set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS >>>INSERT_PATH_HERE<<<)

which does in fact work. But now I'd have to manualy insert the fully qualified path to the variable there

set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS "/path/to/library.lib")

which doesn't seem to be a "good" way to do it to me. So I experimented with generator expressions and came up with the following one:

set_target_properties(B PROPERTIES STATIC_LIBRARY_FLAGS $<TARGET_FILE:A>)

which doesn't work, for reasons I don't fully understand. I guess set_target_properties just doesn't support generator expressions. While trying to get my project to work I tried

MESSAGE($<TARGET_FILE:A>)

(as stated above this explenation) and thought that if I'd get that statement to work I could solve my real problem. So thats what I asked the question posted above. I didn't realise that this would lead to confusion for the people trying to answer me.

标签: cmake
1条回答
Summer. ? 凉城
2楼-- · 2019-04-29 11:32

If you want to use a library in another one you should use target_link_libraries function:

target_link_libraries(B A) 

The signature of target_link_libraries automatically propagates A into all non-static libraries and executables which use B (both directly and indirectly).

Static libraries which use B are aware of their dependency on A but they aren't going to have a copy of the objects files from A within them. The dependency information is carried in INTERFACE_LINK_LIBRARIES and LINK_LIBRARIES target properties of the libraries.

By design, a static library is just an archive of object files. There's no need in mixing object files from different libraries together manually if you only want to use the libraries within your CMake project. CMake will instruct your linker with the list of libraries which needs to be linked into and proper order of the libraries (which indeed is produced out of the dependency graph). The linker, in turn, will resolve all symbols from the object files which are carried in the supplied static libraries.

If you still need to have precise control of the blending objects files, you might consider to use OBJECT library type:

# Create plain objects library which essentially is a set of object files
add_library(zipobj OBJECT zip.cpp)
# Archive all objects from zipobj. Recompilation of zip.cpp won't take place.
add_library(zip STATIC $<TARGET_OBJECTS:zipobj>)

add_library(lzmaobj OBJECT lzma.zpp)
add_library(lzma STATIC $<TARGET_OBJECTS:lzmaobj>)

# Create a library which contains object files from both zipobj and lzmaobj
add_library(archive STATIC $<TARGET_OBJECTS:zipobj> $<TARGET_OBJECTS:lzmaobj>)

EDIT: Also you might try merge_libraries function: http://www.mail-archive.com/cmake@cmake.org/msg28670.html

查看更多
登录 后发表回答