MSVC - Исполняемый файл собирается правильно, а DLL - нет, отсутствуют символы и конфликтуют зависимости - SSCCE / Repro - PullRequest
0 голосов
/ 07 октября 2018

У меня есть работающий исполняемый файл, и я пытаюсь собрать DLL из того же кода, но у меня возникают некоторые странные ошибки, и мне удалось определить виновников после многих пробных ошибок, я решил попроситьпомочь, потому что я действительно застрял сейчас.Я статически связываю SDL2 и Cimgui (Dear Imgui C Wrapper) в моем коде, исполняемый файл работает отлично:

#include "imgui/imgui.h"
#include "cimgui.h"
#pragma comment(lib, "cimgui.lib")

#include "SDL.h"
#undef main
#pragma comment(lib, "SDL2-staticd.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "version.lib")

void main()
{
    SDL_Init(0);
    igCreateContext(0);
    printf("OK");
}

Так что теперь я переключаю проект на DLL (яотключил эту опцию /IMPLIB, чтобы убедиться, что единственное отличие в команде ссылки - это /DLL и расширение).Когда я пытаюсь собрать, я получаю сообщения об ошибках cimgui.lib, таких как:

cimgui.lib(imgui_draw.obj) : error LNK2001: unresolved external symbol memcmp
cimgui.lib(imgui_widgets.obj) : error LNK2001: unresolved external symbol memcpy
cimgui.lib(imgui.obj) : error LNK2001: unresolved external symbol memset

Очевидно, что среда выполнения Visual C больше не связана, я не совсем понимаю, почему, я мог бы просто добавить ее немедленно, нодавайте вернемся назад и удалим Cimgui из кода:

#include "SDL.h"
#undef main
#pragma comment(lib, "SDL2-staticd.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "version.lib")

extern "C" __declspec(dllexport) void main()
{
    SDL_Init(0);
}

Я получаю 13 ошибок, подобных этой:

MSVCRTD.lib(_init_.obj) : error LNK2019: unresolved external symbol _CrtDbgReport referenced in function _CRT_RTC_INIT

Поэтому я вручную включаю библиотеки, содержащие недостающие символы: ucrtd.lib, vcruntimed.lib, а затем DLL строится нормально.

Теперь я пытаюсь снова добавить Cimgui, но он не может скомпилировать с такими ошибками:

MSVCRTD.lib(utility.obj) : error LNK2019: unresolved external symbol __vcrt_initialize referenced in function __scrt_initialize_crt
MSVCRTD.lib(utility.obj) : error LNK2019: unresolved external symbol __acrt_initialize referenced in function __scrt_initialize_crt

__vcrtопределения находятся в libvcruntimed.lib, но определения __acrt находятся в libucrtd.lib, что конфликтует с ucrtd.lib, и даже если я удаляю ucrtd.lib в целом и пытаюсь связать только libucrtd.lib, я получаю ошибки типа:

ucrtd.lib(ucrtbased.dll) : error LNK2005: malloc already defined in libucrtd.lib(malloc.obj)

Что я не знаю, как интерпретировать, потому что я не связываю ucrtd.lib.

Я действительно не понимаю, почему создание DLL не похоже на созданиеИсполняемый особенно потому, что двоичный файл EXE очень похож на DLL, и я мог бы даже насОн может взаимодействовать как DLL, но это не так.Я уверен, что есть способ построить это, и я просто не знаю, как.

Для полноты (и на всякий случай), вот команды компоновщика для EXE и DLL:

/OUT:"C:\Projects\BuildTest\x64\Debug\Build.dll" /MANIFEST /NXCOMPAT /PDB:"C:\Projects\BuildTest\x64\Debug\Build.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /DLL /MACHINE:X64 /INCREMENTAL /PGD:"C:\Projects\BuildTest\x64\Debug\Build.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\Build.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Projects\cimgui_build\Debug" /LIBPATH:"C:\Projects\SDL2-2.0.8\build\Debug" /TLBID:1 
/OUT:"C:\Projects\BuildTest\x64\Debug\Build.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Projects\BuildTest\x64\Debug\Build.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X64 /INCREMENTAL /PGD:"C:\Projects\BuildTest\x64\Debug\Build.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\Build.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Projects\cimgui_build\Debug" /LIBPATH:"C:\Projects\SDL2-2.0.8\build\Debug" /TLBID:1 

РЕДАКТИРОВАТЬ:

Я сделал «Минимальный, полный и проверяемый пример» (Автономный - зависимости включены, относительные пути, проект VS2017, должны компилироваться непосредственно при наличии Windows SDK) и опубликован здесь онлайн:

https://bitbucket.org/AlanGameDev/buildmvce_so/downloads/

(вы можете скачать и извлечь или клонировать, если хотите)

1 Ответ

0 голосов
/ 15 октября 2018

Если вы установите флаг компоновщика / VERBOSE как для сборок exe / dll, так и для сравнения результатов, вы получите представление о том, что происходит.

В сборке exe вы увидите

1>      Found mainCRTStartup
1>        Loaded MSVCRTD.lib(exe_main.obj)
...

1>      Found __xi_a
1>        Referenced in MSVCRTD.lib(exe_main.obj)
1>        Loaded MSVCRTD.lib(initializers.obj)
1>Processed /DEFAULTLIB:kernel32.lib
1> Processed /DISALLOWLIB:msvcrt.lib
1> Processed /DISALLOWLIB:libcmt.lib
1> Processed /DISALLOWLIB:libcmtd.lib
1> Processed /DISALLOWLIB:vcruntime.lib
1>Processed /DEFAULTLIB:vcruntimed.lib
1> Processed /DISALLOWLIB:libvcruntime.lib
1> Processed /DISALLOWLIB:libvcruntimed.lib
1> Processed /DISALLOWLIB:ucrt.lib
1>Processed /DEFAULTLIB:ucrtd.lib
1> Processed /DISALLOWLIB:libucrt.lib
1> Processed /DISALLOWLIB:libucrtd.lib

, ни один из которых не появится в сборке dll.В сборке dll вы увидите только -

1>      Found _DllMainCRTStartup
1>        Loaded SDL2-staticd.lib(SDL.obj)

Что очень странно.Кажется, SDL2 включает свою собственную реализацию точки входа _DllMainCRTStartup, и поскольку компоновщик берет ее оттуда, а не crt lib - он пропускает множество полезных / DEFAULTLIB прагм.включен в SDL для удовлетворения некоторых потребностей Watcom , и уже предполагалось, что это вызовет проблемы в MSVC.

Если вы собираете SDL из источников, вам, вероятно, следует просто закомментировать реализацию _dllMainCRTStartup и (надеюсь) собрать успешно.

...