首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用CMake静态链接SDL2 2/SD2_映像

用CMake静态链接SDL2 2/SD2_映像
EN

Stack Overflow用户
提问于 2020-04-17 02:43:02
回答 4查看 3.9K关注 0票数 4

我正在尝试将SDL2作为一个库添加到我的项目中。我想把它静态地连接起来。我是c++的新手。

1 -为什么SDL网站建议尽可能动态链接?

我理解动态语言的好处。然而,假设用户已经安装了您需要的所有库并准备好进入他们的系统,这是一个相当大的假设。在我看来,动态链接听起来是个好主意,唯一的例子就是您正在使用操作系统/平台附带的众所周知的库。https://wiki.libsdl.org/Installation

2 -动态链接似乎自动找到(SDL2和SDL2_image)的内在依赖关系。静态链接不是。为什么会这样?,这是我的FindSDL2_image.cmake文件

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
  "_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的依赖项,我能够静态地链接它。

代码语言:javascript
运行
复制
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能够自动地将它们拉进来。

EN

Stack Overflow用户

发布于 2020-04-28 14:10:54

看起来有几个问题,我会尽力一步一步地回答这个问题:

为什么SDL网站建议尽可能动态链接?

将应用程序与库动态链接的原因之一是将应用程序与库分离(在本例中称为共享库/ .so )。您可以更新您的库,而无需重新编译应用程序代码。例如,如果您已经完成了您的项目,并且您的客户端正在运行您的应用程序,我想,您不太可能希望重新编译您的应用程序代码,一旦您正在使用的底层库出现了错误修复。

另一方面,通过链接应用程序statically,可以将应用程序绑定到该库(.lib.a表单)。意味着库中的每一项更改都将导致您重新编译代码。有时,这是希望的,例如,您已经为您的客户提供了您的应用程序的担保,通常您希望确保您的库的未来问题不会导致您的应用程序崩溃。

为了更好地理解这一点,我有一个简短的示例代码: CMakeLists.txt:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
#include <iostream>
#include "lib.hpp"
using namespace std;

int main() {
    printStaticLib();
    printShareLib();
    return 0;
}

lib.hpp:

代码语言:javascript
运行
复制
#pragma ONCE

void printStaticLib();
void printShareLib();

lib_static.cpp:

代码语言:javascript
运行
复制
#include <iostream>
#include "lib.hpp"
using namespace std;

void printStaticLib() {
    cout << "linkage of lib_static" << endl;
}

lib_share.cpp:

代码语言:javascript
运行
复制
#include <iostream>
#include "lib.hpp"
using namespace std;

void printShareLib() {
    cout << "linkage of lib_share" << endl;
}

lib_otherstatic.cpp:

代码语言:javascript
运行
复制
#include <iostream>
#include "lib.hpp"
using namespace std;

void printStaticLib() {
    cout << "linkage of the other lib_static with other text" << endl;
}

lib_othershare.cpp:

代码语言:javascript
运行
复制
#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

票数 3
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61263289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档