Как установить точку входа приложения C++ в main () в Windows с помощью CMake? [дубликат]

этот вопрос уже есть ответ здесь:

недавно я начал использовать CMake и пытался создать приложение GUI, у которого нет окна консоли в Windows. Так в моем CMakeLists.txt файл, я сделал это:

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    add_executable(${EXECUTABLE_NAME} main.cpp)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
    add_executable(${EXECUTABLE_NAME} WIN32 main.cpp) #WIN32 So the console window does not open on Windows
endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")

при этом решение работало, и окно консоли не открывается в Windows. однако, это приходит на цену. Когда я пытаюсь построить решение, я понимаю, что мне нужно изменить подпись функции на WinMain, поэтому я изменил свой основной код на следующий:

#ifdef _WIN32
#include <Windows.h>
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) //Windows signature since creating WIN32 application without console
#else
int main()
#endif
{
    // ... GUI code
}

к сожалению, я абсолютно ненавижу это, так как это разрушает весь смысл через CMake. Я не хочу ничего менять в своем коде, который основан на различные платформы. Это подводит меня к моему вопросу. Как установить точку входа приложения C++ в main() в Windows при создании приложения GUI без необходимости устанавливать его вручную в Visual Studio? Могу ли я сделать это непосредственно в CMake, используя кросс-платформенный метод? Или мне придется использовать #if/#else/#endif решение? Единственным улучшением решения выше является использование макроса MAIN_FUNCTION это делает условие препроцессора. Я тоже хочу избежать этого.

С другой стороны, есть другой способ избавиться от окна консоли в GUI-приложении в Windows, о котором я не знал, используя CMake без использования опции WIN32?

2 ответов


решение состоит в том, чтобы добавить set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") до add_executable

он скрывает консоль, все еще позволяя вам иметь обычный int main() как точка входа.


вы путаете две вещи здесь, но они тесно связаны.

консоль, которая появляется является результатом приложения, которое имеет заголовок Win32 IMAGE_OPTIONAL_HEADER::Subsystem стоимостью WINDOWS_CUI вместо WINDOWS_GUI. Это вещь Win32, и она применяется ко всем исполняемым файлам независимо от языка, на котором они написаны.

подпись точки входа-это выбор конкретного компилятора. Это функция ввода, вызываемая языковой средой выполнения,не ОС. ОС звонков функция ввода языковой среды выполнения, которая сначала инициализировала эту среду выполнения, а затем передает управление вашей точке входа.

теперь компилятор VC++ использует CRT в качестве среды выполнения. И эта среда выполнения CRT действительно использует две разные подписи для вашей точки входа. Очевидно, реализация std::cin С WINDOWS_CUI, это своего рода точка пользовательского интерфейса командной строки. Но тот же CRT также работает с WINDOWS_GUI.

вот где все становится сложным. Вы действительно можете изменить Subsystem скомпилированного приложения от CUI до GUI. ЭЛТ не будет возражать, она совместима с обеими подсистемами. Но поскольку это делается для скомпилированного приложения, вызов из одной части приложения (запуск CRT) в другую (ваша точка входа) не затрагивается. Это изменение Win32, а не изменение c++.

чтобы вернуться к CMake: это изменение подсистемы может быть сделано либо после CMake, либо в качестве пользовательского шага после сборки.