我正在尝试将SDL2作为一个库添加到我的项目中。我想把它静态地连接起来。我是c++的新手。
1 -为什么SDL网站建议尽可能动态链接?
我理解动态语言的好处。然而,假设用户已经安装了您需要的所有库并准备好进入他们的系统,这是一个相当大的假设。在我看来,动态链接听起来是个好主意,唯一的例子就是您正在使用操作系统/平台附带的众所周知的库。https://wiki.libsdl.org/Installation
2 -动态链接似乎自动找到(SDL2和SDL2_image)的内在依赖关系。静态链接不是。为什么会这样?,这是我的FindSDL2_image.cmake文件
find_path(SDL2_IMAGE_INCLUDE_DIR SDL_image.h)
include_directories(${SDL2_IMAGE_INCLUDE_DIR})
# PREFER STATIC LIBRARIES ########
# cmake respects the order of extensions when looking for libraries
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
# ------------------- ########
find_library(SDL2_IMAGE_LIBRARY NAMES SDL2_image PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX})
set(SDL2_IMAGE ${SDL2_IMAGE_LIBRARY})这是静态链接sdl2_image。它不能正确链接,因为Undefined symbols
"_png_set_strip_16", referenced from:
_IMG_LoadPNG_RW in libSDL2_image.a(IMG_png.o)
"_png_set_write_fn", referenced from:
_IMG_SavePNG_RW_libpng in libSDL2_image.a(IMG_png.o)
"_png_write_png", referenced from:
_IMG_SavePNG_RW_libpng in libSDL2_image.a(IMG_png.o)如果我删除cmake文件上的### PREFER STATIC LIBRARIES ##部分。它动态地链接,一切都按预期工作。为什么在动态链接时,内部依赖关系被解析,而不是静态链接时呢?
----UPDATE----
通过显式地包含sdl2_image的依赖项,我能够静态地链接它。
find_library(PNGLIB png)
find_library(JPEG jpeg)
find_library(TIFF tiff)
find_library(WEBP webp)
find_library(LZ z)
target_link_libraries(smb ${SDL2} ${PNGLIB} ${JPEG} ${TIFF} ${WEBP} ${SDL2_IMAGE} ${LZ})然而,这对我来说不是很好。找出这些依赖项需要一些猜测和googling。理想情况下,我希望CMAKE能够自动地将它们拉进来。
发布于 2020-04-28 14:10:54
看起来有几个问题,我会尽力一步一步地回答这个问题:
为什么SDL网站建议尽可能动态链接?
将应用程序与库动态链接的原因之一是将应用程序与库分离(在本例中称为共享库/ .so )。您可以更新您的库,而无需重新编译应用程序代码。例如,如果您已经完成了您的项目,并且您的客户端正在运行您的应用程序,我想,您不太可能希望重新编译您的应用程序代码,一旦您正在使用的底层库出现了错误修复。
另一方面,通过链接应用程序statically,可以将应用程序绑定到该库(.lib或.a表单)。意味着库中的每一项更改都将导致您重新编译代码。有时,这是希望的,例如,您已经为您的客户提供了您的应用程序的担保,通常您希望确保您的库的未来问题不会导致您的应用程序崩溃。
为了更好地理解这一点,我有一个简短的示例代码: CMakeLists.txt:
cmake_minimum_required (VERSION 3.0)
project(linkageLibrary)
set(STATIC_LIB lib_static)
set(SHARE_LIB lib_share)
set(STATIC_OTHER_LIB lib_otherstatic)
set(SHARE_OTHER_LIB lib_othershare)
add_library(${STATIC_LIB} STATIC ${STATIC_LIB}.cpp)
add_library(${SHARE_LIB} SHARED ${SHARE_LIB}.cpp)
# not yet in usage...
add_library(${STATIC_OTHER_LIB} STATIC ${STATIC_OTHER_LIB}.cpp)
add_library(${SHARE_OTHER_LIB} SHARED ${SHARE_OTHER_LIB}.cpp)
add_executable(${CMAKE_PROJECT_NAME} main.cpp)
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${${CMAKE_PROJECT_NAME}_SOURCE_DIR})
target_link_libraries(${CMAKE_PROJECT_NAME} ${STATIC_LIB} ${SHARE_LIB})
file(WRITE ${CMAKE_BINARY_DIR}/exchangeShareLibrary.sh "
echo \"before exchange the static library\"
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME} &&
mv ${CMAKE_BINARY_DIR}/lib${SHARE_LIB}.so ${CMAKE_BINARY_DIR}/lib${SHARE_LIB}.so.bk &&
cp ${CMAKE_BINARY_DIR}/lib${SHARE_OTHER_LIB}.so ${CMAKE_BINARY_DIR}/lib${SHARE_LIB}.so &&
echo \"after the shared library has been changed\" &&
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}")
file(WRITE ${CMAKE_BINARY_DIR}/exchangeStaticLibrary.sh "
echo \"before exchange the static library\"
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME} &&
mv ${CMAKE_BINARY_DIR}/lib${STATIC_LIB}.a ${CMAKE_BINARY_DIR}/lib${STATIC_LIB}a.bk &&
cp ${CMAKE_BINARY_DIR}/lib${STATIC_OTHER_LIB}.a ${CMAKE_BINARY_DIR}/lib${STATIC_LIB}.a &&
echo \"after the static library has been changed\" &&
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}")main.cpp:
#include <iostream>
#include "lib.hpp"
using namespace std;
int main() {
printStaticLib();
printShareLib();
return 0;
}lib.hpp:
#pragma ONCE
void printStaticLib();
void printShareLib();lib_static.cpp:
#include <iostream>
#include "lib.hpp"
using namespace std;
void printStaticLib() {
cout << "linkage of lib_static" << endl;
}lib_share.cpp:
#include <iostream>
#include "lib.hpp"
using namespace std;
void printShareLib() {
cout << "linkage of lib_share" << endl;
}lib_otherstatic.cpp:
#include <iostream>
#include "lib.hpp"
using namespace std;
void printStaticLib() {
cout << "linkage of the other lib_static with other text" << endl;
}lib_othershare.cpp:
#include <iostream>
#include "lib.hpp"
using namespace std;
void printShareLib() {
cout << "linkage of the other lib_share with other text" << endl;
}如果您运行生成的脚本,您将注意到在printShareLib()获取交换之后,.so将以不同的方式输出,而不是printStaticLib()。(在没有清理的情况下再次尝试make,如果您现在执行./linkageLibrary,您将得到printStaticLib()的其他输出。你能猜出原因吗?)
关于你的第二期:
动态链接似乎自动找到(SDL2和SDL2_image)的内在依赖关系。静态链接不是。为什么是这种情况?
在不了解系统设置的情况下,我猜构建系统无法找到.a静态库。试着找出它在哪里,并最终把find_library(SDL2_IMAGE_LIBRARY NAMES SDL2_image HINTS ${_YOUR_SDL2_INSTALLATION_PATH})链接
现在回到您的问题,为什么SDL2建议动态链接,这是库开发人员的决定,正如您可以在他的自述文件中看到的那样。
也请参考本博客如何使用SDL2与CMake
https://stackoverflow.com/questions/61263289
复制相似问题