diff --git a/editorial/agent-rewrites/371.json b/editorial/agent-rewrites/371.json index e7d3fae..eb612a8 100644 --- a/editorial/agent-rewrites/371.json +++ b/editorial/agent-rewrites/371.json @@ -3,5 +3,5 @@ "slug": "компиляция-64-x-разрядных-программ-на-dmd-по", "title": "DMD под Windows x64: как проверить архитектуру сборки и зависимости", "excerpt": "Сборка D-программы с флагом -m64 не заканчивается на успешном сообщении компилятора. Разберём, как проверить DMD, linker, PE-заголовок и DLL, чтобы не искать ошибку в коде, когда проблема находится в toolchain.", - "contentHtml": "

Команда dmd -m64 main.d завершается без ошибки, но приложение не запускается на другой Windows-машине. Иногда linker сообщает о несовместимой библиотеке. Иногда Windows показывает, что DLL не найдена. Размер .exe при этом выглядит убедительно, а исходный код не менялся. Ошибка стоит времени на повторные сборки, ручное копирование DLL и отладку не того слоя.

\n

Тезис простой: 64-битный результат задаёт не только флаг -m64. Важны версия DMD, выбранный linker, архитектура объектных и библиотечных файлов, окружение командной строки и набор DLL, который увидит целевая система. Проверять нужно готовый PE-файл, а не предположение по команде сборки.

\n
\"Проверка
Граница проверки проходит от команды DMD до PE-заголовка и DLL, которые нужны готовому приложению.
\n

Что именно меняет -m64

\n

Флаг -m64 просит DMD собрать 64-битную программу. Он не превращает 32-битную внешнюю библиотеку в 64-битную. Он также не исправляет PATH, не устанавливает linker и не добавляет отсутствующую DLL. Каждый слой отвечает за свою часть результата.

\n

На старых установках DMD под Windows настройки могли лежать в sc.ini. Там указывались linker и пути к SDK. Если 64-битная секция ссылалась на старую 32-битную утилиту или на каталог библиотек другой платформы, исходники компилировались, а линковка падала. В ранних сценариях отдельно встречалась граница между OMF и COFF: объектный файл или .lib одного формата нельзя безусловно подключить к другому.

\n

Современный официальный установщик обычно закрывает базовую настройку сам. Это не отменяет проверки. На машине могут остаться несколько DMD, Visual Studio Build Tools могут быть установлены без нужного набора C++, а DUB может использовать другую конфигурацию, чем ручная команда. Поэтому сначала фиксируем фактические версии и пути.

\n

Минимальная проверка на учебном проекте

\n

Ниже приведён учебный пример для Windows. Он не показывает production-совместимость и не доказывает, что любая библиотека проекта поддерживает x64. Создайте отдельный каталог с одним исходным файлом, чтобы отделить проблему toolchain от проблемы приложения.

\n
@echo off\nwhere dmd\ndmd --version\nwhere dub\ndub --version\n\nif not exist bin mkdir bin\ndmd -m64 -of=bin\\hello.exe source\\hello.d\nif errorlevel 1 exit /b 1\n\ndumpbin /headers bin\\hello.exe | findstr /i \"machine\"\ndumpbin /dependents bin\\hello.exe
\n

Файл source\\hello.d может содержать только import std.stdio; void main() { writeln(\"Hello, x64\"); }. Это проверяет учебный путь от DMD до исполняемого файла. Строка с PE-заголовком должна показывать признак x64, а /DEPENDENTS выводит импортируемые DLL. Конкретный текст вывода зависит от версии Visual Studio и установленного набора инструментов.

\n

Запускайте dumpbin из Developer Command Prompt или из x64 Native Tools Command Prompt. Если команда не найдена, это проблема окружения, а не повод копировать случайный dumpbin.exe в каталог проекта. Найдите установленный набор Visual Studio и откройте его командную строку.

\n

Симптом → причина → проверка → действие

\n
СимптомПричинаПроверкаДействие
Линковка сообщает о machine type conflictОбъект или .lib собран для другой архитектурыПроверить PE-заголовки и происхождение каждого бинарного файлаПересобрать зависимость под x64 или выбрать совместимый пакет
dmd найден, но linker не найденPATH указывает не на то окружениеwhere dmd, версия DMD, команда linkerОткрыть Developer Command Prompt и повторить проверку
Сборка проходит, запуск сообщает о пропавшей DLLЗависимость не установлена или не попала в поставкуdumpbin /dependents и запуск в чистой средеДобавить разрешённую DLL в поставку или убрать зависимость
Ручная правка sc.ini не помогаетИсправлен не тот раздел или используется другой DMDСверить путь из where dmd с каталогом sc.iniСначала выбрать один toolchain; затем изменить только нужную настройку
Debug работает, release нетКонфигурации используют разные linker или runtimeСравнить команды, PATH и список DLL двух сборокЗафиксировать release-окружение и проверить его отдельно
\n

Порядок действий

\n
  1. Запишите целевую платформу, версию Windows, версию DMD и способ запуска сборки.
  2. Выполните where dmd, dmd --version и, если используется DUB, dub --version. Убедитесь, что команда запускает ожидаемый toolchain.
  3. Откройте Developer Command Prompt с Visual C++ tools. Не смешивайте linker из одного окружения с библиотеками из другого без проверки.
  4. Соберите минимальный учебный проект командой dmd -m64. Сохраните полный вывод и код возврата.
  5. Проверьте PE-заголовок готового файла через dumpbin /headers. Не используйте размер файла как признак архитектуры.
  6. Проверьте импортируемые DLL через dumpbin /dependents. Отдельно проверьте запуск release-бинарника в изолированной среде без случайных DLL из PATH.
  7. Если ошибка остаётся, заменяйте по одному слою: сначала внешний .lib, затем linker, затем конфигурацию DUB. После каждого изменения повторяйте проверку PE и зависимостей.
\n

Если проверка не проходит

\n

Не начинайте с переписывания D-кода. Сначала сохраните сообщение linker, список команд и пути, которые вывел where. Затем определите файл, на котором появилась ошибка. Для внешней библиотеки проверьте, кто её собрал и для какой архитектуры. Если поставщик даёт только 32-битный бинарник, флаг -m64 не решит проблему.

\n

Не копируйте DLL из каталога Windows или Visual Studio в папку приложения наугад. Такая копия может скрыть настоящую зависимость и создать другой результат на машине пользователя. Сначала выясните, какая библиотека импортируется и разрешена ли её поставка. Для системной DLL учитывайте версию Windows и установленный runtime.

\n

Если используется старая DMD, ручная правка sc.ini может быть необходима. Меняйте только секцию, соответствующую 64-битной сборке, и делайте резервную копию файла. После изменения снова выведите путь к DMD и повторите учебную сборку. Если результат не изменился, вероятно, команда читает другой sc.ini или linker берётся из PATH.

\n

Ограничения

\n

Эта проверка устанавливает архитектуру учебного бинарника и показывает его прямые импорты. Она не гарантирует работу графического интерфейса, COM, драйверов, установщика или всех динамических загрузок через LoadLibrary. Она также не заменяет тестирование конкретных внешних библиотек и не подтверждает поддержку каждой версии Windows.

\n

Команды с dumpbin зависят от наличия Visual Studio tools. На машине без них нужен другой проверенный PE-анализатор, но критерий остаётся тем же: инструмент должен прочитать архитектуру файла и список зависимостей. Не делайте вывод о x64 по имени каталога, флагу в скрипте или размеру .exe.

\n

Учебные имена hello.exe, пути и версия toolchain здесь демонстрационные. Для реального проекта зафиксируйте свои версии, конфигурацию DUB, linker и перечень поставляемых DLL.

\n

Критерий готовности

\n

Сборка готова к следующему этапу, когда сохранённая команда завершается успешно, PE-заголовок явно указывает x64, все внешние библиотеки имеют ту же архитектуру, а release-бинарник запускается в целевой изолированной среде с ожидаемыми DLL. Рядом с артефактом должны лежать версии DMD и linker, команда сборки и вывод проверок. Если хотя бы один пункт неизвестен, результат считается непроверенным, даже если приложение запустилось на машине разработчика.

\n

Проверяемые источники

\n" + "contentHtml": "

Команда dmd -m64 main.d завершается без ошибки, но приложение не запускается на другой Windows-машине. Иногда linker сообщает о несовместимой библиотеке. Иногда Windows показывает, что DLL не найдена. Размер .exe при этом выглядит убедительно, а исходный код не менялся. Цена ошибки — несколько циклов сборки, ручное копирование DLL и отладка не того слоя.

\n

Тезис простой: 64-битный результат задаёт не только флаг -m64. Важны версия DMD, выбранный linker, архитектура объектных и библиотечных файлов, окружение командной строки и набор DLL, который увидит целевая система. Проверять нужно готовый PE-файл, а не предположение по команде сборки.

\n
\"Проверка
Граница проверки проходит от команды DMD до PE-заголовка и DLL, которые нужны готовому приложению.
\n

Что именно меняет -m64

\n

Флаг -m64 просит DMD собрать 64-битную программу. Он не превращает 32-битную внешнюю библиотеку в 64-битную. Он также не исправляет PATH, не устанавливает linker и не добавляет отсутствующую DLL. Каждый слой отвечает за свою часть результата.

\n

На старых установках DMD под Windows настройки могли лежать в sc.ini. Там указывались linker и пути к SDK. Если 64-битная секция ссылалась на старую 32-битную утилиту или на каталог библиотек другой платформы, исходники компилировались, а линковка падала. В ранних сценариях отдельно встречалась граница между OMF и COFF: объектный файл или .lib одного формата нельзя безусловно подключить к другому.

\n

Для актуального DMD под Windows 64-битные программы по умолчанию линкуются Microsoft linker, а при его отсутствии DMD может использовать поставляемый LLD. В старых конфигурациях выбор 64-битного linker задавался переменной LINKCMD64 или отдельной секцией файла настроек. Поэтому проверяйте не только наличие link.exe, но и фактическую версию DMD и используемый путь.

\n

Официальный установщик DMD выполняет базовую настройку автоматически, но это не отменяет проверки. На машине могут остаться несколько DMD, Visual Studio Build Tools могут быть установлены без нужного набора C++, а DUB может использовать другую конфигурацию, чем ручная команда. Поэтому сначала фиксируем фактические версии и пути.

\n

Минимальная проверка на учебном проекте

\n

Ниже приведён учебный пример для Windows. Он не доказывает, что любая библиотека проекта поддерживает x64. Создайте отдельный каталог с одним исходным файлом, чтобы отделить проблему toolchain от проблемы приложения.

\n
@echo off\nwhere dmd\ndmd --version\nwhere dub\ndub --version\nwhere link\nif defined LINKCMD64 echo LINKCMD64=%LINKCMD64%\n\nif not exist bin mkdir bin\ndmd -m64 -of=bin\\hello.exe source\\hello.d\nif errorlevel 1 exit /b 1\n\ndumpbin /headers bin\\hello.exe | findstr /i \"machine\"\ndumpbin /dependents bin\\hello.exe
\n

Файл source\\hello.d может содержать только import std.stdio; void main() { writeln(\"Hello, x64\"); }. Это проверяет учебный путь от DMD до исполняемого файла. В выводе /HEADERS ищите строку machine (x64) или эквивалентное обозначение архитектуры. Команда /DEPENDENTS выводит имена DLL, которые образ напрямую импортирует. Конкретный текст вывода зависит от версии Visual Studio и установленного набора инструментов.

\n

Запускайте dumpbin из Developer Command Prompt или из x64 Native Tools Command Prompt. Если команда не найдена, это проблема окружения, а не повод копировать случайный dumpbin.exe в каталог проекта. Найдите установленный набор Visual Studio и откройте его командную строку.

\n

Симптом → причина → проверка → действие

\n
СимптомПричинаПроверкаДействие
Линковка сообщает о machine type conflictОбъект или .lib собран для другой архитектурыПроверить PE-заголовки и происхождение каждого бинарного файлаПересобрать зависимость под x64 или выбрать совместимый пакет
DMD не находит ожидаемый Microsoft linkerНе настроен PATH или переменная LINKCMD64where link, dmd -v и значение LINKCMD64Открыть x64 Native Tools Command Prompt, исправить путь или проверить доступный LLD
Сборка проходит, запуск сообщает о пропавшей DLLЗависимость не установлена или не попала в поставкуdumpbin /dependents и запуск в чистой средеДобавить разрешённую DLL в поставку или убрать зависимость
Ручная правка sc.ini не помогаетИсправлен не тот раздел или используется другой DMDСверить путь из where dmd с каталогом sc.iniСначала выбрать один toolchain; затем изменить только нужную настройку
Debug работает, release нетКонфигурации используют разные linker или runtimeСравнить команды, PATH и список DLL двух сборокЗафиксировать release-окружение и проверить его отдельно
\n

Порядок действий

\n
  1. Запишите целевую платформу, версию Windows, версию DMD и способ запуска сборки.
  2. Выполните where dmd, dmd --version и, если используется DUB, dub --version. Убедитесь, что команда запускает ожидаемый toolchain.
  3. Если нужен Microsoft linker, откройте x64 Native Tools Command Prompt с Visual C++ tools. Проверьте where link и значение LINKCMD64; не смешивайте linker из одного окружения с библиотеками из другого без проверки.
  4. Соберите минимальный учебный проект командой dmd -m64. Сохраните полный вывод и код возврата.
  5. Проверьте PE-заголовок готового файла через dumpbin /headers. Не используйте размер файла как признак архитектуры.
  6. Проверьте прямые импорты DLL через dumpbin /dependents. Отдельно проверьте запуск release-бинарника в изолированной среде без случайных DLL из PATH.
  7. Если проект собирается через DUB, повторите сценарий с явным dub build --arch=x86_64 и зафиксируйте выбранные компилятор и конфигурацию.
  8. Если ошибка остаётся, заменяйте по одному слою: сначала внешний .lib, затем linker, затем конфигурацию DUB. После каждого изменения повторяйте проверку PE и зависимостей.
\n

Если проверка не проходит

\n

Не начинайте с переписывания D-кода. Сначала сохраните сообщение linker, список команд и пути, которые вывели where и dmd -v. Затем определите файл, на котором появилась ошибка. Для внешней библиотеки проверьте, кто её собрал и для какой архитектуры. Если поставщик даёт только 32-битный бинарник, флаг -m64 не решит проблему.

\n

Не копируйте DLL из каталога Windows или Visual Studio в папку приложения наугад. Такая копия может скрыть настоящую зависимость и создать другой результат на машине пользователя. Сначала выясните, какая библиотека импортируется и разрешена ли её поставка. Для системной DLL учитывайте версию Windows и установленный runtime.

\n

Если используется старая DMD, ручная правка sc.ini может быть необходима. Меняйте только секцию, соответствующую 64-битной сборке, и делайте резервную копию файла. После изменения снова выведите путь к DMD и повторите учебную сборку. Если результат не изменился, вероятно, команда читает другой sc.ini или linker берётся из PATH. Для актуальной DMD сначала проверьте, не используется ли штатный LLD: отсутствие Microsoft link.exe само по себе не доказывает неисправность toolchain.

\n

Ограничения

\n

Эта проверка устанавливает архитектуру учебного бинарника и показывает его прямые импорты. Она не гарантирует работу графического интерфейса, COM, драйверов, установщика или всех динамических загрузок через LoadLibrary. Она также не заменяет тестирование конкретных внешних библиотек и не подтверждает поддержку каждой версии Windows.

\n

Команды с dumpbin зависят от наличия Visual Studio tools. На машине без них нужен другой проверенный PE-анализатор, но критерий остаётся тем же: инструмент должен прочитать архитектуру файла и список зависимостей. Не делайте вывод о x64 по имени каталога, флагу в скрипте или размеру .exe.

\n

Учебные имена hello.exe, пути и версия toolchain здесь демонстрационные. Для реального проекта зафиксируйте свои версии, конфигурацию DUB, linker и перечень поставляемых DLL.

\n

Критерий готовности

\n

Сборка готова к следующему этапу, когда сохранённая команда завершается успешно, PE-заголовок явно указывает x64, все внешние объектные и библиотечные файлы имеют совместимую архитектуру, а release-бинарник запускается в целевой изолированной среде с ожидаемыми DLL. Рядом с артефактом должны лежать версии DMD и linker, команда сборки и вывод проверок. Если хотя бы один пункт неизвестен, результат считается непроверенным, даже если приложение запустилось на машине разработчика.

\n

Проверяемые источники

\n" }