Кросс-компиляция для Windows
Создано: 12 января 2025 г.
Создано: 12 января 2025 г.
у меня есть проект на qt c++ на макбуке(сборщик cmake), обьясни мне пошагово и понятным языком как мне сделать exe файл чтобы он мог открывать в windows
Ниже описан общий подход к тому, как собрать Windows-исполняемый .exe
(приложение под Windows) из Qt/C++ проекта на macOS с использованием CMake. Сразу отмечу, что прямое «обычное» создание .exe
на Mac невозможнó без специального инструментария: необходима либо кросс-компиляция (MinGW, clang для Windows и т.д.), либо запуск сборки в среде Windows (например, в виртуальной машине, Docker-контейнере с Windows, WINE для сборки и т.д.). Самый популярный вариант – установка MinGW-w64 для macOS и настройка CMake-проекта так, чтобы использовать кросс-компилятор.
Ниже шаги по порядку:
Код и библиотеки:
Убедитесь, что ваш код не содержит специфичных для macOS функций (например, использования Objective-C++
кода) и что все внешние зависимости доступны на Windows (или есть аналоги).
Qt-модули:
Обычно Qt – кроссплатформенный фреймворк. Следите только, чтобы в CMakeLists.txt
не было модулей или флагов, которые доступны исключительно на macOS.
На macOS есть возможность поставить кросс-компилятор, который умеет собирать код под Windows. Самый популярный вариант – MinGW-w64:
bashbrew install mingw-w64
(Если Homebrew не установлен, сначала нужно установить Homebrew.)
После установки в системе будут доступны компиляторы вида:
x86_64-w64-mingw32-gcc
x86_64-w64-mingw32-g++
и т. д.Это специальный файл CMake, в котором указываются пути к кросс-компиляторам и другие параметры окружения. Назовём его, например, toolchain-mingw.cmake
.
Содержимое может выглядеть так (базовый пример):
cmake# toolchain-mingw.cmake set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) # Указываем, что будем использовать MinGW-w64 set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) # Устанавливаем флаги компиляции, если нужно: set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc")
Обратите внимание на флаги
-static-libstdc++
и-static-libgcc
. Они чаще всего нужны, чтобы «вшить» системные runtime-библиотеки (libstdc++/libgcc) прямо в.exe
. Это упрощает запуск на Windows-машине, где может не оказаться необходимых версий DLL.
Если требуется Qt, нужно убедиться, что у вас есть подходящие для Windows заголовки и библиотеки Qt (см. ниже раздел «Qt-библиотеки»).
Переходим в папку сборки (или создаём её):
bashmkdir build-windows cd build-windows
Затем вызываем CMake, указывая путь к исходникам и к файлу toolchain-mingw.cmake
:
bashcmake \ -DCMAKE_TOOLCHAIN_FILE=../path/to/toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ ../path/to/your_project
Обратите внимание, что пути (
path/to/...
) нужно заменить на реальные пути к вашему проекту и к файлуtoolchain-mingw.cmake
.
Далее запускаем сборку:
bashcmake --build . --config Release
или
bashmake -j4
(в зависимости от используемой системы сборки).
.exe
файлПосле завершения сборки в папке build-windows
(или где CMake создал папки bin
/Release
/Debug
и т.п.) вы увидите итоговый файл с расширением .exe
(например, myapp.exe
).
Если ваш проект использует Qt, то просто установить MinGW-w64 мало:
В этом случае придётся:
Qt5_DIR
или Qt6_DIR
в CMakeLists.txt
.Это достаточно сложный процесс и в небольших проектах чаще обходятся виртуальной машиной (или Docker-средой) с Windows + MinGW + Qt.
Проще всего взять машину (или виртуалку) с Windows, поставить:
Далее собрать проект классически:
powershellcmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release path\to\project mingw32-make -j4
В результате получите .exe
, готовый к запуску в Windows.
Когда у вас есть .exe
, важно убедиться, что все нужные DLL (библиотеки) лежат рядом или находятся в доступном для Windows PATH. Для Qt-приложений обычно используют windeployqt.exe
(если сборка велась в Windows), которое автоматически собирает нужные Qt-библиотеки.
Если вы сделали кросс-компиляцию и динамически ссылаетесь на Qt (или другие библиотеки), то нужно вручную положить рядом соответствующие .dll
файлы. Если использовалась статическая сборка (статические библиотеки Qt), то можно обойтись без DLL (но статическая сборка Qt обычно требует отдельной конфигурации).
cmake --build .
с нужным toolchain-файлом..exe
в папке сборки.Таким образом, вы получите .exe
, который можно будет запустить на Windows. Если проект только начинает развиваться, и нет критичной необходимости кросс-собирать на macOS, проще всего поставить Windows (на реальную машину, в виртуалку, через Boot Camp) и собирать там, используя Qt Installer (MinGW kit) или Visual Studio kit – это сильно упростит процесс.
я установил mingw, дальше я не понимаю, где нужно создать toolchain-файл и как
Ниже пошаговое объяснение, как создать и где разместить toolchain-файл для кросс-компиляции под Windows с помощью MinGW-w64 на macOS. Предположим, что вы уже установили MinGW-w64 через Homebrew (brew install mingw-w64
).
Чёткого, «обязательного» места для toolchain-файла нет. Главное — чтобы вы могли к нему обратиться из командной строки или из вашего CMakeLists.txt
. На практике есть несколько распространённых вариантов:
В корне проекта.
CMakeLists.txt
(например, toolchain-mingw.cmake
).В отдельной папке (например, cmake/toolchains
или toolchains
).
В любом другом месте, лишь бы путь был доступен при вызове cmake
.
Для начала, проще всего создать файл в корне проекта.
Откройте любой текстовый редактор (Xcode, Visual Studio Code, Sublime, nano — что удобнее).
Создайте пустой файл и сохраните его под именем, например, toolchain-mingw.cmake
.
Поместите туда примерно такой минимальный набор строк:
cmake# toolchain-mingw.cmake # Указываем, под какую "систему" мы собираем set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) # Указываем MinGW-компиляторы (пути могут отличаться в зависимости от установки) set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) # Рекомендуется статически линковать runtime-библиотеки: set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
Обратите внимание, что имена компиляторов (
x86_64-w64-mingw32-gcc
,x86_64-w64-mingw32-g++
) должны совпадать с тем, что у вас установилось через Homebrew. Если вы не уверены, можно в терминале набратьwhich x86_64-w64-mingw32-g++
и посмотреть, где лежит исполняемый файл.
Сохраните файл. Всё, ваш toolchain-файл готов.
Допустим, у вас есть стандартная структура проекта с главным CMakeLists.txt
. Чтобы собрать проект с использованием MinGW, нужно:
Создать отдельную папку для сборки (это «best practice» для CMake). Например, в корне проекта:
bashmkdir build-windows cd build-windows
Вызвать CMake, указав путь к вашему toolchain-mingw.cmake
, который мы создали:
bashcmake \ -DCMAKE_TOOLCHAIN_FILE=../toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ ../
..
(две точки) означает «вернуться в родительскую директорию», где лежит CMakeLists.txt
.toolchain-mingw.cmake
тоже в корень проекта, то путь ../toolchain-mingw.cmake
будет верным.Собрать проект:
bashcmake --build . --config Release
или
bashmake -j4
(в зависимости от того, какой генератор CMake выбрал).
Результат: в папке build-windows
(или в подпапке bin
, Release
и т.п.) вы найдёте .exe
файл.
Если ваш проект использует Qt, то:
Вам нужны библиотеки Qt под Windows (а не под macOS).
Если всё же хотите кросс-компилировать прямо на Mac (редкий сценарий):
CMakeLists.txt
..lib
/.dll
/.a
файлы.При запуске .exe
в Windows потребуется «доукомплектовать» его DLL от Qt (если вы не делали статическую сборку). Для этого в среде Windows обычно используют windeployqt.exe
.
toolchain-mingw.cmake
в удобном для вас месте (часто – в корне проекта).CMAKE_SYSTEM_NAME
, CMAKE_C_COMPILER
, CMAKE_CXX_COMPILER
и нужные флаги.cmake
с флагом -DCMAKE_TOOLCHAIN_FILE=...
и собираете проект..exe
для Windows.Если не требуется именно кросс-компиляция на Mac, то проще (и в случае Qt чаще) собирать уже под Windows (реальная система, виртуалка или Boot Camp), потому что там есть готовый установщик Qt + MinGW, и всё делается «из коробки». Но если вы хотите именно на macOS собрать под Windows — всё сводится к правильной настройке toolchain-файла и, в случае Qt, ещё и кросс-библиотек Qt.
я ввел команду which x86_64-w64-mingw32-g++ и мне выдало /opt/local/bin/x86_64-w64-mingw32-g++, что должно тогда быть написано в toolchain файле
Если утилита which x86_64-w64-mingw32-g++
показывает путь
/opt/local/bin/x86_64-w64-mingw32-g++
значит ваш кросс-компилятор лежит именно там. Соответственно, в toolchain-файле (toolchain-mingw.cmake
) нужно указывать эти пути явно. Пример минимального содержимого:
cmake# toolchain-mingw.cmake # Указываем, что собираем под Windows set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) # Пути к компиляторам (C и C++) set(CMAKE_C_COMPILER /opt/local/bin/x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER /opt/local/bin/x86_64-w64-mingw32-g++) # Рекомендуется статически линковать runtime-библиотеки # (чтобы не таскать libstdc++ и libgcc отдельно) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
Важно:
- Если у вас есть отдельный путь к
x86_64-w64-mingw32-gcc
(например,/opt/local/bin/x86_64-w64-mingw32-gcc
), пропишите его точно так же.- Если в дальнейшем CMake не найдёт нужные заголовки/библиотеки, может потребоваться дополнительно указать пути к include и lib через переменные вида
CMAKE_C_FLAGS
/CMAKE_CXX_FLAGS
или иные настройки (зависит от конкретной конфигурации MinGW и Qt, если вы используете Qt).
После создания такого toolchain-mingw.cmake
(допустим, в корне вашего проекта), вы сможете вызывать CMake так:
bashmkdir build-windows cd build-windows cmake \ -DCMAKE_TOOLCHAIN_FILE=../toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ ../ cmake --build . --config Release
В результате в папке сборки появится готовый .exe
под Windows.
я не понимаю что мне делать после создания файла toolchain, он у меня в отдельной папке, сейчас у меня в qt открыт проект, что мне делать?
Ниже — два варианта, как использовать toolchain-файл после его создания, чтобы собрать .exe
для Windows из вашего Qt/C++ проекта под macOS. Выберите тот способ, который удобнее.
Закройте Qt Creator (если открыт).
Часто проще собрать проект в терминале, чтобы убедиться, что кросс-компиляция в принципе работает.
Создайте папку для сборки (например, build-windows
), чтобы не «мусорить» в исходниках:
bashmkdir build-windows cd build-windows
Вызовите CMake, указывая:
toolchain-mingw.cmake
.CMakeLists.txt
вашего проекта.Пример (пути нужно скорректировать под ваш проект):
bashcmake \ -DCMAKE_TOOLCHAIN_FILE=/путь/к/вашему/toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ /путь/к/папке/с/исходниками
Скомпилируйте:
bashcmake --build . --config Release
или, если CMake выбрал генератор Makefiles:
bashmake -j4
Итоговый .exe
появится в папке build-windows
(или в подпапке Release
, в зависимости от конфигурации).
.exe
можно скопировать в Windows и запустить.Таким образом вы проверите, что сам процесс кросс-компиляции отлажен и работает.
Если хотите прямо в Qt Creator собирать .exe
:
Qt Creator > Preferences…
), затем вкладку Kits./opt/local/bin/x86_64-w64-mingw32-gcc
и т. п.).-DCMAKE_TOOLCHAIN_FILE=/путь/к/toolchain-mingw.cmake
в дополнительных аргументах CMake.Далее:
Qt Creator сделает то же самое, что и вариант №1 (вызовет CMake с указанным toolchain-файлом), только в графическом режиме.
Обратите внимание: если ваш проект использует Qt-библиотеки, то, чтобы скомпилировать под Windows, нужны Qt-библиотеки под Windows. На macOS обычно вы установили Qt под macOS — это не те же самые файлы, что нужны для Windows. В большинстве случаев кросс-компиляция Qt на macOS — довольно сложная история, поэтому зачастую проще собрать проект внутри реальной Windows (или виртуалки) с установленным Qt для MinGW.
Самый быстрый способ проверить, что всё работает:
build-windows
, запустите cmake -DCMAKE_TOOLCHAIN_FILE=...
, далее make
..exe
.Если нужно продолжать из Qt Creator, создайте новый «Kit», укажите в нём toolchain-файл, выберите этот Kit для сборки — и стройте из интерфейса Qt Creator.
Вот и всё: после этого ваш .exe
будет в папке сборки; его уже можно перенести на Windows и запускать там (не забыв про необходимые DLL, если нужны внешние библиотеки).
cmake
-DCMAKE_TOOLCHAIN_FILE=/Users/filippkudravcev/Desktop/cma/toolchain-mingw.cmake
-DCMAKE_BUILD_TYPE=Release
/Users/filippkudravcev/vlad_popov
я ввожу в консоль вот это все и мне выводит ошибку zsh: command not found: cmake
zsh: command not found: -DCMAKE_BUILD_TYPE=Release
Судя по сообщению zsh: command not found: cmake
, у вас не установлен (или не прописан в PATH
) cmake
. А также видно, что вторая строка воспринимается как отдельная команда из-за неправильной записи переносов. Ниже по шагам, как это исправить:
Если у вас установлен Homebrew, можно выполнить:
bashbrew install cmake
После установки введите:
bashwhich cmake
Если в ответ получаете что-то вроде /usr/local/bin/cmake
или /opt/homebrew/bin/cmake
(в зависимости от процессора и настройки Homebrew), значит CMake доступен.
Если вы используете MacPorts (похоже, вы устанавливали MinGW из MacPorts, так как компилятор лежит в /opt/local/bin
), то можно установить CMake так:
bashsudo port install cmake
Затем проверьте, что cmake
доступен командой:
bashwhich cmake
При использовании слэшей (\
) для переноса аргументов в zsh/bash важно, чтобы после слэша не было других символов и не было пропуска (пробела) до слэша. Например:
bashcmake \ -DCMAKE_TOOLCHAIN_FILE=/Users/filippkudravcev/Desktop/cma/toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ /Users/filippkudravcev/vlad_popov
Обратите внимание, что везде, где мы хотим перенести строку, строка заканчивается \
сразу, без пробелов. Такая команда отработает как одна строка.
Если удобнее, можете просто записать одной строкой:
bashcmake -DCMAKE_TOOLCHAIN_FILE=/Users/filippkudravcev/Desktop/cma/toolchain-mingw.cmake -DCMAKE_BUILD_TYPE=Release /Users/filippkudravcev/vlad_popov
Как правило, в CMake-проектах рекомендуют создавать отдельную папку под сборку. Например, сделайте так:
bashcd /Users/filippkudravcev/vlad_popov # где лежит ваш CMakeLists.txt mkdir build-windows cd build-windows
А затем уже вызывайте cmake
(и указывайте путь к исходникам «на уровень выше»):
bashcmake \ -DCMAKE_TOOLCHAIN_FILE=/Users/filippkudravcev/Desktop/cma/toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ ..
Обратите внимание на ..
(две точки) — это путь к родительской папке, где, собственно, лежит CMakeLists.txt
.
После успешной конфигурации (если CMake напишет, что всё ок), запустите сборку:
bashcmake --build . --config Release
или, если CMake выбрал Makefiles:
bashmake -j4
cmake
установлен и находится в PATH
(проверка командой which cmake
).\
без пробела после него.mkdir build-windows && cd build-windows
cmake -DCMAKE_TOOLCHAIN_FILE=... -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
Таким образом вы избежите ошибки zsh: command not found: cmake
и ошибок многострочного ввода.
сейчас после ввода этого cmake
-DCMAKE_TOOLCHAIN_FILE=/Users/filippkudravcev/Desktop/cma/toolchain-mingw.cmake
-DCMAKE_BUILD_TYPE=Release
/Users/filippkudravcev/vlad_popov
выадет это
CMake Error at CMakeLists.txt:12 (find_package):
Could not find a package configuration file provided by "QT" with any of
the following names:
textQt6Config.cmake qt6-config.cmake Qt5Config.cmake qt5-config.cmake
Add the installation prefix of "QT" to CMAKE_PREFIX_PATH or set "QT_DIR" to
a directory containing one of the above files. If "QT" provides a separate
development package or SDK, be sure it has been installed.
-- Configuring incomplete, errors occurred!
Эта ошибка означает, что при сборке проект не может найти Qt, а именно — конфигурационные файлы Qt6Config.cmake
, Qt5Config.cmake
и т.п. Причина в том, что вы пытаетесь кросс-компилировать на macOS под Windows, а у вас нет установленных Qt-библиотек именно для Windows (MinGW-версия).
Ниже разберём, почему так происходит и какие есть варианты решения.
Когда вы пишете в CMakeLists.txt
что-то вроде:
cmakefind_package(Qt6 COMPONENTS Core Widgets REQUIRED)
или
cmakefind_package(Qt5 COMPONENTS Core Widgets REQUIRED)
CMake ищет файлы конфигурации вида:
Qt6Config.cmake
(для Qt6)Qt5Config.cmake
(для Qt5)На macOS обычно стоит Qt собранный под macOS (к примеру, /Users/username/Qt/5.15.2/clang_64/
), но при кросс-компиляции вы пытаетесь «превратить» ваш код в .exe
для Windows. Поэтому нужны именно библиотеки Qt для MinGW (Windows). macOS-вариант Qt здесь не подойдёт.
Это самый надёжный и быстрый способ получить рабочий .exe
, так как не придётся самому собирать Qt под Windows на macOS.
.a
, .lib
, .dll
и т. п. для Windows, но сгенерированные на вашем Mac).И тогда CMake найдёт соответствующиеbashcmake \ -DCMAKE_TOOLCHAIN_FILE=.../toolchain-mingw.cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH=/Users/filippkudravcev/qt-for-windows-mingw \ /Users/filippkudravcev/vlad_popov
Qt5Config.cmake
или Qt6Config.cmake
именно под MinGW/Windows.Если по какой-то причине вы просто экспериментируете, и Qt под Windows не так принципиален, можно использовать другой toolkit или вообще чистый C++ (но это, скорее всего, не ваш случай).
Add the installation prefix of "QT" to CMAKE_PREFIX_PATH
?В сообщении CMake написано, что нужно добавить «установочный префикс» Qt в переменную CMAKE_PREFIX_PATH
. Иными словами, CMake должен знать, где лежат файлы Qt5Config.cmake
или Qt6Config.cmake
. Для сборки под Windows эти файлы должны быть именно из версии Qt для Windows.
Пример (на Windows или при кросс-компиляции, если Qt уже собран под MinGW):
bashcmake \ -DCMAKE_PREFIX_PATH="C:/Qt/6.5.0/mingw_64" \ ...
(или в вашем случае — путь к кросс-собранному Qt на Mac).
CMAKE_PREFIX_PATH
на «кросс-собранное» Qt,Иначе CMake просто не найдёт нужные файлы конфигурации Qt5Config.cmake
/ Qt6Config.cmake
, потому что macOS-версия Qt и Windows-версия Qt — это разные наборы файлов, которые не взаимозаменяемы.