如何使用 CMake link 到非标准位置的库?
How to link to a library in a non-standard location with CMake?
我有一些库位于非标准位置。这是来自 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.
当 link 在我的 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}
...
)
所以最终所有的库都被连接起来并传递到 linker:
link_directories (${OF_CORE_LIBS})
然后我使用:
target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})
到link他们。
但是,我在 linking 阶段收到以下警告:
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)
然后我将这些文件夹传递给 linker:
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
)
并且在 linking 阶段:
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 名称之间的区别。然而,仍然有一个问题得到了回答:How to tell CMake to accept and link arbitrary lib names?
在上面的问题中,库只是用它们的名字来调用,例如,openFrameworks.a
应该被称为 libopenFrameworks.a
以便被 linker 拾取,但事实并非如此。那,我会在另一个问题下问。
So eventually all the libs are concatenated and passed into the linker:
link_directories (${OF_CORE_LIBS})
不,他们不是。来自 the manual
link_directories
Specify directories in which the linker will look for libraries.
link_directories(directory1 directory2 ...)
Specify the paths in which the linker should search for libraries.
所以您已经指定了 linker 应该搜索的目录
您想要 link 的库。现在你想指定 linker 应该 link 一个库,比如说,libfoo.a
your_executable
.
再次,the manual:
target_link_libraries(your_executable foo)
您告诉 linker 在哪里看 以及 要找什么。
以后
I think I am doing exactly what you have described in your answer, right?
不,你不是。
你给出了一个文件列表(显然它们是静态库,尽管它们缺少
常规 lib
前缀)到 link_directories
。它需要一个 目录列表
其中 linker 将查找您使用 target_link_libraries
.
指定的库
这就是为什么 linker 说:
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)
将导致 linker 在每个 link_directories
.
中查找库 libfoo.{so|a}
我有一些库位于非标准位置。这是来自 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.
当 link 在我的 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}
...
)
所以最终所有的库都被连接起来并传递到 linker:
link_directories (${OF_CORE_LIBS})
然后我使用:
target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})
到link他们。
但是,我在 linking 阶段收到以下警告:
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)
然后我将这些文件夹传递给 linker:
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
)
并且在 linking 阶段:
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 名称之间的区别。然而,仍然有一个问题得到了回答:How to tell CMake to accept and link arbitrary lib names?
在上面的问题中,库只是用它们的名字来调用,例如,openFrameworks.a
应该被称为 libopenFrameworks.a
以便被 linker 拾取,但事实并非如此。那,我会在另一个问题下问。
So eventually all the libs are concatenated and passed into the linker:
link_directories (${OF_CORE_LIBS})
不,他们不是。来自 the manual
link_directories
Specify directories in which the linker will look for libraries.
link_directories(directory1 directory2 ...)
Specify the paths in which the linker should search for libraries.
所以您已经指定了 linker 应该搜索的目录
您想要 link 的库。现在你想指定 linker 应该 link 一个库,比如说,libfoo.a
your_executable
.
再次,the manual:
target_link_libraries(your_executable foo)
您告诉 linker 在哪里看 以及 要找什么。
以后
I think I am doing exactly what you have described in your answer, right?
不,你不是。
你给出了一个文件列表(显然它们是静态库,尽管它们缺少
常规 lib
前缀)到 link_directories
。它需要一个 目录列表
其中 linker 将查找您使用 target_link_libraries
.
这就是为什么 linker 说:
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)
将导致 linker 在每个 link_directories
.
libfoo.{so|a}