cmake 中 gcc 的 -mwindows 选项相当于什么?

问题描述 投票:0回答:6

我正在遵循教程:

http://zetcode.com/tutorials/gtktutorial/firstprograms/

它可以工作,但每次我双击可执行文件时,都会出现一个我不想要的控制台。

我如何摆脱那个控制台?

我试过这个:

add_executable(Cmd WIN32 cmd.c)

但是遇到了这个致命错误:

MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup
Cmd.exe : fatal error LNK1120: 1 unresolved externals

直接使用 gcc 即可:

gcc -o Cmd cmd.c -mwindows ..

我猜这与入口函数有关:

int main( int argc, char *argv[])
,但是为什么gcc可以工作?

我怎样才能使它与

cmake
一起工作?

更新

为了方便起见,我将源代码粘贴到这里:

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{
  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_widget_show(window);

  gtk_main();

  return 0;
}

更新2

为什么

gcc -mwindows
有效但
add_executable(Cmd WIN32 cmd.c)
无效?

也许这与 cmake 中的

-mwindows
不等价?

c windows gtk cmake
6个回答
8
投票

add_executable(Cmd WIN32 cmd.c)

告诉 CMake 这是一个 Windows 程序,它会查找 WinMain 而不是 main。如果您想查看正在使用的标志,可以运行 make VERBOSE=1。 问题可能是如何为 gtk 应用程序定义 WinMain? 我知道使用 Qt,您可以链接到为您定义它的库中。


4
投票

虽然接受的答案适用于 MinGW,但当您未定义

WinMain
时,它不适用于 MSVC。 这是一个跨工具链的答案,因为其他人没有涵盖它。

修复子系统

add_executable(my_exe WIN32 main.c)
如果使用 MinGW 编译器,

基本上会通过

-mwindows
,如果使用 MSVC,则基本上会通过
/SUBSYSTEM:WINDOWS
。 这会将生成的可执行文件的 PE header 中的 subsystem 字段设置为
2
,即
IMAGE_SUBSYSTEM_WINDOWS_GUI
。 这指示 Windows 不为此可执行文件提供单独的控制台窗口。

修复 MSVC 上的入口点

当 MSVC 接收到

/SUBSYSTEM:WINDOWS
时,其运行时期望定义 1 一个
WinMain
,而不是
main
,这与 MinGW 的不同(它适用于任何定义的)。 如果想继续使用
main
,请修复入口点:

target_link_options(my_exe PRIVATE
  $<$<CXX_COMPILER_ID:MSVC>:/ENTRY:mainCRTStartup>
)

1:是的,操作系统首先调用 C 运行时,并且 C 运行时调用可执行文件的入口点

修复每个配置的子系统

add_executable(my_exe WIN32 ...
在内部设置可执行文件的
WIN32_EXECUTABLE
属性。 这提供了另一种更有用的方法:

add_executable(my_exe main.c)  # look ma, no WIN32!
set_target_properties(my_exe PROPERTIES WIN32_EXECUTABLE 1)

当您只想对某些配置执行此操作时,这非常有用。 我个人仅在 Release 版本上启用此功能,而在 Debug 版本上拥有控制台窗口很有用。

# No console window for non-debug builds
set_target_properties(my_exe PROPERTIES WIN32_EXECUTABLE
  $<AND:$<PLATFORM_ID:Windows>,$<NOT:$<CONFIG:Debug,RelWithDebInfo>>>
)

验证

# Generate Ninja files for GCC
cmake -B build_g -G "Ninja Multi-Config"

# Generate Visual Studio project and solution for MSVC
cmake -B build_v -G "Visual Studio 17 2022"

# Build with verbosity
cmake --build build_g --config Release -v

这应该显示实际的构建命令以及完整详细的参数。 用于验证是否为正确的构建配置传递了

-mwindows
/SUBSYSTEM:WINDOWS


3
投票

您可以将这些链接器标志设置为具有

main()
入口点并且没有控制台:

SET(CMAKE_EXE_LINKER_FLAGS 
    "${CMAKE_EXE_LINKER_FLAGS} /subsystem:windows /ENTRY:mainCRTStartup")

有关更多信息,请参阅这个答案了解链接器标志,并参阅这个答案了解如何在

cmake
中设置标志。


3
投票

对于 CMake 3.13 及更高版本,您可以使用

target_link_options(target PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")

2
投票

如果您希望程序以控制台模式运行(即

main
函数),则必须在MSVC中的项目属性中指定它。您现在使用的是窗口模式下的项目(即
WinMain
函数,您没有该函数,因此会出现错误)。

但是,如果您不想获得丑陋的控制台窗口,则需要使用窗口模式(即将您的

main
函数转换为适当的
WinMain
函数)。这样,您的普通窗口就将显示出来。

编辑:顺便说一句,你真的不应该将程序命名为“cmd”,这是 Windows 命令解释器的名称。


1
投票

根据 CMake 文档使用 WIN32 标志与 ADD_EXECUTABLE:

当此属性设置为 true 时,在 Windows 上链接时的可执行文件将使用 WinMain() 入口点创建,而不仅仅是 main()。这使其成为 GUI 可执行文件而不是控制台应用程序。请参阅 CMAKE_MFC_FLAG 变量文档来配置 WinMain 可执行文件的 MFC 使用。

但是,您的程序的入口点是

main()
而不是
WinMain()
。相反,您应该做的是省略 WIN32 标志,但您需要链接 libgtk。因此,您将使用 TARGET_LINK_LIBRARIES:

FIND_PACKAGE(GTK2 2.6 REQUIRED gtk)
INCLUDE_DIRECTORIES(${GTK2_INCLUDE_DIRS})
LINK_DIRECTORIES(${GTK2_LIBRARIES})
ADD_EXECUTABLE(myprogramname source1 source2 ... sourceN)
TARGET_LINK_LIBRARIES(myprogramname ${GTK2_LIBRARIES})
© www.soinside.com 2019 - 2024. All rights reserved.