我正在遵循教程:
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
不等价?
add_executable(Cmd WIN32 cmd.c)
告诉 CMake 这是一个 Windows 程序,它会查找 WinMain 而不是 main。如果您想查看正在使用的标志,可以运行 make VERBOSE=1。 问题可能是如何为 gtk 应用程序定义 WinMain? 我知道使用 Qt,您可以链接到为您定义它的库中。
虽然接受的答案适用于 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 接收到
/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
。
对于 CMake 3.13 及更高版本,您可以使用
target_link_options(target PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
如果您希望程序以控制台模式运行(即
main
函数),则必须在MSVC中的项目属性中指定它。您现在使用的是窗口模式下的项目(即 WinMain
函数,您没有该函数,因此会出现错误)。
但是,如果您不想获得丑陋的控制台窗口,则需要使用窗口模式(即将您的
main
函数转换为适当的 WinMain
函数)。这样,您的普通窗口就将显示出来。
编辑:顺便说一句,你真的不应该将程序命名为“cmd”,这是 Windows 命令解释器的名称。
根据 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})