CMake can';找不到导入的库

CMake can';找不到导入的库,cmake,Cmake,在foo/CMakeLists.txt中,基于和,我有以下内容 SET (EXTERNAL_LIB_ROOT "../../external_libs/") ADD_LIBRARY (avcodec-debug STATIC IMPORTED) SET_PROPERTY ( TARGET avcodec-debug PROPERTY IMPORTED_LOCATION ${EXTERNAL_LIB_ROOT}/libavcodec-0.8.10.a) 在bar/CMakeL

foo/CMakeLists.txt
中,基于和,我有以下内容

SET (EXTERNAL_LIB_ROOT "../../external_libs/")

ADD_LIBRARY (avcodec-debug STATIC IMPORTED)

SET_PROPERTY (
    TARGET avcodec-debug PROPERTY IMPORTED_LOCATION
    ${EXTERNAL_LIB_ROOT}/libavcodec-0.8.10.a)
bar/CMakeLists.txt
中,我有:

# old way uses system libraries
#TARGET_LINK_LIBRARIES (bar avformat avcodec avutil)

# new way uses local debug builds
TARGET_LINK_LIBRARIES (bar avformat avcodec-debug avutil)
当我运行
make

/usr/bin/ld: cannot find -lavcodec-debug
如果我恢复到原来的方式,build,触摸foo/CMakeLists.txt并重建,CMake的配置输出表明构建系统正在发现avcodec调试


那么为什么不能将其添加为依赖项呢?

导入的目标与非导入的目标不遵循相同的可见性规则。虽然非导入的目标是全局的(定义后可从任何位置查看和访问),但导入的目标仅在定义它们的
CMakeLists.txt
及其下方(在此定义的CMakeList中由
add_子目录()
添加的目录中)可见

由于在您的案例中,
foo
bar
的兄弟,因此目标名称
avcodec debug
bar/CMakeLists.txt
中不可见,因此它被视为正常的库名称

通常,最好在包含的文件中定义导入的目标,而不是在它们自己的项目中。因此,将
foo/CMakeLists.txt的相关部分更改(或提取)为
foo/avcodec.cmake
,然后在顶级CMakeList中替换

add_subdirectory(foo)


正如上文Angew所提到的,导入库的可见性有所不同,不过您可以使用
GLOBAL
modifier对其进行扩展。您只需修改
add_library
下一步调用即可:

ADD_LIBRARY(avcodec-debug STATIC IMPORTED GLOBAL)

foo/CMakeLists.txt
bar/CMakeLists.txt
之间的关系是什么?
ADD_子目录(foo)
ADD_子目录(bar)
出现在顶级CMakeLists.txt中。你应该把它添加到问题中,这很重要。可见性规则是不同的,但不知道这一点,这一点都不重要,因为我已经“了解”了可见性规则。这就是为什么我说“你应该添加那个”而不是“你应该添加那个”。我的意思是这将使问题更加完整。谢谢,但我现在还没有。我创建了trunk/external/libav.cmake,它导入.././external\u libs/libav*.a(相对于trunk/external,external\u libs/是trunk/)和trunk/foo/bar/CMakeLists有
include(../../external/libav.cmake)
,但它抱怨:“没有规则使目标`/../external\u libs/libavcodec-0.8.10.a'”。。。有什么想法吗?此外,如果我将导入路径更改为
。/external\u libs/lbav*
,则CMake配置成功(这对我来说毫无意义),但g++找不到库。我建议使用显式路径前缀,如
${CMake\u CURRENT\u LIST\u DIR}
${CMake\u CURRENT\u SOURCE DIR}
而不是依赖相对路径,尤其是那些以
开头的路径。
为了详细说明@Angew的上述注释,如果包含的文件使用代码设置包含文件中使用的变量,如
set(MY_file../foobar.c”)
,则foobar.c的位置将相对于包含文件的位置进行解释。另一方面,
set(MY_文件“${CMAKE_CURRENT_LIST_DIR}/./foobar.c”)
将在设置MY_文件时扩展CMAKE_CURRENT_LIST_DIR的值,因此无论在哪里使用MY_文件的值,它都是正确的。
ADD_LIBRARY(avcodec-debug STATIC IMPORTED GLOBAL)