【问题标题】:How to link to a library in a non-standard location with CMake?如何使用 CMake 链接到非标准位置的库?
【发布时间】:2016-06-14 18:02:22
【问题描述】:

我有一些位于非标准位置的库。这是来自 OpenFrameworks 并且库在里面:

/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/osx/openFrameworks.a
...
/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/boost/lib/osx/boost_system.a
...
etc.

在我的 CMake 中链接这些时,我使用以下方法:

set(LIB_OF ${OF_DIRECTORY}/libs/openFrameworksCompiled/lib/osx/openFrameworks.a)
...
set(LIB_BOOST_MAIN ${OF_DIRECTORY}/libs/boost/lib/osx/boost.a)
...
set(LIB_CAIRO1 ${OF_DIRECTORY}/libs/cairo/lib/osx/cairo-script-interpreter.a)
...
set(LIB_FREETYPE ${OF_DIRECTORY}/libs/freetype/lib/osx/freetype.a)
...

然后我将这些变量合并为一个大变量:

set(OF_CORE_LIBS
    ${LIB_OF}
    ...
    ${LIB_BOOST_MAIN}
    ...
    ${LIB_CAIRO1}
    ...
    ${LIB_FREETYPE}
    ...
)

所以最终所有的库都被连接起来并传递到链接器中:

link_directories (${OF_CORE_LIBS})

然后我使用:

target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})

链接它们。

但是,我在链接阶段收到以下警告:

Linking CXX executable ../bin/3DPrimitiveExample
ld: warning: -L path '/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/osx/openFrameworks.a' is not a directory
...
(All the libs are listed in this way)

我如何告诉 CMake 查看这些目录,即使它们不是称为 blah/lib 而是 blah/lib/osx?我可以更改包的结构,但我不想修改它的设计方式。

我知道答案与 PROPERTIES 或默认的 CMAKE 变量有关,但帮助对我来说仍然有点神秘。我猜它是set_target_properties(),但不确定语法。 (我在 cmake 2.8.12)

更新(1): 所以我通过以下方式改变了我的方法:

set(LIB_OF ${OF_DIRECTORY}/libs/openFrameworksCompiled/lib/)
set(LIB_FREEIMAGE ${OF_DIRECTORY}/libs/FreeImage/lib/)
set(LIB_BOOST ${OF_DIRECTORY}/libs/boost/lib/)
set(LIB_CAIRO ${OF_DIRECTORY}/libs/cairo/lib/)
set(LIB_FMODEX ${OF_DIRECTORY}/libs/fmodex/lib/)
set(LIB_FREETYPE ${OF_DIRECTORY}/libs/freetype/lib/)
set(LIB_GLEW ${OF_DIRECTORY}/libs/glew/lib/)
set(LIB_OPENSSL ${OF_DIRECTORY}/libs/openssl/lib/)
set(LIB_POCO ${OF_DIRECTORY}/libs/poco/lib/)
set(LIB_RTAUDIO ${OF_DIRECTORY}/libs/rtAudio/lib/)
set(LIB_TESS ${OF_DIRECTORY}/libs/tess2/lib/)

一旦创建了这些位置变量,它们就会再次合并:

set(OF_CORE_LIBS
    ${LIB_OF}
    ${LIB_FREEIMAGE}
    ${LIB_BOOST}
    ${LIB_CAIRO}
    ${LIB_FMODEX}
    ${LIB_FREETYPE}
    ${LIB_GLEW}
    ${LIB_GLFW} 
    ${LIB_OPENSS}
    ${LIB_POCO}
    ${LIB_RTAUDIO}
    ${LIB_TESS}
)

所以当我详细说明它时,我会得到以下信息:

OF_CORE_LIBS: /Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/;/Users/me/packages/builds/x86_64/of- 0.9.3-osx-release/libs/FreeImage/lib/;/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/boost/lib/; (etc)

然后我将这些文件夹传递给链接器:

link_directories (${OF_CORE_LIBS})

现在错误的部分是这样的:

target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})

显然,我不能在这里直接传递文件夹?我需要库名称。在这个阶段我需要另一个包含库名称的列表吗?

更新(2):

对于 lib 搜索文件夹:

set(OF_CORE_LIB_DIRS
    ${LIB_OF}
    ${LIB_FREEIMAGE}
    ${LIB_BOOST}
    ${LIB_CAIRO}
    ${LIB_FMODEX}
    ${LIB_FREETYPE}
    ${LIB_GLEW}
    ${LIB_GLFW} 
    ${LIB_OPENSS}
    ${LIB_POCO}
    ${LIB_RTAUDIO}
    ${LIB_TESS}
)

对于实际的库:

set(OF_CORE_LIBS
    openFrameworks
    freeimage
    boost_system
    boost_filesyste
    freeimage
    cairo-script-interpreter
    cairo
    pixman-1
    fmodex
    freetype
    glew
    ssl
    crypto
    PocoCrypto
    PocoData
    PocoDataSQLite
    PocoJSON
    PocoMongoDB
    PocoXML
    PocoNet
    PocoNetSSL
    PocoUtil
    PocoZip
    PocoFoundation
    rtAudio
    tess2
)

在链接阶段:

link_directories (${OF_CORE_LIB_DIRS})
add_executable(${APP_NAME} ${SOURCE_FILES})
target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})

现在我收到以下错误:

Linking CXX executable ../bin/3DPrimitiveExample.app/Contents/MacOS/3DPrimitiveExample
ld: library not found for -lopenFrameworks

这是目录位:

set(LIB_OF ${OF_DIRECTORY}/libs/openFrameworksCompiled/lib/osx)

文件就在里面:

openFrameworks.a

其他问题:

下面的答案帮助我理解了 lib 文件夹和实际 lib 名称之间的区别。但是,仍然有一个问题得到解答:如何告诉 CMake 接受和链接任意库名称?

在上面的问题中,库只是用它们的名字来调用的,例如,openFrameworks.a 应该被称为libopenFrameworks.a 以便被链接器拾取,但事实并非如此。那,我将在另一个问题下问。

【问题讨论】:

  • 这个question 似乎覆盖了类似的地方?解决方案可能也适用于您的情况?
  • 谢谢。但这对我没有帮助。我正在做完全相同的事情,并且收到了上述警告。我想知道修复警告并将文件夹传递给链接器的方法,而不是实际的 lib 文件。
  • 不,这里的问题是您将完整路径传递给库。您需要将路径传递到库所在的文件夹。然后你可以简单地喜欢你的典型 -l
  • 是的。我怎么能用 CMake 做到这一点。当我做set(LIB_BOOST_MAIN ${OF_DIRECTORY}/libs/boost/lib/osx) 时,CMake 抱怨这不是官方库,因为*.a 文件不在/lib 文件夹中。
  • 所以你的实际问题是CMake抱怨/lib文件夹中没有.a文件。 edit您的问题帖子,因此它将清楚地描述问题。

标签: c++ cmake static-linking


【解决方案1】:

所以最终所有的库都被连接起来并传递到链接器中:

link_directories (${OF_CORE_LIBS})

不,他们不是。来自the manual

链接目录

指定链接器将在其中查找库的目录。

link_directories(directory1 directory2 ...)

指定链接器搜索库的路径。

所以你已经指定了链接器应该搜索的目录 您要链接的库。现在你想指定链接器应该链接一个库,比如libfoo.a your_executable

再次,the manual

target_link_libraries(your_executable foo)

您告诉链接器去哪里以及去寻找什么

稍后

我认为我所做的正是你在回答中描述的,对吧?

不,你不是。

您正在提供一个文件列表(显然它们是静态库,尽管它们缺少 传统的lib 前缀)到link_directories。它需要一个目录列表 链接器将在其中查找您使用 target_link_libraries 指定的库。

这就是为什么链接器说:

ld: warning: -L path '/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/\
libs/openFrameworksCompiled/lib/osx/openFrameworks.a' is not a directory

这是一个文件。然后更正一下:

target_link_libraries(your_executable foo)

将导致链接器在每个link_directories 中查找库libfoo.{so|a}

【讨论】:

  • 抱歉,我跳过了我正在执行的一些步骤并从问题中省略了它们,因此问题可能有点令人困惑。我刚刚更新了内容,这样问题就更清楚了,它涵盖了我正在使用的所有阶段。我想我所做的正是你在回答中描述的,对吧?
  • 当我这样做时,我的意思是当我传递文件夹时,我得到这个:WARNING: Target "3DPrimitiveExample" requests linking to directory "/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/". Targets may link only to libraries. CMake is dropping the item.
  • @symbolix 这是因为target_link_libraries(${APP_NAME} ${OF_CORE_LIBS}) 现在在需要库名称 列表时将目录 列表提供给target_link_libraries${OF_CORE_LIBS} 不能既是目录列表又是库名称列表!你不能在这两个地方都使用它。对于link_directories,您需要一个要搜索的目录列表。对于target_link_libraries,您需要一个应搜索的库名称列表。
  • 现在我开始明白了。非常感谢您的帮助和耐心。我对这件事一无所知。请参阅我的问题下方的 update(1)
  • @symbolix 您的 update(1) 问题的答案是肯定的。您需要按照约定 libfoo.a 命名静态库。为了给链接选项-lfoo定位它们,这是由target_link_libraries(app foo)生成的
猜你喜欢
  • 2020-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多