Форум программистов, компьютерный форум CyberForum.ru

Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.79
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
07.02.2014, 17:22     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #1
Не, реально, зачем он?

...Друзья! Много где в инете вы найдёте как кропать dll-ки, например тут. обратите внимание на командную строку:

Bash
1
gcc -c -DBUILD_DLL dllfct.c
Да, так вот. Много где приводят примеры с использованием этго параметра, но зачем он никто толком не знает.

А вот я не поленился и скомандовал --help для каждого из экзешников лежащих в папке mingw\bin- ни для одного из экзешников такого параметра нет. То есть он просто-напросто ни одним из экзешников не используется. Вот результаты, кому интересно, в архиве.

Так зачем же нужен параметр -DBUILD_DLL? Спасибо, кто откликнется.
Вложения
Тип файла: rar rez.rar (46.3 Кб, 9 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.02.2014, 17:22     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW)
Посмотрите здесь:

Для чего нужен define? C++
C++ для чего нужен символ \b
Прототип функции.Для чего нужен C++
C++ Для чего нужен EOF?
Для чего нужен с++? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
19.02.2014, 22:31  [ТС]     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #41
Цитата Сообщение от DrOffset Посмотреть сообщение
Вот скажи, ты знаешь, что компилятор собирает каждый модуль отдельно, независимо? Именно поэтому у нас получаются объектные файлы на выходе cpp->obj (или o).
да
Цитата Сообщение от DrOffset Посмотреть сообщение
Понимаешь что такое компиляция?
нет
Цитата Сообщение от DrOffset Посмотреть сообщение
Понимаешь что такое связывание (линковка)?
нет
Если бы все ответы были "да", тогда и вопрос был бы плёвым.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
19.02.2014, 23:16     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #42
Цитата Сообщение от kravam Посмотреть сообщение
да
нет
нет
Если бы все ответы были "да", тогда и вопрос был бы плёвым.
Первого "да" хватит, чтобы понять почему компилятор не в состоянии узнать природу вызываемой функции.
В момент построения кода конкретного модуля у него нет информации об остальных модулях. В некоторых других языках - это не так и С++ часто за это ругают. Но эта архитектура уже существует. И мы идем от нее.

Линковщик работает потом и занимается разрешением ссылок между модулями. Вставляет сервисный код, характерный для заданной платформы. На его этапе уже можно понять что откуда вызывается, но здесь уже поздно. Ведь объектник может быть собран с хитрой оптимизацией, причем оптимизация может быть задана разная для разных объектников, просто так взять и вынуть одну инструкцию и вставить другую линкер не может. Даже без оптимизации не может. Вообще это не принципиально, я просто привел пример того, какие трудности стоят на пути реализации такой возможности в ликере.

Хотя существуют решения, которые потребуют ухода от текущей архитектуры, увеличения времени сборки.
Называется LTCG (Microsoft specific). Наверное твой вопрос разрешится, если задействовать LTCG. Но если разобраться, то это читерство, т.к. после включения LTCG obj-файл содержит уже не машинный код, а некоторое промежуточное представление, с которым может работать компилятор при последующих проходах. Это уже совсем не классический С++, хоть и может давать существенный прирост производительности.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.02.2014, 15:25     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #43
Цитата Сообщение от DrOffset Посмотреть сообщение
Называется LTCG (Microsoft specific).
В GCC это называется LTO.
Цитата Сообщение от DrOffset Посмотреть сообщение
Это уже совсем не классический С++
Технические особенности работы компилятора и линковщика собственно к C++ не относятся. Так что никакой потери "классичности" нет, по этому поводу можно не беспокоиться. Как и прежде, мы имеем на входе исходные коды, а на выходе исполняемый файл или библиотеку.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
20.02.2014, 15:32     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #44
Цитата Сообщение от Nick Alte Посмотреть сообщение
В GCC это называется LTO.
Да. Появилось относительно недавно.

Цитата Сообщение от Nick Alte Посмотреть сообщение
Технические особенности работы компилятора и линковщика собственно к C++ не относятся. Так что никакой потери "классичности" нет, по этому поводу можно не беспокоиться. Как и прежде, мы имеем на входе исходные коды, а на выходе исполняемый файл или библиотеку.
Чтобы было понятно, я в этом своем утверждении исходил не из стандарта языка, а из заявления Страуструпа (если мне не изменяет память - в книге The Design and Evolution of C++), что С++ проектировался так, чтобы исключить лишние проходы компилятора и иметь максимально возможную совместимость с С, если не на уровне кода, то на уровне линковки. То есть это уже практическая сторона (вне стандарта) и взгляд Страуструпа на этот вопрос.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.02.2014, 15:44     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #45
Цитата Сообщение от DrOffset Посмотреть сообщение
Да. Появилось относительно недавно.
Так ведь и у Микрософта оно не с начала времён.
Цитата Сообщение от DrOffset Посмотреть сообщение
То есть это уже практическая сторона (вне стандарта) и взгляд Страуструпа на этот вопрос.
Точнее говоря, это вопрос реализации. Но даже с учётом этого аспекта процесс всё равно не изменяется принципиально: компилятору достаётся меньше работы и он выдаёт более "сырой" промежуточный формат, линкеру приходится потрудиться больше, но по большому счёту обе фазы всё те же, всё там же.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
20.02.2014, 15:52     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #46
Да. И забыл упомянуть, что я не "вспомнил" про GCC-шный вариант потому, что он как раз не "нарушает" заявленный принцип и позволяет реализовать LTO на любом линкере, поддерживаемом GCC.
Despite the "link time" name, LTO does not need to use any special linker features. The basic mechanism needed is the detection of GIMPLE sections inside object files. This is currently implemented in collect2. Therefore, LTO will work on any linker already supported by GCC.
В отличие от варианта Microsoft.

Может ли LTO от GCC провести оптимизацию, которую хочет ТС - я не знаю. Надо проверять.

Добавлено через 6 минут
Цитата Сообщение от Nick Alte Посмотреть сообщение
Точнее говоря, это вопрос реализации. Но даже с учётом этого аспекта процесс всё равно не изменяется принципиально: компилятору достаётся меньше работы и он выдаёт более "сырой" промежуточный формат, линкеру приходится потрудиться больше, но по большому счёту обе фазы всё те же, всё там же.
На самом деле этот вопрос слабо коррелирует с изначальной темой.
Все, что ты написал - верно. Но то, что я вообще это упомянул, характеризует только мое личное мнение (которое в чем-то совпало с мнением автора языка) по поводу все большего ухода от канонов и потери и так небольшой совместимости между реализациями.
Т.к. не вижу смысла дальше это обсуждать, предлагаю вернуться к теме топика
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.02.2014, 11:08     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW)
Еще ссылки по теме:

Параметр rhs, что это и для чего (конструктор-копировщик) C++
Создание и использование dll- Для чего dllimport? C++
Создание программы, которая будет обращаться к компилятору C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
21.02.2014, 11:08  [ТС]     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) #47
Код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//B.cpp
#include <windows.h>
#include <stdio.h>
 
void my_func_exe ();
extern "C" __declspec(dllimport) void my_func_dll_0 ();
extern "C" void my_func_dll_1 ();
 
int main () {
 my_func_exe ();
 my_func_exe ();
 my_func_dll_0 ();
 my_func_dll_0 ();
 my_func_dll_1 ();
 my_func_dll_1 ();
 return 0;
}
Командуем:
Bash
1
2
gcc -c B.cpp
objdump -d B.o
Наблюдаем B.o
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
00000000 <_main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   e8 00 00 00 00          call   b <_main+0xb>
   b:   e8 00 00 00 00          call   10 <_main+0x10>
  10:   e8 00 00 00 00          call   15 <_main+0x15>
  15:   a1 00 00 00 00          mov    0x0,%eax
  1a:   ff d0                   call   *%eax
  1c:   a1 00 00 00 00          mov    0x0,%eax
  21:   ff d0                   call   *%eax
  23:   e8 00 00 00 00          call   28 <_main+0x28>
  28:   e8 00 00 00 00          call   2d <_main+0x2d>
  2d:   b8 00 00 00 00          mov    $0x0,%eax
  32:   c9                      leave
  33:   c3                      ret
Ну тут, собсно всё понятно. Если говорим компилятору __declspec(dllimport), то он вызывает функцию так:
Assembler
1
2
mov    eax, адрес_ячейки памяти_в_таблице_импорта // пока тут ноли
call   [eax]
В остальных случаях просто вызывает
Assembler
1
call   адрес_ячейки_памяти_в_коде_приложения //пока тут ноли
Синтаксис я переделал под masm.
Так, ну а потом линкёр заполняет таблицу импорта правильными адресами, вместо нолей подставляет нужные адреса, добавляет jmp во втором случае и всё становится круто.

Последний мой вопрос был: а почему компилятор во всех случаях, где функция вызывается из dll не пишет

mov eax, адрес_ячейки памяти_в_таблице_импорта // пока тут ноли
call [eax]

В свете последний осмыслений, этот вопрос кажется теперь глуповатым. "Потому, что компилятор не линкёр, так было задумано разработчиками."- этот ответ был бы вполне себе правомерным. Кесарю кесарево. Компилятор занимается тем, чем занимается, а линкёр адресами и различием того факта, откуда вызывается функция, не объявленная как- __declspec(dllimport). (Хотя в принципе, можно было сделать иначе, но это были бы дополнительные издержки- например, два прохода компилятора.)

Собсно, именно это и говорил DrOffset.

Для продвижения вперёд информации достаточно. А вообще по большому счёту, надо было бы знать- если компилятор лепит объектные файлы, то что такое объект в понимании компилятора? Максимально конкретно подойти к этому вопросу, и найти ответ типа:

1) Объектом в понимании компилятора является тело функции без адресов
2) и т. д.

Мысль, надеюсь понятна- что за сущности такие присутствуют в объектном файле ну и по адресам узнать. Но это отдельный разговор. Как и вопрос, возникший вследствие понимания- зачем нужны *.a файлы, если в них, кроме символов, ничего нет? Вопрос для отдельной темы, конечно. Всем спасибо.
Yandex
Объявления
21.02.2014, 11:08     Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW)
Ответ Создать тему
Опции темы

Текущее время: 16:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru