skeeto / w64devkit

Portable C and C++ Development Kit for x64 (and x86) Windows
The Unlicense
3k stars 211 forks source link

Executables supplied with w64devkit are locking console on Windows11 #94

Open danil-kondr2016 opened 11 months ago

danil-kondr2016 commented 11 months ago

When I tried to use w64devkit on Windows 11, busybox and gcc (and maybe another executables) don't release console and only Ctrl-C make application release it. I am trying different versions of w64devkit because I think that there is a bug in the runtime. This error is reproduced on Windows 11 x64

demo

danil-kondr2016 commented 10 months ago

I tried to recompile w64devkit by myself on Debian 12 Bookworm inside Docker container. I used multibuild.sh script as following:

$ ./multibuild.sh 

It had compiled the w64devkit distribution. I have tested it on my Windows 11 and this bug don't occure. It is very strange.

I am only sure that source code is correct. There can be problems with build itself.

Spoiledpay commented 9 months ago

Given this, what would an effective compilation on the command line be like to generate a native Windows GUI?

c:\gcc -o button button.c -Wl,--subsystem,windows -lgdi32

C:\w64devkit\bin/ld.exe: C:/w64devkit/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crtexewin.o):crtexewin.c:(.text.startup+0xb1): undefined reference to `WinMain' collect2.exe: error: ld returned 1 exit status

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

#define ID_BEEP 1
#define ID_QUIT 2

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow) {

    MSG  msg;
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"Buttons";
    wc.hInstance     = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc;
    wc.hCursor       = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Buttons",
                  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                  150, 150, 300, 200, 0, 0, hInstance, 0);

    while (GetMessage(&msg, NULL, 0, 0)) {

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam) {

    switch(msg) {

        case WM_CREATE:

            CreateWindowW(L"Button", L"Beep",
                WS_VISIBLE | WS_CHILD ,
                20, 50, 80, 25, hwnd, (HMENU) ID_BEEP, NULL, NULL);

            CreateWindowW(L"Button", L"Quit",
                WS_VISIBLE | WS_CHILD ,
                120, 50, 80, 25, hwnd, (HMENU) ID_QUIT, NULL, NULL);
            break;

        case WM_COMMAND:

            if (LOWORD(wParam) == ID_BEEP) {

                MessageBeep(MB_OK);
            }

            if (LOWORD(wParam) == ID_QUIT) {

                PostQuitMessage(0);
            }

            break;

        case WM_DESTROY:

            PostQuitMessage(0);
            break;
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}
Spoiledpay commented 9 months ago

As for this one, compilation works using the following command line.

gcc -o win win.c -Wl,--subsystem,windows -lgdi32

#include<Windows.h>

int WINAPI WinMain(HINSTANCE hInstance,     //the instance of the program        
                      HINSTANCE hPrevInstance, //the previous instance 
                   LPSTR lpCmdLine,         //ptr to command line args
                   int nCmdShow)            //display properties
{
    HWND h;     
    h = CreateWindow("BUTTON",
                        "Hit me",
                        WS_OVERLAPPEDWINDOW,
                        350,300,250,100,0,0,
                         hInstance,0); //Create a window with BUTTON class

    ShowWindow(h,nCmdShow);   //show the window                                                
     MessageBox(0,"Press Me","Waiting",MB_OK); //used to display window                                                 
}
Spoiledpay commented 9 months ago

So, what can we do to create native Windows GUI apps?

Compile Windows GUI

gcc -o win win.c -Wl,--subsystem,windows -lgdi32

Compiler Window Gui Example

clang-cl.exe -o Button.obj -c Button.c -municode lld-link /subsystem:windows /out:Button.exe Button.obj user32.lib

skeeto commented 9 months ago

You're missing -municode for button.c. It defines the unicode entry point, so you need to inform GCC. Also, instead of -Wl, use -mwindows, which is a slightly "higher level" option. This command is sufficient to compile it:

cc -municode -mwindows -o button button.c

If this is a new program, it's simpler to skip the unicode macro stuff entirely. Use the narrow entry point, and GetCommandLineW if you need the command line string. Call the narrow or wide API directly, not through macros. In your case that means GetMessageW and DispatchMessageW. (The macros and TCHAR stuff are leftovers from the 16- to 32-bit transition 30 years ago, and there's no reason to use them in the 21st century.)

Since the second program doesn't use the unicode entry point:

cc -mwindows -o win win.c

In either case -lgdi32 is implicit when choosing the windows subsystem, so you don't need to list it. This program also uses some of the old 16-bit transition macros: CreateWindow instead of CreateWindowA, and MessageBox instead of MessageBoxA.