Files
progcode/editorial/agent-rewrites/371.json
T
huncode 2d914b543f
Build and deploy / deploy (push) Failing after 15s
Publish rewritten technical article archive
2026-08-02 22:19:34 +03:00

8 lines
14 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"index": 371,
"slug": "компиляция-64-x-разрядных-программ-на-dmd-по",
"title": "DMD под Windows x64: как проверить архитектуру сборки и зависимости",
"excerpt": "Сборка D-программы с флагом -m64 не заканчивается на успешном сообщении компилятора. Разберём, как проверить DMD, linker, PE-заголовок и DLL, чтобы не искать ошибку в коде, когда проблема находится в toolchain.",
"contentHtml": "<p>Команда <code>dmd -m64 main.d</code> завершается без ошибки, но приложение не запускается на другой Windows-машине. Иногда linker сообщает о несовместимой библиотеке. Иногда Windows показывает, что DLL не найдена. Размер <code>.exe</code> при этом выглядит убедительно, а исходный код не менялся. Ошибка стоит времени на повторные сборки, ручное копирование DLL и отладку не того слоя.</p>\n<p>Тезис простой: 64-битный результат задаёт не только флаг <code>-m64</code>. Важны версия DMD, выбранный linker, архитектура объектных и библиотечных файлов, окружение командной строки и набор DLL, который увидит целевая система. Проверять нужно готовый PE-файл, а не предположение по команде сборки.</p>\n<figure><img src=\"/assets/illustrations/mascot-hero-2017-dmd-win64-wide-safe.png\" alt=\"Проверка сборки DMD для Windows x64\"/><figcaption>Граница проверки проходит от команды DMD до PE-заголовка и DLL, которые нужны готовому приложению.</figcaption></figure>\n<h2>Что именно меняет -m64</h2>\n<p>Флаг <code>-m64</code> просит DMD собрать 64-битную программу. Он не превращает 32-битную внешнюю библиотеку в 64-битную. Он также не исправляет PATH, не устанавливает linker и не добавляет отсутствующую DLL. Каждый слой отвечает за свою часть результата.</p>\n<p>На старых установках DMD под Windows настройки могли лежать в <code>sc.ini</code>. Там указывались linker и пути к SDK. Если 64-битная секция ссылалась на старую 32-битную утилиту или на каталог библиотек другой платформы, исходники компилировались, а линковка падала. В ранних сценариях отдельно встречалась граница между OMF и COFF: объектный файл или <code>.lib</code> одного формата нельзя безусловно подключить к другому.</p>\n<p>Современный официальный установщик обычно закрывает базовую настройку сам. Это не отменяет проверки. На машине могут остаться несколько DMD, Visual Studio Build Tools могут быть установлены без нужного набора C++, а DUB может использовать другую конфигурацию, чем ручная команда. Поэтому сначала фиксируем фактические версии и пути.</p>\n<h2>Минимальная проверка на учебном проекте</h2>\n<p>Ниже приведён учебный пример для Windows. Он не показывает production-совместимость и не доказывает, что любая библиотека проекта поддерживает x64. Создайте отдельный каталог с одним исходным файлом, чтобы отделить проблему toolchain от проблемы приложения.</p>\n<pre><code>@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</code></pre>\n<p>Файл <code>source\\hello.d</code> может содержать только <code>import std.stdio; void main() { writeln(\"Hello, x64\"); }</code>. Это проверяет учебный путь от DMD до исполняемого файла. Строка с PE-заголовком должна показывать признак x64, а <code>/DEPENDENTS</code> выводит импортируемые DLL. Конкретный текст вывода зависит от версии Visual Studio и установленного набора инструментов.</p>\n<p>Запускайте <code>dumpbin</code> из Developer Command Prompt или из x64 Native Tools Command Prompt. Если команда не найдена, это проблема окружения, а не повод копировать случайный <code>dumpbin.exe</code> в каталог проекта. Найдите установленный набор Visual Studio и откройте его командную строку.</p>\n<h2>Симптом → причина → проверка → действие</h2>\n<table><thead><tr><th>Симптом</th><th>Причина</th><th>Проверка</th><th>Действие</th></tr></thead><tbody><tr><td>Линковка сообщает о machine type conflict</td><td>Объект или <code>.lib</code> собран для другой архитектуры</td><td>Проверить PE-заголовки и происхождение каждого бинарного файла</td><td>Пересобрать зависимость под x64 или выбрать совместимый пакет</td></tr><tr><td><code>dmd</code> найден, но linker не найден</td><td>PATH указывает не на то окружение</td><td><code>where dmd</code>, версия DMD, команда linker</td><td>Открыть Developer Command Prompt и повторить проверку</td></tr><tr><td>Сборка проходит, запуск сообщает о пропавшей DLL</td><td>Зависимость не установлена или не попала в поставку</td><td><code>dumpbin /dependents</code> и запуск в чистой среде</td><td>Добавить разрешённую DLL в поставку или убрать зависимость</td></tr><tr><td>Ручная правка <code>sc.ini</code> не помогает</td><td>Исправлен не тот раздел или используется другой DMD</td><td>Сверить путь из <code>where dmd</code> с каталогом <code>sc.ini</code></td><td>Сначала выбрать один toolchain; затем изменить только нужную настройку</td></tr><tr><td>Debug работает, release нет</td><td>Конфигурации используют разные linker или runtime</td><td>Сравнить команды, PATH и список DLL двух сборок</td><td>Зафиксировать release-окружение и проверить его отдельно</td></tr></tbody></table>\n<h2>Порядок действий</h2>\n<ol><li>Запишите целевую платформу, версию Windows, версию DMD и способ запуска сборки.</li><li>Выполните <code>where dmd</code>, <code>dmd --version</code> и, если используется DUB, <code>dub --version</code>. Убедитесь, что команда запускает ожидаемый toolchain.</li><li>Откройте Developer Command Prompt с Visual C++ tools. Не смешивайте linker из одного окружения с библиотеками из другого без проверки.</li><li>Соберите минимальный учебный проект командой <code>dmd -m64</code>. Сохраните полный вывод и код возврата.</li><li>Проверьте PE-заголовок готового файла через <code>dumpbin /headers</code>. Не используйте размер файла как признак архитектуры.</li><li>Проверьте импортируемые DLL через <code>dumpbin /dependents</code>. Отдельно проверьте запуск release-бинарника в изолированной среде без случайных DLL из PATH.</li><li>Если ошибка остаётся, заменяйте по одному слою: сначала внешний <code>.lib</code>, затем linker, затем конфигурацию DUB. После каждого изменения повторяйте проверку PE и зависимостей.</li></ol>\n<h2>Если проверка не проходит</h2>\n<p>Не начинайте с переписывания D-кода. Сначала сохраните сообщение linker, список команд и пути, которые вывел <code>where</code>. Затем определите файл, на котором появилась ошибка. Для внешней библиотеки проверьте, кто её собрал и для какой архитектуры. Если поставщик даёт только 32-битный бинарник, флаг <code>-m64</code> не решит проблему.</p>\n<p>Не копируйте DLL из каталога Windows или Visual Studio в папку приложения наугад. Такая копия может скрыть настоящую зависимость и создать другой результат на машине пользователя. Сначала выясните, какая библиотека импортируется и разрешена ли её поставка. Для системной DLL учитывайте версию Windows и установленный runtime.</p>\n<p>Если используется старая DMD, ручная правка <code>sc.ini</code> может быть необходима. Меняйте только секцию, соответствующую 64-битной сборке, и делайте резервную копию файла. После изменения снова выведите путь к DMD и повторите учебную сборку. Если результат не изменился, вероятно, команда читает другой <code>sc.ini</code> или linker берётся из PATH.</p>\n<h2>Ограничения</h2>\n<p>Эта проверка устанавливает архитектуру учебного бинарника и показывает его прямые импорты. Она не гарантирует работу графического интерфейса, COM, драйверов, установщика или всех динамических загрузок через <code>LoadLibrary</code>. Она также не заменяет тестирование конкретных внешних библиотек и не подтверждает поддержку каждой версии Windows.</p>\n<p>Команды с <code>dumpbin</code> зависят от наличия Visual Studio tools. На машине без них нужен другой проверенный PE-анализатор, но критерий остаётся тем же: инструмент должен прочитать архитектуру файла и список зависимостей. Не делайте вывод о x64 по имени каталога, флагу в скрипте или размеру <code>.exe</code>.</p>\n<p>Учебные имена <code>hello.exe</code>, пути и версия toolchain здесь демонстрационные. Для реального проекта зафиксируйте свои версии, конфигурацию DUB, linker и перечень поставляемых DLL.</p>\n<h2>Критерий готовности</h2>\n<p>Сборка готова к следующему этапу, когда сохранённая команда завершается успешно, PE-заголовок явно указывает x64, все внешние библиотеки имеют ту же архитектуру, а release-бинарник запускается в целевой изолированной среде с ожидаемыми DLL. Рядом с артефактом должны лежать версии DMD и linker, команда сборки и вывод проверок. Если хотя бы один пункт неизвестен, результат считается непроверенным, даже если приложение запустилось на машине разработчика.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://dlang.org/dmd-windows.html\">DMD Compiler for Windows</a> — официальное описание установки, <code>-m64</code> и linker под Windows.</li><li><a href=\"https://learn.microsoft.com/en-us/cpp/build/reference/dumpbin-reference?view=msvc-170\">DUMPBIN Reference</a> — официальное описание анализа COFF, PE, executable и DLL.</li><li><a href=\"https://learn.microsoft.com/en-us/cpp/build/reference/dependents?view=msvc-170\">/DEPENDENTS (DUMPBIN)</a> — официальное описание вывода импортируемых DLL.</li></ul>"
}