在cmake中,gcc的-mwindows选项的等价物是什么?

mqkwyuun  于 2022-11-24  发布在  Windows
关注(0)|答案(6)|浏览(256)

我跟着图图:
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的等价物?

vohkndzv

vohkndzv1#

如果你想让你的程序在控制台模式下运行(比如main函数),你必须在MSVC的项目属性中指定它。你现在使用的是一个窗口模式下的项目(比如WinMain函数,你没有这个函数,所以出现了错误)。
但是如果你不想看到丑陋的控制台窗口,你可以使用窗口模式(即将main函数转换为一个合适的WinMain函数)。
编辑:顺便说一句,你真的不应该把你的程序命名为“cmd”,那是Windows命令解释器的名字。

pu82cl6c

pu82cl6c2#

根据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})
lpwwtiir

lpwwtiir3#

虽然公认的答案适用于MinGW,但当您不定义WinMain时,它不适用于MSVC。恕我直言,没有答案是跨工具链兼容的。

修复子系统

add_executable(my_exe WIN32 main.c)

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

修复MSVC上的入口点

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

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

1:是,操作系统首先调用C运行时和it's the C runtime which calls your executable's entry point

根据配置修复子系统

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是否已传递给正确的建置组态。

wxclj1h5

wxclj1h54#

添加可执行文件(命令WIN32 cmd.c)
告诉CMake这是一个Windows程序,它会查找WinMain而不是main。如果你想查看正在使用的标志,你可以运行make VERBOSE=1。问题可能是你如何为gtk应用程序定义WinMain?我知道用Qt,你链接到一个为你定义它的库中。

sd2nnvve

sd2nnvve5#

您可以将这些连接器旗标设定为具有main()进入点,但没有主控台:

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

如需详细信息,请参阅链接器旗标的此答案,以及如何在cmake中设定旗标的this answer

t30tvxxf

t30tvxxf6#

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

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

相关问题