diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6622d972..fb01a25f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,8 +14,8 @@ on:
     - '!no-build-**'    # unless marked as no-build
 
 env:
+  GEODE_CI: ''
   CCACHE_ACTION_CI: true
-  SCCACHE_GHA_ENABLED: "on"
 
 jobs:
   build:
@@ -26,8 +26,7 @@ jobs:
         - name: Windows
           os: windows-latest
           os_identifier: win
-          cache_variant: sccache
-          extra_flags: '-T host=x86 -A win32 -DGEODE_DEBUG=On'
+          extra_flags: '-G Ninja -T host=x86 -A win32 -DGEODE_DEBUG=On'
           cli_cmd: ''
           package_cmd: 'makensis -WX -V3 ./installer/windows/installer.nsi'
           installer_path: './installer/windows/geode-installer-win.exe'
@@ -35,7 +34,6 @@ jobs:
         - name: macOS
           os: macos-latest
           os_identifier: mac
-          cache_variant: ccache
           extra_flags: '-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug -DGEODE_DEBUG=On -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13'
           cli_cmd: 'chmod +x $GITHUB_WORKSPACE/cli/geode'
           package_cmd: './installer/mac/package.sh ./bin/nightly ./installer/mac/geode-installer-mac.pkg'
@@ -52,13 +50,17 @@ jobs:
     - uses: hendrikmuhs/ccache-action@v1
       with:
         key: ${{ matrix.config.os }}
-        variant: ${{ matrix.config.cache_variant }}
 
     - uses: ilammy/msvc-dev-cmd@v1
       with:
         arch: x86
       if: matrix.config.os_identifier == 'win'
 
+    - name: Install ninja
+      shell: bash
+      run: choco install ninja
+      if: matrix.config.os_identifier == 'win'
+
     - name: Download CLI
       uses: robinraju/release-downloader@v1.8
       with:
@@ -77,12 +79,11 @@ jobs:
 
     - name: Configure CMake
       run: >
-        cmake
+        cmake -B ${{ github.workspace }}/build
         ${{ matrix.config.extra_flags }}
         -DCLI_PATH="${{ github.workspace }}/cli"
-        -DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.config.cache_variant }}
-        -DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.config.cache_variant }}
-        -B ${{ github.workspace }}/build
+        -DCMAKE_C_COMPILER_LAUNCHER=ccache
+        -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
 
     - name: Build
       run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fed7a527..7040b9b4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -105,6 +105,10 @@ target_link_libraries(GeodeFilesystemImpl PUBLIC ghc_filesystem)
 
 include(ExternalProject)
 set(GEODE_CODEGEN_BINARY_OUT ${CMAKE_CURRENT_BINARY_DIR}/codegen)
+if(DEFINED ENV{GEODE_CI})
+	message(STATUS "GEODE_CI set")
+	set(GEODE_CODEGEN_CMAKE_ARGS -G ${CMAKE_GENERATOR} -DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER} -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER})
+endif()
 ExternalProject_Add(CodegenProject
 	BUILD_ALWAYS ON
 	SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/codegen
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index a098f2b2..e34f2e36 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -220,6 +220,11 @@ elseif (WIN32)
 
 		# disable outputting .exp file
 		target_link_options(${PROJECT_NAME} PRIVATE /NOEXP)
+
+		# disable incremental link in CI builds
+		if (DEFINED ENV{GEODE_CI})
+			target_link_options(${PROJECT_NAME} PRIVATE /INCREMENTAL:NO)
+		endif()
 	endif()
 endif()
 
diff --git a/loader/launcher/windows/CMakeLists.txt b/loader/launcher/windows/CMakeLists.txt
index 4dc26411..805c4c01 100644
--- a/loader/launcher/windows/CMakeLists.txt
+++ b/loader/launcher/windows/CMakeLists.txt
@@ -46,4 +46,9 @@ if (MSVC)
 	target_link_options(fake-geode-loader PRIVATE /NOEXP /DEBUG:NONE)
 	target_link_options(ProxyLoader PRIVATE /NOIMPLIB /NOEXP /DEBUG:NONE)
 	target_link_options(Updater PRIVATE /DEBUG:NONE)
+	if (DEFINED ENV{GEODE_CI})
+		target_link_options(fake-geode-loader PRIVATE /INCREMENTAL:NO)
+		target_link_options(ProxyLoader PRIVATE /INCREMENTAL:NO)
+		target_link_options(Updater PRIVATE /INCREMENTAL:NO)
+	endif()
 endif()