Я пытаюсь создать приложение и снова связать его с dll ffmpeg. Однако я хочу создать статический exe-файл.
Я использую MSYS2 и mingw-w64 (x86_64) с версией gcc 13.2.0, при сборке эта команда используется в make-файле.
gcc -g -O2 -static -o comskip.exe comskip-comskip.o comskip-mpeg2dec.o comskip-platform.o comskip-video_out_dx.o ccextratorwin/comskip-608.o ccextratorwin/comskip-ccextractor.o ccextratorwin/comskip-encoding.o ccextratorwin/comskip-general_loop.o ccextratorwin/comskip-myth.o -largtable2 -Lffmpeg-6.1.1-full_build-shared/lib -lavutil -lavformat -lavcodec -lswscale -lcomdlg32 -lgdi32 -lpthread -lm
Однако созданный exe-файл не связан статически с библиотеками ffmpeg (avcodec, avutil, avformat и swscale). Когда я пытаюсь запустить exe, он все равно запрашивает файл dll отдельно.
У меня в папке lib есть файлы avcodec.lib, avcodec-60.def и avcodec.dll.a. Вопрос в том, почему mingw-w64 по-прежнему связывается динамически, а не статически с файлами .lib? Что мне нужно, чтобы он статически связывался с библиотекой avcodec? (У меня также есть файл avcodec.dll, но я понимаю, что файлы .lib необходимы для статической связи). Это 64-битные файлы dll и lib.
Пробовал, никакой разницы





Я пытаюсь создать приложение и связать его с dll ffmpeg. Однако я хочу создать статический exe-файл.
Боюсь, это не вариант. Вы не можете статически связывать библиотеки DLL. в программу. Программа может загружать только библиотеки DLL во время выполнения: такова природа Динамические библиотеки. Единственное, что вы можете статически связать с программой представляют собой объектные файлы, которые могут быть явно названы компоновщику или выборочно. извлеченный компоновщиком из статической библиотеки . Объектные файлы всегда статически связаны; динамические библиотеки всегда динамически связан. Это единственные варианты.
Но тот факт, что ваша программа упорно пытается загрузить свои библиотеки DLL, хотя вам удастся связать его статически:
gcc -g -O2 -static -o comskip.exe ....
представляет собой более темную проблему.
Мы надеемся и ожидаем, что такая команда, как gcc ... -static -o prog ..., не сможет создать исполняемый файл с динамическими зависимостями. Но в Windows есть способ, благодаря историческому опыту Microsoft.
решение, что name.lib с таким же успехом может быть именем библиотеки импорта DLL
для name.dll, а также имя версии статической библиотеки name.dll.
насколько я понимаю, файлы .lib необходимы для статической связи
Звучит так, как будто вы думаете, что если у вас есть, например. "тот" avcodec.lib файл, который соответствует avcodec.dll
то вы можете использовать его для статической ссылки avcodec.dll на программу.
Вы не можете. Если есть файл avcodec.lib, соответствующий avcodec.dll, то avcodec.lib может быть
или:
avcodec, только для статического связывания, тогда как name.dll
версия динамической библиотеки, только для динамического связывания. Они оба созданы из одних и тех же объектных файлов,
но совершенно по-разному. avcodec.dll и avcodec.lib независимы друг от друга.
Вам не нужно avcodec.lib, чтобы связать программу с avcodec.dll. Вам не нужно avcodec.dll, чтобы
ссылка с avcodec.lib. Вы никогда (намеренно) не будете связывать программу с обоими.или avcodec.lib может быть:
avcodec.dll с программой. Компоновщик MS не может напрямую связываться с DLL:
чтобы сделать это косвенно, ему нужна библиотека импорта для ввода в
вместо этого компоновщик. Библиотека импорта avcodec.lib есть
прокси времени соединения для avcodec.dll. Он содержит заглушки, представляющие
символы, экспортированные с помощью avcodec.dll, которые компоновщик среды выполнения разрешит
настоящие символы, как только avcodec.dll будут найдены и загружены вместе с программой.Как видите, это две разные вещи, которые avcodec.lib могут быть,
согласно соглашению об именах библиотек MS, имеют совершенно противоречивые цели :)
Соглашения об именах библиотек, соблюдаемые компоновщиком Msys2/mingw64.
Чтобы правильно установить связи Msys2/mingw64, необходимо понять имена и типы файлов, которые компоновщик может использовать в качестве библиотек разных типов. Мы будем использовать соответствующую библиотеку примеров avcodec.
libavcodec.dll: каноническое имя Msys2/mingw64 для динамической библиотеки avcodec.libavcodec.a: каноническое имя Msys2/mingw64 для статической библиотеки avcodec. Этот файл
— это архив, созданный архиватором GNU ar — каноническое расширение файла .a — заполненный
объектные файлы для выборочного использования в статической компоновке.libavcodec.dll.a: Каноническое имя Msys2/mingw64 для библиотеки импорта, соответствующей libavcodec.dll. Этот
файл — это ar архив, содержащий очень маленькие объектные файлы, служащие во время компоновки.
заглушки для символов, экспортированных libavcodec.dllavcodec.dll.a: Неканоническое имя Msys2/mingw64 для библиотеки импорта, возможно, созданное для соответствия libavcodec.dll
и, возможно, соответствовать avcodec.dll.avcodec.dll: каноническое название Microsoft для динамической библиотеки avcodec.avcodec.lib: каноническое имя Microsoft для статической библиотеки avcodec. Этот файл
— это архив, созданный архиватором Microsoft LIB — каноническое расширение .lib — заполненный
с объектными файлами для выборочного использования в статической компоновке.avcodec.lib: также каноническое имя Microsoft для библиотеки импорта, соответствующей avcodec.dll. Этот
file — это архив LIB, содержащий очень маленькие объектные файлы, которые служат заглушками во время компоновки для символов, экспортируемых name.dll.
Поскольку это архив LIB и содержит объектные файлы, это строго статическая библиотека — это просто
бесполезно статически связывать библиотеку avcodec! Если «настоящая» статическая библиотека avcodec.lib вообще существует,
это где-то еще.Как решает компоновщик Msys2/mingw64 -l name.
В отличие от компоновщика Microsoft компоновщику Msys2/mingw64 фактически не нужна библиотека импорта для связывания с DLL. но он будет использовать библиотеку импорта, если сначала встретит ее. Или Кстати, у вас все еще есть динамическая, а не статическая связь: время выполнения программы зависит от DLL.
Компоновщик отдает предпочтение библиотекам, которые соответствуют его собственным соглашениям об именах. но также пытается соответствовать соглашению об именах Microsoft.
По умолчанию компоновщик разрешает связывание с DLL и предпочитает их статическим библиотекам. Чтобы решить -l name,
он просматривает свой список каталогов явного и неявного поиска в поисках файлов-кандидатов.
В каждом каталоге он будет принимать следующие файлы в порядке предпочтения:
libname.dll, libname.dll.a, name.dll.a, name.dll, libname.a, name.lib
Если опция -static была передана gcc, то только два последних из них будут
быть приняты, поскольку все остальные подразумевают динамическую связь. Как только компоновщик находит в каталоге каких-либо кандидатов, он выбирает
предпочтительный, вводит его в связь и больше не смотрит.
Что пошло не так
Для связи -staticlibname.a или name.lib должны быть настоящей статической библиотекой.
что ты хочешь. Но любая из них на самом деле может быть библиотекой импорта, и компоновщик будет
не будьте мудрее, если файл действительно является архивом, содержащим объектные файлы.
С libname.a очень маловероятно, что файл действительно будет библиотекой импорта.
а не статическая библиотека, потому что канонической библиотекой импорта будет libname.dll.a. Но с
в стиле Microsoft name.lib такого различия нет: библиотека импорта может легко
проникнуть в путь поиска вашего компоновщика туда, где должна находиться настоящая статическая библиотека, или вас просто примут за статическую библиотеку.
библиотеку, когда проработаете -L dir варианты поиска библиотеки.
Одна из таких вещей случилась с вами. В вашей ссылке -static компоновщик принимает
avcodec.lib как разрешающая -l avcodec. Он находится в каталоге поиска, также содержащем avcodec.def и avcodec.dll.a. avcodec.def
не является каким-либо именем библиотеки (это выходной файл gendef) и avcodec.dll.a не будет принят
разрешить -l avcodec в -static связи. Итак, avcodec.lib связан. На самом деле это библиотека импорта в стиле MS, которая
прокси для avcodec.dll и ваш «статически связанный» comskip.exe соответственно пытается загрузить avcodec.dll во время выполнения.
В unix-подобных ОС компоновщик не может быть обманут таким образом, поскольку он не использует библиотеки импорта, даже опционально.
И компоновщик MS тоже нельзя обмануть таким образом, потому что у него нет эквивалента опции gcc-static.
Компоновщик Msys2/mingw64 можно обмануть таким образом, потому что это компоновщик GNU/Linux, портированный на Windows с дополнительной поддержкой.
для импортных библиотек.
Судя по вашему варианту связи -Lffmpeg-6.1.1-full_build-shared/lib, получается, что ffmpeg-6.1.1-full_build-shared/lib
— это каталог поиска, в котором сохраняется эта путаница с библиотеками. Вероятно, схема:
name.lib, name.def, name.dll.a
повторяется для всех остальных ffmpeg библиотек, на которые вы ссылаетесь. Если вы не создали это
настройте сами, тогда я предполагаю, что
name.lib файлы были помещены туда в качестве библиотек импорта для сборки с помощью набора инструментов MS Visual C++, и что
name.dll.a файлы возникли с помощью таких команд, как:
> gendef.exe [lib?]name.dll
> dlltool.exe -d [lib?]name.def -D [lib?]name.dll -l name.dll.a
и был помещен туда в качестве библиотек импорта для сборки с помощью набора инструментов Msys2/mingw64 GCC.
Что делать?
Чтобы статически связать свой comskip.exe, вам нужно связать настоящий ffmpeg статический
библиотеки для mingw64 GCC. Вы можете установить все это в MSYS2 из пакета mingw-w64-x86_64-ffmpeg.
В оболочке MSYS2 выполните:
$ pacman -S mingw-w64-x86_64-ffmpeg
Тогда добавьте ссылку -L C:\msys64\mingw64\lib вместо -Lffmpeg-6.1.1-full_build-shared/lib.
Из библиотек, отличных от ffmpeg, которые вы ссылаетесь,
-largtable2 ... -lcomdlg32 -lgdi32 -lpthread -lm
вы должны обнаружить, что C:\msys64\mingw64\lib имеет статические версии всех, кроме libargtable2.a. Для этого не существует пакета pacman.
Google сообщает мне, что дистрибутив исходного кода argtable2 находится на Sourceforge
и github. Вы, вероятно, получили это от одного из тех
исходники и можете самостоятельно собрать статическую библиотеку с помощью gcc и ar. Однако эти источники видели
никакого развития в течение примерно 10 лет, и я также заметил более активный форк github argtabl3, который вы можете проверить.
Удивительно полезно. К вашему сведению, мне удалось установить библиотеки argtable2 в MSYS2 через pacman, используя pacman -S $MINGW_PACKAGE_PREFIX-argtable. Я видел этот инструмент для преобразования .lib в .a, но, похоже, он не работает с 64-битными dll. Может ли это быть потому, что он не поддерживает 64-битную версию, или потому, что, как вы сказали, это не настоящий архив, а библиотека компоновщика. code.google.com/archive/p/lib2a
@user2406275 user2406275 Пожалуйста, и приятно, что у pacman есть все ваши библиотеки. Не знаю LIB2A, но на первый взгляд это похоже на любительское упражнение по созданию вряд ли необходимого графического интерфейса Windows для простых команд Mingw64. Я не сразу вижу в этом необходимость, поскольку вы видели, что компоновщик Mingw64 вполне доволен библиотеками импорта MS, а пакеты библиотек OTOH pacman поставляются с каноническими *.dll.a библиотеками импорта.
Что произойдет, если вы переместите файлы
av*.dll.aиз папки lib в другое место, а затем попытаетесь связать их?