From 263d6d525fc4e677d09fb5dfabb39097162a5b8e Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Thu, 10 Sep 2026 09:57:12 +0200 Subject: [PATCH] Windows build 2/2? --- .gitattributes | 3 ++ .gitignore | 1 + CMakeLists.txt | 62 ++++++++++++++++++++++++++ README.md | 108 +++++++++++++++++++++++++++++++++++++++------- build-windows.bat | 85 ++++++++++++++++++++++++++++++++++++ run-windows.bat | 17 ++++++++ 6 files changed, 260 insertions(+), 16 deletions(-) create mode 100644 .gitattributes create mode 100644 CMakeLists.txt create mode 100644 build-windows.bat create mode 100644 run-windows.bat diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..37fe55c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Keep Windows batch scripts usable when checked out on Windows. +*.bat text eol=crlf +*.cmd text eol=crlf diff --git a/.gitignore b/.gitignore index f57ee59..e5c945d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ error.log CLAUDE.md progress/ dist/ +build/ # Object files *.o diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7858848 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.16) +project(maturita C) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# GTK4 is found through pkg-config everywhere: Linux/macOS packages, MSYS2, +# vcpkg and the native MSVC (gvsbuild) package all ship .pc files. +if(MSVC) + # On MSVC the Unix-style flags pkg-config prints are not understood, so + # ask for the native "/I" and ".lib" form instead. + find_program(PKG_CONFIG_EXECUTABLE + NAMES pkg-config pkg-config.exe pkgconf pkgconf.exe) + if(NOT PKG_CONFIG_EXECUTABLE) + message(FATAL_ERROR + "pkg-config was not found. A native GTK4 install for MSVC " + "(e.g. gvsbuild) provides it; set PKG_CONFIG_PATH to " + "/lib/pkgconfig. See README.md.") + endif() + + execute_process( + COMMAND "${PKG_CONFIG_EXECUTABLE}" --cflags gtk4 --msvc-syntax + OUTPUT_VARIABLE GTK4_CFLAGS_RAW + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE GTK4_CFLAGS_RESULT) + execute_process( + COMMAND "${PKG_CONFIG_EXECUTABLE}" --libs gtk4 --msvc-syntax + OUTPUT_VARIABLE GTK4_LIBS_RAW + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE GTK4_LIBS_RESULT) + + if(NOT GTK4_CFLAGS_RESULT EQUAL 0 OR NOT GTK4_LIBS_RESULT EQUAL 0) + message(FATAL_ERROR + "pkg-config could not find GTK4. Set PKG_CONFIG_PATH to " + "/lib/pkgconfig (for example C:\\gtk\\lib\\pkgconfig).") + endif() + + separate_arguments(GTK4_CFLAGS WINDOWS_COMMAND "${GTK4_CFLAGS_RAW}") + separate_arguments(GTK4_LIBS WINDOWS_COMMAND "${GTK4_LIBS_RAW}") +else() + find_package(PkgConfig REQUIRED) + pkg_check_modules(GTK4 REQUIRED IMPORTED_TARGET gtk4) +endif() + +# WIN32 suppresses the console window on Windows; the app still uses main(), +# so MSVC needs mainCRTStartup as the entry point. +if(WIN32) + add_executable(maturita WIN32 maturita.c) +else() + add_executable(maturita maturita.c) +endif() + +if(MSVC) + target_compile_options(maturita PRIVATE ${GTK4_CFLAGS}) + target_link_options(maturita PRIVATE ${GTK4_LIBS}) + target_link_options(maturita PRIVATE /ENTRY:mainCRTStartup) + target_compile_definitions(maturita PRIVATE _CRT_SECURE_NO_WARNINGS) +else() + target_link_libraries(maturita PRIVATE PkgConfig::GTK4 m) + target_compile_options(maturita PRIVATE + -Wall -Wextra -Wno-deprecated-declarations) +endif() diff --git a/README.md b/README.md index e3b466b..966a51f 100644 --- a/README.md +++ b/README.md @@ -104,14 +104,17 @@ Linux (Arch): sudo pacman -S gtk4 ``` -Windows – GTK 4 has **no native Windows installer**. On Windows it is -distributed through [MSYS2](https://www.msys2.org/), a Unix-like build -environment that comes with its own package manager called **`pacman`**. +Windows – GTK 4 has no official installer for Windows. There are two +supported ways to get it: -`pacman` is **not** a Windows command. It only exists inside an MSYS2 -terminal, so it will not work in `cmd.exe` or PowerShell. Install MSYS2 -first, then follow the [Windows step-by-step](#windows-step-by-step) -instructions below. +- **Native (MSVC / Visual Studio) – recommended.** Download the prebuilt + [gvsbuild](https://github.com/wingtk/gvsbuild/releases/latest) GTK4 + package and unzip it. See + [Native Windows](#native-windows-visual-studio--msvc) below. +- **MSYS2 / MinGW.** Install [MSYS2](https://www.msys2.org/) and use its + `pacman` package manager. `pacman` is **not** a Windows command and only + works inside an MSYS2 terminal. See + [Windows with MSYS2](#windows-with-msys2) below. #### 2. Build tools (compiler, Make, pkg-config) @@ -143,10 +146,11 @@ sudo dnf install pkgconf-pkg-config sudo pacman -S base-devel pkgconf ``` -Windows – the MSYS2 packages installed in the step above already include -GCC, Make and pkgconf; there is nothing extra to install. Always build and -run from the **MSYS2 UCRT64** terminal so the MinGW `PATH` (and the GTK -DLLs) are available. +Windows – with the native MSVC path you only need Visual Studio with the +**Desktop development with C++** workload (this includes the compiler and +`pkg-config` comes from the GTK package). With the MSYS2 path, the packages +installed above already include GCC, Make and pkgconf; there is nothing +extra to install. ### Building the Application @@ -168,6 +172,30 @@ gcc -o maturita maturita.c `pkg-config --cflags --libs gtk4` -lm gcc -o maturita.exe maturita.c `pkg-config --cflags --libs gtk4` -lm -mwindows ``` +On Windows with Visual Studio, use the native build script or CMake +instead – see [Native Windows](#native-windows-visual-studio--msvc). + +#### Building with CMake (optional, all platforms) + +A `CMakeLists.txt` is provided for CMake/IDE users. On Linux and macOS: + +```bash +cmake -S . -B build +cmake --build build +``` + +On Windows, first add GTK to the environment (adjust `C:\gtk` if needed), +then configure from an **x64 Native Tools Command Prompt**: + +```bat +set "PATH=C:\gtk\bin;%PATH%" +set "PKG_CONFIG_PATH=C:\gtk\lib\pkgconfig" +cmake -S . -B build -G "Visual Studio 17 2022" -A x64 +cmake --build build --config Release +``` + +CMake finds GTK 4 through pkg-config on every platform. + ### Running the Application ```bash @@ -184,10 +212,55 @@ or ./maturita.exe ``` -### Windows step-by-step +### Native Windows (Visual Studio / MSVC) -There is no native Windows build of GTK, so the whole toolchain lives -inside MSYS2. From start to finish: +This is the recommended Windows path: it builds a real native `.exe` with +MSVC and needs no MSYS2 or MinGW shell. GTK 4 for MSVC comes from +[gvsbuild](https://github.com/wingtk/gvsbuild). + +1. **Install Visual Studio** (2019 or 2022) with the **Desktop + development with C++** workload. The free Community edition is enough. + +2. **Download the gvsbuild GTK4 package** from the + [latest release](https://github.com/wingtk/gvsbuild/releases/latest) – + the asset is named `GTK4_Gvsbuild__x64.zip` – and unzip it to + `C:\gtk` so that `C:\gtk\bin`, `C:\gtk\lib`, `C:\gtk\include` and + `C:\gtk\share` exist. (If you unzip it elsewhere, set the `GTK_ROOT` + environment variable to that folder before building.) + +3. **Build.** From this repository, run `build-windows.bat` from a normal + Command Prompt (or double-click it). It locates Visual Studio, sets up + the MSVC environment and the GTK paths, and produces `maturita.exe`: + + ```bat + build-windows.bat + ``` + + Internally it gathers the GTK flags with + `pkg-config --cflags gtk4 --msvc-syntax` / + `pkg-config --libs gtk4 --msvc-syntax` and compiles with: + + ```bat + cl /O2 /MD maturita.c /Fe:maturita.exe ^ + /link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup ^ + %GTK_CFLAGS% %GTK_LIBS% + ``` + +4. **Run.** `maturita.exe` needs the GTK DLLs on `PATH`, so either run it + from the same terminal or double-click `run-windows.bat`, which adds + `C:\gtk\bin` to `PATH` first. + +To build from Visual Studio itself, open the folder with CMake support (the +included `CMakeLists.txt` handles GTK), or create an empty C project and +paste the output of `pkg-config --cflags gtk4 --msvc-syntax` into +**C/C++ → Command Line → Additional Options** and the output of +`pkg-config --libs gtk4 --msvc-syntax` into +**Linker → Command Line → Additional Options**. + +### Windows with MSYS2 + +If you prefer GCC over MSVC, you can still build a native `.exe` with +MSYS2. The resulting binary is a normal Windows executable. 1. **Install MSYS2** from and complete the installer (accept the default install location). @@ -220,7 +293,7 @@ inside MSYS2. From start to finish: make run # or: ./maturita.exe ``` -#### Running the `.exe` without the MSYS2 shell +#### Bundling the MSYS2 build `maturita.exe` needs the GTK/MinGW DLLs next to it (or on `PATH`) to start, so double-clicking it from Explorer normally fails with a @@ -276,7 +349,10 @@ saved per unit to `progress/unit1.conf` / `progress/unit2.conf` / ``` maturita.c entire application (UI, navigation, themes, exercises) -Makefile build & run targets +Makefile build & run targets (Linux, macOS, MSYS2) +CMakeLists.txt optional CMake build (all platforms, incl. MSVC) +build-windows.bat native MSVC build script (no MSYS2 needed) +run-windows.bat launches maturita.exe with the GTK4 DLLs on PATH README.md this file LICENSE GPL-3.0 license progress/ created at runtime diff --git a/build-windows.bat b/build-windows.bat new file mode 100644 index 0000000..d5ed29e --- /dev/null +++ b/build-windows.bat @@ -0,0 +1,85 @@ +@echo off +setlocal + +REM --------------------------------------------------------------------------- +REM Native Windows build with MSVC. No MSYS2 or MinGW shell required. +REM +REM Requirements: +REM * Visual Studio 2019/2022 with the "Desktop development with C++" +REM workload installed. +REM * A GTK4 build for MSVC, for example the gvsbuild prebuilt package +REM unzipped to C:\gtk (see README.md). +REM +REM If GTK lives somewhere other than C:\gtk, set GTK_ROOT first, e.g. +REM set GTK_ROOT=D:\gtk +REM --------------------------------------------------------------------------- + +if not defined GTK_ROOT set "GTK_ROOT=C:\gtk" + +REM --- 1. Locate Visual Studio and enter the 64-bit MSVC environment -------- +set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +if not exist "%VSWHERE%" ( + echo [error] vswhere.exe not found. + echo Install Visual Studio with the "Desktop development with C++" + echo workload, then run this script again. + exit /b 1 +) + +set "VSPATH=" +for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VSPATH=%%i" +if not defined VSPATH ( + echo [error] No Visual Studio C++ installation found. + exit /b 1 +) + +call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" >nul +if errorlevel 1 ( + echo [error] Failed to initialise the MSVC environment. + exit /b 1 +) + +REM --- 2. Point the build at the GTK4 installation -------------------------- +set "PATH=%GTK_ROOT%\bin;%PATH%" +set "PKG_CONFIG_PATH=%GTK_ROOT%\lib\pkgconfig;%PKG_CONFIG_PATH%" + +set "PKG_CONFIG=pkg-config" +where pkg-config >nul 2>nul +if errorlevel 1 ( + where pkgconf >nul 2>nul + if errorlevel 1 ( + echo [error] pkg-config/pkgconf was not found. + echo Make sure GTK_ROOT points at a GTK4 install that contains + echo bin\pkg-config.exe. Current GTK_ROOT: %GTK_ROOT% + exit /b 1 + ) + set "PKG_CONFIG=pkgconf" +) + +REM --- 3. Collect the GTK4 flags in MSVC syntax ----------------------------- +set "GTK_CFLAGS=" +set "GTK_LIBS=" +for /f "usebackq delims=" %%c in (`%PKG_CONFIG% --cflags gtk4 --msvc-syntax`) do set "GTK_CFLAGS=%%c" +for /f "usebackq delims=" %%l in (`%PKG_CONFIG% --libs gtk4 --msvc-syntax`) do set "GTK_LIBS=%%l" + +if not defined GTK_CFLAGS ( + echo [error] pkg-config could not find gtk4. + echo Check that "%PKG_CONFIG_PATH%" contains gtk4.pc. + exit /b 1 +) + +REM --- 4. Compile ----------------------------------------------------------- +echo Building maturita.exe with MSVC... +cl /nologo /O2 /MD /W3 /std:c11 /D_CRT_SECURE_NO_WARNINGS ^ + %GTK_CFLAGS% maturita.c ^ + /Fe:maturita.exe ^ + /link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup %GTK_LIBS% + +if errorlevel 1 ( + echo [error] Build failed. + exit /b 1 +) + +echo. +echo Built maturita.exe +echo Run it from this terminal with: maturita.exe +echo Or use run-windows.bat / double-click maturita.exe. diff --git a/run-windows.bat b/run-windows.bat new file mode 100644 index 0000000..2e0b6fa --- /dev/null +++ b/run-windows.bat @@ -0,0 +1,17 @@ +@echo off +setlocal + +REM Launch a locally built maturita.exe with the GTK4 runtime on PATH, so the +REM app can be started by double-clicking even when GTK is not installed +REM system-wide. + +if not defined GTK_ROOT set "GTK_ROOT=C:\gtk" +set "PATH=%GTK_ROOT%\bin;%PATH%" + +if not exist "%~dp0maturita.exe" ( + echo [error] maturita.exe not found next to this script. + echo Build it first with build-windows.bat. + exit /b 1 +) + +start "" /D "%~dp0" "%~dp0maturita.exe"