Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: wxWidgets (3.0.4), MSVS2017 и статическая линковка приложений под WinXP.

Добрый день!
Играюсь с WxWidgets, небольшой затык: не могу "статически" (т.е., без wx*.dll) собрать ни одного примера для запуска под WinXP.

Сами библиотеки для статической линковки под WinXP вроде собираются, но проверить не могу: при сборке икзэмпл - приложений получаю сообщение об ошибке: "неразрешенный символ __imp__strerror"...

При сборке указываю:
"Набор инструментов платформы" - "Visual Studio 2017 - Windows XP (v141_xp)"
"Версия пакета SDK под Windows" - "7.0".
...
"Динамическая" (т.е., с wx*.dll) линковка выполняется без ошибок и без проблем работает под WinXP...
Точно также, все хорошо, если сборка (статическая или динамическая) выполняется не для ОС WinXP.
...

Не сталкивался ли кто-нибудь с такой "проблемой"? Или для WinXP никто уже не собирает?

Можно плюнуть и собирать с "динамической" линковкой, но хочется понять, в чем проблема.
Ответ:
Юзер 01
...не могу "статически" ...собрать ни одного примера для запуска под WinXP.

Сами библиотеки для статической линковки под WinXP вроде собираются, но проверить не могу: при сборке икзэмпл - приложений получаю сообщение об ошибке: "неразрешенный символ __imp__strerror"...

При сборке указываю:
"Набор инструментов платформы" - "Visual Studio 2017 - Windows XP (v141_xp)"
"Версия пакета SDK под Windows" - "7.0".
...
"Динамическая" (т.е., с wx*.dll) линковка выполняется без ошибок и без проблем работает под WinXP...
Точно также, все хорошо, если сборка (статическая или динамическая) выполняется не для ОС WinXP.
...


Исходная ситуация была такая же, но сообщение отличалось.
Решение нашлось:

В итоге приложение WxWidgets собирается и в "статическом" варианте под WinXP, если при выбранной v141_xp выключить "conformance mode" (опцию /permissive-).
Эта беда касается только v141_xp при "статической" сборке.

+ Ну и еще
Ну и еще, конечно, в проекте следует указать такую же кодировку проекта, какая использовалась при сборке библиотеки WxWidgets.


К сообщению приложен файл. Размер - 19Kb
Вопрос: Как выполнить статическую линковку библиотек?

Такая ситуация: скомпилировал на ноуте консольное приложение, на уровне хеллоу ворлда, а на персональном компе оно при запуске выдает системную ошибку (отсутствие файла libgcc_s_dw2-1.dll), в свою очередь скомпилированное на персональнике выдает ошибку на ноуте (отсутствие файла libgcc_s_seh-1.dll). Как мне произвести статическую линковку библиотек, чтобы я мог без проблем запускать прогу в других системах?

p.S> gcc 5.0.1 (minGW-w64)
Ответ:
Сообщение от ambrosia
а не подскажете, в какой литературе можно подробнее узнать о линковке?

Как обычно, бесплатную версию можно найти в интернете.
Вопрос: О статической линковке

Приветствую!

Задался вопросом как же правильно строить библиотеки для статической линковки. Вопрос возник после просмотра содержимого результирующего исполняемого файла. Дело в том, что после линковки некоторых библиотек в исполняемый файл попадает много незадействованного кода. Эксперимент оформил шелл-скриптом для *nix:

Скрытый текст
    #!/bin/sh
     
    if [ `whoami` = "root" ]; then
       echo "Под учеткой рута работать отказываюсь."
       exit
    fi
     
    # если clang не установлен - нужно заменить на gcc и g++ соответственно
     
    CC="clang -Wall -pedantic -O3 -c"
    CXX="clang++ -Wall -pedantic -O3 -c"
    LINK1="clang -static -O3"
    LINK2="clang++ -static -O3"
     
    # генерация библиотеки 1 ==================================
    #
    # все функции включаются в одну единицу трансляции
    #
    # =========================================================
     
    printf "#include <stdio.h>\n\n" > testo-1.c
    for i in $(seq 20)
    do
      printf "void SomeFunc_$i() {\n" >> testo-1.c
      printf "  printf(\"SomeFunc_$i\\\n\");\n" >> testo-1.c
      printf "}\n\n" >> testo-1.c
    done
    $CC testo-1.c
    ar rcs libtesto-1.a testo-1.o
    rm -f *.c *.o
     
    # генерация библиотеки 2 ==================================
    #
    # каждая функция включается в отдельную единицу трансляции
    #
    # =========================================================
     
     
    for i in $(seq 20)
    do
      printf "#include <stdio.h>\n\n" > testo-2-$i.c
      printf "void SomeFunc_$i() {\n" >> testo-2-$i.c
      printf "  printf(\"SomeFunc_$i\\\n\");\n" >> testo-2-$i.c
      printf "}\n\n" >> testo-2-$i.c
    done
    $CC testo-2-*.c
    ar rcs libtesto-2.a `ls testo-2-*.o`
    rm -f *.c *.o
     
    # генерация библиотеки 3 ==================================
    #
    # создается класс, где реализация методов включается в одну
    # единицу трансляции
    #
    # =========================================================
     
    printf "#pragma once\n\n" > testo-3.h
    printf "class GodClass {\n" >> testo-3.h
    printf "  public:\n" >> testo-3.h
    for i in $(seq 20)
    do
      printf "    void SomeMethod_$i();\n" >> testo-3.h
    done
    printf "};\n" >> testo-3.h
     
    printf "#include <iostream>\n" > testo-3.cpp
    printf "#include \"testo-3.h\"\n\n" >> testo-3.cpp
    for i in $(seq 20)
    do
      printf "void GodClass::SomeMethod_$i() {\n" >> testo-3.cpp
      printf "  std::cout << \"SomeMethod_$i\" << std::endl;\n" >> testo-3.cpp
      printf "}\n\n" >> testo-3.cpp
    done
    $CXX testo-3.cpp
    ar rcs libtesto-3.a testo-3.o
    rm -f *.cpp *.o
     
    # генерация библиотеки 4 ==================================
    #
    # создается класс, где реализация методов разносится по
    # разным единицам трансляции
    #
    # =========================================================
     
    printf "#pragma once\n\n" > testo-4.h
    printf "class GodClass {\n" >> testo-4.h
    printf "  public:\n" >> testo-4.h
    for i in $(seq 20)
    do
      printf "    void SomeMethod_$i();\n" >> testo-4.h
    done
    printf "};\n" >> testo-4.h
     
    for i in $(seq 20)
    do
      printf "#include <iostream>\n" > testo-4-$i.cpp
      printf "#include \"testo-4.h\"\n\n" >> testo-4-$i.cpp
      printf "void GodClass::SomeMethod_$i() {\n" >> testo-4-$i.cpp
      printf "  std::cout << \"SomeMethod_$i\" << std::endl;\n" >> testo-4-$i.cpp
      printf "}\n\n" >> testo-4-$i.cpp
    done
    $CXX testo-4-*.cpp
    ar rcs libtesto-4.a `ls testo-4-*.o`
    rm -f *.cpp *.o
     
    # линкуем исполняемые файлы ===============================
     
    printf "void SomeFunc_1();\n\n" > testo-1.c
    printf "int main() {\n" >> testo-1.c
    printf "  SomeFunc_1();\n" >> testo-1.c
    printf "}\n" >> testo-1.c
    cp testo-1.c testo-2.c
    $LINK1 testo-1.c -L. -ltesto-1 -o testo-1
    $LINK1 testo-2.c -L. -ltesto-2 -o testo-2
    printf "#include \"testo.h\"\n\n" > testo-3.cpp
    printf "int main() {\n" >> testo-3.cpp
    printf "  GodClass G;\n" >> testo-3.cpp
    printf "  G.SomeMethod_1();\n" >> testo-3.cpp
    printf "}\n" >> testo-3.cpp
    cp testo-3.cpp testo-4.cpp
    mv testo-3.h testo.h
    $LINK2 testo-3.cpp -L. -ltesto-3 -o testo-3
    $LINK2 testo-4.cpp -L. -ltesto-4 -o testo-4
    rm -f *.c* *.h
     
    # анализируем что попало в исполняемые файлы ==============
     
    clear
    echo "Найдено функций в  1-м исполняемом файле: "`nm testo-1 | grep SomeFunc | wc -l`
    echo "Найдено функций во 2-м исполняемом файле: "`nm testo-2 | grep SomeFunc | wc -l`
    echo "Найдено методов в  3-м исполняемом файле: "`nm testo-3 | grep SomeMethod | wc -l`
    echo "Найдено методов в  4-м исполняемом файле: "`nm testo-4 | grep SomeMethod | wc -l`

Результат работы скрипта таков:
    Найдено функций в  1-м исполняемом файле: 20
    Найдено функций во 2-м исполняемом файле: 1
    Найдено методов в  3-м исполняемом файле: 20
    Найдено методов в  4-м исполняемом файле: 1



Как видно, что если разносить функции и методы в разные единицы трансляции, и результат собирать в библиотеку - то "ненужное" при линковке в исполняемый модуль не попадает. Соответственно пара вопросов:

1) Можно ли как-то линкер "упросить" не заносить ненужное в исполняемый файл не используя выше означенный подход?
2) На сколько применим выше означенный подход для С++ (касаемо удаления реализации неиспользуемых методов класса)?

В данной теме прошу не поднимать вопросы проектирования, вопрос именно по линковке.
Ответ:
Цитата cppasm @
В GCC ещё есть LTO
Тоже помогает лишний код выбрасывать.

Это я сразу попробовал, слышал об этом. Но чет не исключало неиспользуемый код.
Вопрос: Статическая линковка OpenAL

Собрал данную библиотеку статической через CMake. Все ОК.
Собираю проект и вижу ошибки следующего вида:
Код:

obj\Debug\sound.o||In function `ZN5SoundD2Ev':|
F:\Projects (C++)\SD\SD\sound.cpp|18|undefined reference to `_imp__alcMakeContextCurrent'|
F:\Projects (C++)\SD\SD\sound.cpp|20|undefined reference to `_imp__alcDestroyContext'|
F:\Projects (C++)\SD\SD\sound.cpp|22|undefined reference to `_imp__alcCloseDevice'|
obj\Debug\sound.o||In function `ZN5Sound13CheckALCErrorEv':|
F:\Projects (C++)\SD\SD\sound.cpp|41|undefined reference to `_imp__alcGetError'|
F:\Projects (C++)\SD\SD\sound.cpp|43|undefined reference to `_imp__alcGetString'|
obj\Debug\sound.o||In function `ZN5Sound4initEv':|
F:\Projects (C++)\SD\SD\sound.cpp|62|undefined reference to `_imp__alcOpenDevice'|
F:\Projects (C++)\SD\SD\sound.cpp|70|undefined reference to `_imp__alcCreateContext'|
F:\Projects (C++)\SD\SD\sound.cpp|75|undefined reference to `_imp__alcMakeContextCurrent'|
F:\Projects (C++)\SD\SD\sound.cpp|79|undefined reference to `_imp__alListenerfv'|
F:\Projects (C++)\SD\SD\sound.cpp|81|undefined reference to `_imp__alListenerfv'|
F:\Projects (C++)\SD\SD\sound.cpp|83|undefined reference to `_imp__alListenerfv'|
obj\Debug\sound_stream.o||In function `ZN11SoundStreamD2Ev':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|15|undefined reference to `_imp__alDeleteBuffers'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream12CheckALErrorEv':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|22|undefined reference to `_imp__alGetError'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|24|undefined reference to `_imp__alGetString'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream4loadEP6Streamb':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|35|undefined reference to `_imp__alGenSources'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|45|undefined reference to `_imp__alSourcef'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|46|undefined reference to `_imp__alSourcef'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|47|undefined reference to `_imp__alSourcefv'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|48|undefined reference to `_imp__alSourcefv'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|50|undefined reference to `_imp__alSourcef'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream8load_oggEP6Stream':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|125|undefined reference to `_imp__alSourcei'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|136|undefined reference to `_imp__alGetSourcei'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|143|undefined reference to `_imp__alGenBuffers'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|167|undefined reference to `_imp__alSourcei'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|170|undefined reference to `_imp__alSourcei'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream12ReadOggBlockEjj':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|215|undefined reference to `_imp__alBufferData'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|222|undefined reference to `_imp__alSourceQueueBuffers'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream4playEv':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|230|undefined reference to `_imp__alSourcePlay'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream4stopEv':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|235|undefined reference to `_imp__alSourceStop'|
obj\Debug\sound_stream.o||In function `ZN11SoundStream5closeEv':|
F:\Projects (C++)\SD\SD\sound_stream.cpp|240|undefined reference to `_imp__alSourceStop'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|241|undefined reference to `_imp__alIsSource'|
F:\Projects (C++)\SD\SD\sound_stream.cpp|242|undefined reference to `_imp__alDeleteSources'|
||=== Build finished: 32 errors, 0 warnings (0 minutes, 0 seconds) ===|

Раньше собирал с shared-библиотекой (то есть в DLL) - все линковалось и работало. Но решил сделать статическую линковку для упрощения программы (что бы не таскать кучу библиотек выгоном).
Посмотрел файл libOpenAL32.a и вижу там объявление всех этих функций:
Код:

FIRST LINKER MEMBER
	Symbols	: 0000012A

	MbrOffs 	Name
	-------------------- 	--------------------
	000018D8  	_alDeleteAuxiliaryEffectSlots
	000018D8  	_alIsAuxiliaryEffectSlot
	000018D8  	_alAuxiliaryEffectSlotf
	000018D8  	_alAuxiliaryEffectSlotfv
	000018D8  	_alGetAuxiliaryEffectSloti
	000018D8  	_alGetAuxiliaryEffectSlotiv
	000018D8  	_alGetAuxiliaryEffectSlotf
	000018D8  	_alGetAuxiliaryEffectSlotfv
	000018D8  	_NoneCreate
	000018D8  	_InitializeEffect
и .т.д.

Всё отличие - в отсутствии "_imp_" в именах
Ответ: Она не обязательна. Новые версии спокойно собираются и работают...
Вопрос: Статическая линковка?

Куку, хотелось бы узнать, можно ли как то упаковать программу(1.exe) и библиотеку (.dll), которую использует программа и которая лежит рядом с ней, в один файл. Долго гуглил, даже дошел до адского названия статическая линковка, но конкретной инфы не удалось найти.

Проект C# (visual studio 2015)
Ответ: салома, качаешь , распаковываешь, включаешь нужные части в проект.
Вопрос: VS2013 LNK1104 - ошибка статической линковки библиотек в консольном приложении

Visual Studio 2013.
В решении три проекта (C++): консольное приложение и две статических библиотеки.
Указываю компоновщику дополнительные библиотеки при помощи директивы #pragma comment(lib, "mylib.lib").
В проекте статической библиотеки это работает. В проекте консольного приложения не работает - получаю LNK1104.
Если указать полный путь, то все линкуется успешно и в проекте консольного приложения. Но прописывать полные пути для каждой конфигурации не удобно и не правильно.

В VS2008, точно помню, все работало без полного пути.

Кто-нибудь знает как это победить в VS2013?
Ответ: Если кому-то интересно, то решение добавить путь в свойствах проекта. То есть в свойствах проекта: Configuration Properties -> VC++ Diretories -> Library Directories=$(OutDir);$(LibraryPath)
После этого проект консольного приложения находит локальные статические библиотеки.
Вопрос: Статическая линковка библиотеки GLEW (qmake, mingw)

Для использования GLEW в Qt Creator с компилятором MinGW скачал исходники GLEW () и собрал через консоль, скоприровав это:
Кликните здесь для просмотра всего текста
gcc -DGLEW_NO_GLU -O2 -Wall -W -Iinclude -DGLEW_BUILD -o src/glew.o -c src/glew.c
gcc -shared -Wl,-soname,libglew32.dll -Wl,--out-implib,lib/libglew32.dll.a -o lib/glew32.dll src/glew.o -L/mingw/lib -lglu32 -lopengl32 -lgdi32 -luser32 -lkernel32
ar cr lib/libglew32.a src/glew.o

В pro файле проекта прописываю необходимый путь до заголовочников (INCLUDEPATH) и до библиотек (QMAKE_LIBDIR и LIBS += -lglew32 соответственно). И конечно же путь до dll в переменную PATH настроек среды запуска приложения. Таким образом, с динамической линковкой живётся без проблем и без ошибок.
Проблемы начинаются со статической сборкой. По идее, это должно решаться прописыванием "#define GLEW_STATIC" перед включением заголовочника glew.h. Ещё был вариант добавить флаг компиляции в pro файл: "QMAKE_CXXFLAGS += -DGLEW_STATIC". Тем не менее, ни после первого, ни после второго вариантов (ни после их комбинации) приложение не перестаёт требовать dll. Что не так, и что, может быть, нужно сделать дополнительно? Заранее спасибо за ответ.
Ответ: Без ошибок. Причём мелькало, что libglew.a он собирает с флагом -DGLEW_STATIC.
Вопрос: Нюанс статической линковки

Не ради какой-то практической пользы (коммерческой лицензии нет), а ради интереса - попытался собрать свой проект, использующий Qt, в статике.
Произошла ошибка ликновки, "мол такой-то символ неопределен". И тут дело даже не в использовании Qt, т.к. линкер не находил символы из libssl. Хотя странно, в строке сборки подключение этой библиотеки присутствует. Вобщем, как часто бывает, методом "научного тыка" изменил порядок в строке флагов сборки. А именно, в Makefile.Release перенес часть ключей "-lssl -lcrypto -lcrypt32 -lz -lws2_32" из начала в конец строки флагов сборки ... И все собралось :-?

Я понимаю, это выход, но это костыль - хочется делать все это всеж из IDE (QtCreator), ибо повторная генерация make-файлов, в случае полной пересборки с очисткой - все опять приводит к ошибке сборки.

Вообщем, нужны мысли, как решить проблему.

И еще вот прям щя вспомнилось ... когда собирал тулчейн x86_64-w64-mingw32.static, да и равно как и все остальные, мною во всю использовался и настраивался инструмент pkgconfig, а в проектах в QtCreator я его не использую. Может это быть причиной?
Сообщение отредактировано: JoeUser -
Ответ:
Цитата HardRock @
Порядок библиотек при статической линковки имеет значение потому что линкер "заглядывает" в библиотеку один раз, вытаскивая из неё только функции, которые уже знает (нашел ранее) и которые при этом помечены как undefined.

А можно где-то про это почитать? А то очень уж не очевидно это звучит.
Вопрос: Статическая линковка Qt 5.6

Решил я обновить Qt до 5.6. После чего надо было собрать комплект статической сборки. Решил собирать по этой инструкции так как еще с 5.0.2 процес не менялся (не считая ключей конфигуратора). Но вот незадача ни папки Src, ни configure.bat в папке (и подпапках) Qt не было обнаружено. Как их добавить?
Ответ:
Сообщение от ASKMAN
Что вы под этим подразумеваете?
Когда устанавливали QT надо было ставить галоччку напротив Sources(или, что то в этом роде) и тогда у вас были бы исходники.
Вопрос: IDE и статическая линковка (UNIX)

Подскажите, пожалуста кто сталкивался с написанием портативных программ (библиотеки вместе с приложением).
Было испробыванно С# - не заточенно под UNIX, Qt - чтобы собрать статический qmake требуеться скомпилировать около 470мб исходников (после пару часов ожидания компиляции, остановил процес и отказался от Qt).

ВОПРОС - Что лутше использовать для написания приложенний?
Ответ:
Сообщение от pdaomsk
Если под Linux компилить динамически, то на другой машине оно не запускается если не установлена qt-sdk.
Наглая ложь.