如何使用CMake链接到非标准位置的库?

时间:2016-06-14 18:02:22

标签: c++ cmake static-linking

我有一些非标准位置的库。这是来自OpenFrameworks,而libs在里面:

/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}
    ...
)

所以最终所有的lib都被连接起来并传递给链接器:

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)

UPDATE(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})

显然,我无法直接在这里传递文件夹?我需要lib名称。在这个阶段我是否需要另一个包含lib名称的列表?

UPDATE(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接受并链接任意lib名称?

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

1 个答案:

答案 0 :(得分:2)

  

所以最终所有的lib都被连接起来并传递给链接器:

link_directories (${OF_CORE_LIBS})

不,他们不是。来自the manual

  

link_directories

     

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

     

link_directories(directory1 directory2 ...)

     

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

所以你已经指定了链接器应该搜索的目录 您要链接的库。现在,您要指定链接器应链接库,例如libfoo.ayour_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)

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