Ya, I'm using clang-cl currently to compile for windows and I'm compiling for c99. So the #pragma function() should work with clang? Here is my current minimal compilable example along with the build file I'm using:
win64_main.c
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdbool.h>
//This is normally a part of the c runtime library so have to define it here
int _fltused = 0x9875;
bool app_running = false;
LRESULT CALLBACK win32_program_window_callback(HWND WindowHandle, UINT Message, WPARAM wParam, LPARAM lParam) {
LRESULT result = { 0 };
//For hardware rendering
HDC WindowContext = GetDC(WindowHandle);
switch (Message)
{
case WM_CREATE: {
}break;
case WM_PAINT: {
//To understand why you need a display buffer call here as well as game loop, see this post:
//https://hero.handmade.network/forums/code-discussion/t/825-wm_paint_question_beginner
PAINTSTRUCT Paint;
HDC deviceContext = BeginPaint(WindowHandle, &Paint);
EndPaint(WindowHandle, &Paint);
} break;
case WM_DESTROY: {
app_running = false;
} break;
case WM_CLOSE: {
app_running = false;
} break;
case WM_ACTIVATEAPP: {
} break;
default: {
result = DefWindowProc(WindowHandle, Message, wParam, lParam);
} break;
}
return result;
};
void win32_process_pending_messages(HWND window) {
MSG message;
while(PeekMessage(&message, 0, 0, 0, PM_REMOVE)) {
switch(message.message) {
case WM_QUIT: {
app_running = false;
}break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP: {
}break;
case WM_MOUSEWHEEL: {
int delta = GET_WHEEL_DELTA_WPARAM(message.wParam);
}break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP: {
}break;
default: {
TranslateMessage(&message);
DispatchMessageA(&message);
}break;
}
}
}
void __stdcall WinMainCRTStartup() {
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
WNDCLASS window_properties = {0};
window_properties.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; //TODO: Check if OWNDC/HREDRAW/VEDRAW matter
window_properties.lpfnWndProc = win32_program_window_callback;
window_properties.hInstance = GetModuleHandle(0);
window_properties.lpszClassName = "my_window_class";
window_properties.hCursor = LoadCursor(NULL, IDC_ARROW);
if(RegisterClass(&window_properties)) {
DWORD window_styles = WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
RECT rect = (RECT){ 0, 0, (LONG)1280, (LONG)720 };
BOOL success = AdjustWindowRectEx(&rect, window_styles, false, 0);
HWND window = CreateWindowEx(0, window_properties.lpszClassName, "My Window", WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, 0, 0, window_properties.hInstance, 0);
HDC window_context = GetDC(window);
if(window && window_context) {
app_running = true;
while(app_running) {
win32_process_pending_messages(window);
}
PostMessage(window, WM_CLOSE, 0, 0);
}
}
int result = 0;
ExitProcess(result);
}
clang build.bat file:
@echo off
REM This represents the full directory path to your batch file
set cwd=%~dp0
REM Equivalent to vcvarsall.bat
call "C:\msvc\setup.bat"
REM I believe above "call 'C:msvc\..." changes directorys so making sure to change back to current directory
cd /d %cwd%
REM -GS- tells compiler to not worry about security calls (like __security_cookie) that would typically be inserted with c libs. -Gs99999999999 basically says don't worry about __chkdsk for checking stack overruns
set compiler_flags=-Z7 -nologo -Oi -Od -Ob1 -WX -W4 -GR -EHa- -GS- -Gs999999999 -wd4505 -wd4101 -wd4530 -w14700 -wd4100 -we4820 -wd4201 -wd4189
REM -STACK:0x100000,0x100000 is setting function stack default to 1MB. Can increase this if we need to. Keep in mind though this also increases default stack size for all threads created
set linker_flags=-subsystem:windows -machine:x64 -incremental:no -nologo -opt:ref -debug -ignore:4099 -NODEFAULTLIB -STACK:0x100000,0x100000
set include_paths=-I"%cwd%source" -I"C:\msvc\Windows Kits\10\Include\10.0.22621.0\um"
set library_paths=-LIBPATH:"C:\msvc\Windows Kits\10\Lib\10.0.22621.0\um\x64"
set import_libraries="kernel32.lib" "user32.lib"
IF NOT EXIST bin mkdir bin
pushd bin
clang-cl /c ..\source\*.c %compiler_flags% %include_paths% -DBGZ_WIN64 -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -fno-builtin
lld-link *.obj -OUT:win64_main.exe %linker_flags% %library_paths% %import_libraries%
popd
With the #pragma function()
clang is saying unknown pragma ignored
which is what I expect since I think those are specific to the msvc compiler. If I remove the pragma stuff then I get an undefined memset symbol at line 99 (WNDCLASS window_properties = {0})