GLFW-Skia C++ Template - Windows Setup Instruction
Introduction
This template is designed for use in conjunction with a WSL (Windows Subsystem for Linux) distribution running on a Windows 11 host. This section provides step-by-step instructions for setting up the native Windows build environment, including building the GLFW and Skia libraries from source.
The setup process involves:
- Building GLFW 3.4 using Visual Studio and CMake
- Building Skia graphics library with debug and release configurations
- Configuring dependencies locally within your project folder for full customization
Note: This guide focuses on the Windows-native build setup. For the companion WSL/Linux setup, see the Linux Setup Guide.
Requirements for Windows
📚 Visual Studio 2022 Community Edition (optional)
📚 Visual Studio code (optional)
📚 Python 3
📚 PowerShell
Setup Instructions
This is the Windows part of a dual-platform development environment:
- Windows Setup (This Page): Native development tools, Visual Studio, debugging
- WSL Linux Setup: Cross-platform builds and Linux testing → Linux Setup Guide
Why both? You’ll develop primarily on Windows but can build and test Linux versions seamlessly through WSL.
💫 New experimental Setup with VSC Agent
For our New experimental Setup with VSC Agent See here This will try to use the VS Co-pilot agent to install the Windows part installation. This is experimental and may be changed.
Build GLFW library for Windows
GLFW Version 3.4 has a CMake file that generates Visual Studio projects, which can be built using Visual Studio 2022/2026 Community Edition in combination with the MSBuild tools.
The dependency libraries (GLFW and Skia) are, in this project, installed within the project folder so that the entire project is self-contained in a single directory. This has the obvious disadvantage
that the libraries cannot be reused across different projects (and thus must be re-installed and customized for each project). However, the advantage is that the libraries can be fully customized for the specific needs of the current project.
You may choose to create a shared library installation, but this procedure assumes that the libraries are installed within the project in the folder: .\dependencies\win
We still believe this is the best approach, even for large libraries like Skia.
General procedure:
- Launch a PowerShell terminal in the cloned GitHub project folder.
- In your project folder, create the following folder if needed, then navigate to it: .\dependencies\win
- Download glfw-3.4.zip into the above folder (result should be: .\dependencies\win\glfw-3.4.zip, rename to this if you have a newer sub-version)
- For the next step, use a reliable extraction tool that does not skip hidden or system files and extracts the zip file in the correct location. After extraction, the files should be in the folder: .\dependencies\win\glfw-3.4\. I use the 7-Zip utility from here. When using the following command in a PowerShell CLI (in the mentioned folder), the zip will be extracted in the correct location: 7z x glfw-3.4.zip “-o.”
Build procedure (Dynamic DLL preferred / Static alternative)
The following procedure applies to both Dynamic (DLL) and Static library builds. Key differences are highlighted in the table below.
Differences between Dynamic and Static builds:
| Aspect | Dynamic (DLL) - Preferred | Static |
|---|---|---|
| Output folder | outdll | outstatic |
| CMake flag | -DBUILD_SHARED_LIBS=ON | -DBUILD_SHARED_LIBS=OFF |
| Output files | glfw3.dll + glfw3dll.lib(import lib) | glfw3.lib |
| Output location | ./outdll/src/Debug or ./outdll/src/Release | ./outstatic/src/Debug or ./outstatic/src/Release |
Build steps GLFW:
- If not yet available make the output directory (choose based on your build type):
mkdir project root\dependencies\win\glfw-3.4\outdll # For Dynamic DLL
mkdir project root\dependencies\win\glfw-3.4\outstatic # For Static
- Change to that directory
project root\dependencies\win\glfw-3.4\outdll # For Dynamic DLL
project root\dependencies\win\glfw-3.4\outstatic # For Static
- Then run with Power-Shell (choose based on your build type):
cmake .. -G "Visual Studio 17 2022" -A x64 -DBUILD_SHARED_LIBS=ON # For Dynamic DLL
cmake .. -G "Visual Studio 17 2022" -A x64 -DBUILD_SHARED_LIBS=OFF # For Static
- For Visual Studio 2026 use:
cmake .. -G "Visual Studio 18 2026" -A x64 -DBUILD_SHARED_LIBS=ON # For Dynamic DLL
cmake .. -G "Visual Studio 18 2026" -A x64 -DBUILD_SHARED_LIBS=OFF # For Static
Note 1: Initial experimental support in cmake 4.2 (dec 2025). you can use the 2022 version to generate the VS project and compile later with 2026 Note 2: By default the latest installed SDK is use if you require and other add: -DCMAKE_SYSTEM_VERSION=10.0.19041.0
- For Visual Studio 2026 use:
- Next, use PowerShell to search for msbuild.exe versions (2022 and 2026) on the system, this is because we need the full path to msbuild.exe. Use this Power-shell command:
& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` -products * ` -requires Microsoft.Component.MSBuild ` -find MSBuild\**\Bin\MSBuild.exe - Now use the Full path to msbuild.exe to create the library, In the Power-Shell CLI run:
& /path/to/msbuild GLFW.sln /p:Configuration=Debug /p:Platform=x64
Note: Update /p:Configuration=Debug to: /p:Configuration=Release for release builds
- Then copy the generated library files to the project root:
- Dynamic DLL: Copy glfw3.dll (and optionally glfw3dll.lib) from ./outdll/src/Debug or ./outdll/src/Release
- Static: Copy glfw3.lib from ./outstatic/src/Debug or ./outstatic/src/Release>
This ensures VS2022/VS2026 builds the selected library type in the appropriate src folder(i.e: src/debug), depending on the selected Solution Configuration in Visual Studio. For Dynamic DLL builds, make sure to copy the glfw3.dll file to your application executable folder at runtime.
Update CMake files
After building the GLFW library (as DLL or static) Update the ${PROJECT_SOURCE_DIR}/cmake/windows.cmake file, function: _SetExtraWindowsFolders() Make Sure to check and adjust the variables displayed below:
- Check/Set the include folder variable GLFW_WIN_INCLUDE_DIR to:
${PROJECT_SOURCE_DIR}/dependencies/win/glfw-3.4/include - In case of:
- Static linking
- Make sure the path to the library folder GLFW_WIN_LIB_DIR is set to:
${PROJECT_SOURCE_DIR}/dependencies/win/glfw-3.4/outstatic/src/debug - Make sure the variable GLFW_LIBS_WIN_LOCAL contains glfw3 the name of the .lib file (glfw3.lib)
- Make sure the path to the library folder GLFW_WIN_LIB_DIR is set to:
- Dynamic linking
- Make sure the path to the library folder:GLFW_WIN_LIB_DIR is set to
${PROJECT_SOURCE_DIR}/dependencies/win/glfw-3.4/outdll/src/debug - Make sure the variable GLFW_LIBS_WIN_LOCAL contains glfw3dll the name of the import library file (glfw3dll.lib)
- Make also sure the
.dllfile is available in your application’s runtime folder.
- Make sure the path to the library folder:GLFW_WIN_LIB_DIR is set to
- Static linking
Built Skia library
- First Build the depot_tools. depot_tools is a collection of scripts/tools used to manage large Google Git projects
- In your project folder Navigate, with your Power-Shell CLI, to the folder: .\dependencies\win or create it, if it does not exist
- Clone the git repository:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
- This creates a folder: .\dependencies\win\depot_tools add this to the system path and reopen the CLI
- Test. Execute: gclient help → should display help information and in case of the first time opening, download it!
Built dependency Ninja if needed
- Execute ninja --version When this returns a version Ninja is already build and you skip this and continue with the next section Build Skia Debug below. Make sure to use the correct dash!
- If ninja is not installed Download it form here
- Extract it in the project root under the subfolder: .\dependencies\win
You can use and existing, more central installed ninja version, in this case
- Make sure to add the installed folder with ninja.exe to your system PATH so that ninja.exe is available in your terminal(see warning below)
Path ninja must be before depot_tools
Ensure that the ninja path is defined before depot_tools in your PATH!
depot_tools includes a ninja.bat file that will break builds if used accidentally, this maya also result into vague build issues.
- Test. Open a CLI and execute:
ninja --version
Received an error?
When this command:ninja –version returns: python not found
This is because Windows is trying to run a fake python.exe from the Microsoft Store, instead of your real Python install!
✅ Fix
Rename the python.exe and python3.exe files in the following folder to .bak or something similar.
explorer “$env:LOCALAPPDATA\Microsoft\WindowsApps”
⚠️ Bonus round(when you’re extra unlucky — and you probably are): The file will be in use. Because why wouldn’t it be? Open a Power-shell in administrator mode and delete or rename the files.
Build Skia Debug
-
Check this: When you have built Skia before, especially if done in a previous project folder (i.e: ./other project/dependencies/win), check and remove the old System environment variables and paths, old system variables can impact the a new installation, so remove these:
- Environment variable: EMSDK
- Environment variable: EMSDK_NODE
- Environment variable: EMSDK_PYTHON
- Environment variable: JAVA_HOME only when points to a Skia subfolder
- Environment Path: Remove the old paths to the Skia subfolders (usual at the top)
📌Tip Use the following Powershell command to check the value of the variables: Get-ChildItem Env:EMSDK*
⚠️warning failing to do so may lead to nasty Skia build issues
- In your project folder navigate to: .\dependencies\win
- Clone Skia Execute command:
git clone --recursive https://skia.googlesource.com/skia.git
- Change cd to
project root\dependencies\win\skia
- Execute command:
git checkout chrome/m126 # To checkout a stable build instead a the master branch (Use same as on Linux!)
- The following command will call a the Skia build script which uses depot_tools to get the dependencies:
- Execute command:
python tools\git-sync-deps
- Test: It should have created tools like gn and other dependencies, test type in the CLI:
Execute command: .\bin\gn -version
- Test: It should have created tools like gn and other dependencies, test type in the CLI:
Check for errors
Check for errors like: file name too long…
If you see this, your Skia build will fail. This is one of the most common causes (together the previous warning box) of strange or hard-to-diagnose build errors on Windows, especially with Skia or other large C++ projects.
✅ Solution:
You must shorten the folder path. Try the following:
C:\libs\skia
📌 Many developers abandon deeply nested folder structures altogether for Skia and similar projects due to this issue.
- Make sure to be in the folder:
project root\dependencies\win\skia
- create folder:
mkdir out\Debug
- In the next steps we are going to Generate build files with GN (uses Ninja)
- Execute this command in powershell CLI:
@" is_debug = true is_official_build = false skia_use_gl = true target_cpu = "x64" skia_enable_fontmgr_empty = false skia_use_angle = false skia_use_icu = true extra_cflags = ["/MDd", "/D_ITERATOR_DEBUG_LEVEL=2", "/GR"] "@ | Out-File out\Debug\args.gn -Encoding ASCII
- Execute in PowerShell CLI:
.\bin\gn gen out\Debug
This configures the debug build!
Alternative Manual generate build files
This give you the option to change arguments in a file that will be opened automatically, use this if you want to configure Skia manual
- Make sure to be in the folder:
project root\dependencies\win\skia - Execute:
.\bin\gn args out\Debug - Paste the following into the editor that opens:
Editor opens past in this, and save & close the editor and gn will continue :
📌 Tip: use this command to display the valid options: gn args –list out/Debug</pre> </small>
is_debug = true is_official_build = false skia_use_gl = true target_cpu = "x64" skia_enable_fontmgr_empty = false # Optional: enable full font manager skia_use_angle = false # Optional: disable ANGLE if using native OpenGL skia_use_icu = true # ICU required for Unicode support extra_cflags = [ "/MDd", "/D_ITERATOR_DEBUG_LEVEL=2", "/GR" ] # Dynamic #extra_cflags = [ "/MTd", "/D_ITERATOR_DEBUG_LEVEL=2" ] # Static #extra_ldflags = [ "/NODEFAULTLIB:LIBCMT", "/DEFAULTLIB:LIBCMTD" ] # /# DON't add these deprecated\removed options they may cause build errrors /# skia_enable_gpu = true # IS Build ERROR!
─── ✦ ───
Activate the MS VC environmen, Not needed to call ‘vcvars64.bat’ gn can handled it self- Build it:
ninja -C out\Debug
Build result should include files like:
- out\Debug\skia.lib
- out\Debug\libskia.a
- out\Debug\obj\skia*.obj
- Update the file ${PROJECT_SOURCE_DIR}/cmake/windows.cmake (function: _SetExtraWindowsFolders())
make sure it contains:set(SKIA_WIN_CORE_INCLUDE "${PROJECT_SOURCE_DIR}/dependencies/win/skia")⚠️ Don’t add the
includefolder! This folder is part of the include directive of the Skia files - Update the file ${PROJECT_SOURCE_DIR}/cmake/windows.cmake (function: _SetExtraWindowsFolders())
make sure it contains:set(SKIA_WIN_LIBS "${PROJECT_SOURCE_DIR}/dependencies/win/skia/out/Debug"), - Ensure
skiais added to the variable: SKIA_LIBS_WIN_LOCAL in the file cmake/windows.cmake
Build Skia Release
This will create the Skia release library
Install libjpeg-turbo
- Navigate to: ./dependencies/win of the project root folder.
- Clone the git library libjpeg-turbo from here
-
git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git
- Create build directory mkdir build
- Change to the build output folder and(cd build)
- Run ‘configure’:
cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
- Build it:
cmake --build . --config Release
- Add the include and library folders manually to the Skia release build config below.
- Make sure you return to the subfolder ./dependencies/win/skia of the project root folder!
Generate build files for Skia Release
- Navigate to: ./dependencies/win/skia of the project root folder.
- create folder: mkdir build if not exists
- create folder: mkdir out\Release if not exists
- Execute this command, from skia folder in powershell CLI:
@" is_debug = false is_official_build = true skia_use_gl = true target_cpu = "x64" skia_use_system_zlib = false skia_use_system_harfbuzz = false skia_use_system_libpng = false skia_use_system_libwebp = false skia_use_expat = false skia_use_icu = false # no international text layout, no BiDi! extra_cflags = [ "/I../../../libjpeg-turbo/src", "/I../../../libjpeg-turbo/build" ] "@ | Out-File out\Release\args.gn -Encoding ASCII
- Configures the build(from skia folder):
.\bin\gn gen out\Release
This configures the Release build!
- Make sure to be in the folder: project root\dependencies\win\skia
- create the Build with:
ninja -C out\Release
This Creates the Release build!
This finalizes the build process for Windows
How to proceed, build Template project
Next you should be able to build the included template project for instructions see: The build project documentation
Appendix I - Common Pitfalls
⚠️ Common Pitfalls (Windows)
Setup your build environment in Windows is by definition more error sensitive then setting it up in Linux. Here a a few tips to help you avoid (build) issues:
- 🚫 Avoid spaces or special characters in project paths
- 🚫Make sure the official ninja.exe is first in PATH environment variable, not depot_tools\ninja.bat failing to do so will generate builds errors during build of Skia
- 🚫Make sure Skia is not to deep nested, to avoid errors related to long path names, building Skia
- 🚫 Avoid spaces or special characters in project paths:
- ✅ Use full paths in
gn.exeavoid relative path - 🔄 Always reopen the terminal after changing the environment
License
This file is part of: GLFW-Skia C++ Template Stack Copyright (c) 2025-2026 Nico Jan Eelhart.This repository is MIT licensed and free to use. For optional commercial support, customization, training, or long-term maintenance, see COMMERCIAL.md.
─── ✦ ───