master
txt 617 lines 25.5 KB
Raw
1 cmake_minimum_required(VERSION 3.25)
2 set(CMAKE_SYSTEM_VERSION 10.0.26100.0)
3
4 project(wsl)
5
6 # Rationalize TARGET_PLATFORM
7 # When neither CMAKE_GENERATOR_PLATFORM nor TARGET_PLATFORM is set, default to the host architecture.
8 if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "" AND "${TARGET_PLATFORM}" STREQUAL "")
9 if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "ARM64")
10 set(TARGET_PLATFORM "arm64")
11 else()
12 set(TARGET_PLATFORM "x64")
13 endif()
14 message(STATUS "No platform specified, defaulting to '${TARGET_PLATFORM}' based on host architecture.")
15 endif()
16
17 if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "arm64" OR "${TARGET_PLATFORM}" STREQUAL "arm64")
18 set(TARGET_PLATFORM "arm64")
19 elseif("${CMAKE_GENERATOR_PLATFORM}" MATCHES "x64|amd64" OR "${TARGET_PLATFORM}" MATCHES "x64|amd64")
20 set(TARGET_PLATFORM "x64")
21 else()
22 message(FATAL_ERROR "Unsupported platform: ${CMAKE_GENERATOR_PLATFORM}")
23 endif()
24
25
26 if (NOT ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} STREQUAL ${CMAKE_SYSTEM_VERSION})
27 message(FATAL_ERROR "Incorrect Windows SDK version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}, requires ${CMAKE_SYSTEM_VERSION}")
28 endif()
29
30 # Default to debug build if unspecified (pipeline always passes -DCMAKE_BUILD_TYPE=Release)
31 if(NOT CMAKE_BUILD_TYPE)
32 set(CMAKE_BUILD_TYPE "Debug")
33 endif()
34
35 # Only generate the build configuration that CMake is configured for
36 set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE STRING "" FORCE)
37
38 # Configure output directories
39 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${TARGET_PLATFORM})
40
41 # BUNDLE_ONLY mode: skip all source builds; only configure the msixbundle target and nuspec files.
42 # Used by the package pipeline stage to create the bundle from pre-built per-platform msix files.
43 option(BUNDLE_ONLY "Only configure the msixbundle target, skip all source builds" OFF)
44 if (BUNDLE_ONLY)
45 if (NOT PACKAGE_VERSION)
46 message(FATAL_ERROR "PACKAGE_VERSION is required for BUNDLE_ONLY mode")
47 endif()
48
49 if (NOT PACKAGE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
50 message(FATAL_ERROR "PACKAGE_VERSION is invalid: '${PACKAGE_VERSION}'")
51 endif()
52
53 set(PACKAGE_SIGN_COMMAND echo Skipped package signing for:)
54
55 add_subdirectory(nuget)
56 add_subdirectory(msixinstaller)
57 return()
58 endif()
59
60 include(FetchContent)
61
62 # Import GSL and nlohmannjson
63
64 set(FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps/${TARGET_PLATFORM})
65
66 # N.B. Changes to any of the FetchContent dependencies below (GSL, nlohmannjson) must be reflected in cgmanifest.json
67
68 FetchContent_Declare(GSL
69 URL https://github.com/microsoft/GSL/archive/refs/tags/v4.0.0.tar.gz
70 URL_HASH SHA256=f0e32cb10654fea91ad56bde89170d78cfbf4363ee0b01d8f097de2ba49f6ce9)
71
72 FetchContent_MakeAvailable(GSL)
73 FetchContent_GetProperties(GSL SOURCE_DIR GSL_SOURCE_DIR)
74
75
76 FetchContent_Declare(nlohmannjson
77 URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
78 URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa )
79
80 FetchContent_MakeAvailable(nlohmannjson)
81 FetchContent_GetProperties(nlohmannjson SOURCE_DIR NLOHMAN_JSON_SOURCE_DIR)
82
83 FetchContent_Declare(yaml-cpp
84 URL https://github.com/jbeder/yaml-cpp/releases/download/yaml-cpp-0.9.0/yaml-cpp-yaml-cpp-0.9.0.tar.gz
85 URL_HASH SHA256=298593d9c440fd9034b8b193d96318b76d49bc97c6ceadb7b0836edf0b6d7539)
86
87 set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
88 set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
89 set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "" FORCE)
90 set(YAML_MSVC_SHARED_RT OFF CACHE BOOL "" FORCE)
91 set(BUILD_TESTING OFF CACHE BOOL "" FORCE) # Prevents yaml-cpp from generating CTest* targets
92
93 FetchContent_MakeAvailable(yaml-cpp)
94
95 set(BOOST_VERSION "1.90.0")
96 set(BOOST_TARBALL "boost_${BOOST_VERSION}")
97 string(REPLACE "." "_" BOOST_TARBALL "${BOOST_TARBALL}")
98
99 FetchContent_Declare(
100 boost_headers
101 URL https://archives.boost.io/release/${BOOST_VERSION}/source/${BOOST_TARBALL}.tar.gz
102 URL_HASH SHA256=5e93d582aff26868d581a52ae78c7d8edf3f3064742c6e77901a1f18a437eea9
103 )
104
105 FetchContent_MakeAvailable(boost_headers)
106
107
108 # Import modules
109 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
110 find_package(IDL REQUIRED)
111 find_package(LINUXBUILD REQUIRED)
112 find_package(NUGET REQUIRED)
113 find_package(VERSION REQUIRED)
114 find_package(MC REQUIRED)
115 find_package(Appx REQUIRED)
116 find_package(CSharp REQUIRED)
117
118 # Download nuget packages
119 restore_nuget_packages()
120
121 # Load nuget packages versions and paths
122 parse_nuget_packages_versions()
123
124 find_nuget_package(Microsoft.Direct3D.Linux DIRECT3D /build/native)
125 find_nuget_package(Microsoft.Identity.MSAL.WSL.Proxy MSAL /build/native/bin)
126 find_nuget_package(Microsoft.RemoteDesktop.Client.MSRDC.SessionHost MSRDC /build/native/bin)
127 find_nuget_package(Microsoft.Taef TAEF /)
128 find_nuget_package(Microsoft.Windows.ImplementationLibrary WIL /)
129 find_nuget_package(Microsoft.WSL.Kernel KERNEL /build/native)
130 find_nuget_package(Microsoft.WSL.bsdtar BSDTARD /build/native/bin)
131 find_nuget_package(Microsoft.WSL.LinuxSdk LINUXSDK /)
132 find_nuget_package(Microsoft.WSL.TestDistro TEST_DISTRO /)
133 find_nuget_package(Microsoft.WSL.TestData WSL_TEST_DATA /)
134 find_nuget_package(Microsoft.WSLg WSLG /build/native/bin)
135 find_nuget_package(vswhere VSWHERE /tools)
136 find_nuget_package(Wix WIX /tools/net6.0/any)
137
138 # Architecture-specific nuget packages from the OS repo.
139 if (${TARGET_PLATFORM} STREQUAL "x64")
140 find_nuget_package(Microsoft.DXCore.Linux.amd64fre DXCORE /build/native)
141 find_nuget_package(Microsoft.WSL.Dependencies.amd64fre WSLDEPS /build/native)
142 endif()
143
144 if (${TARGET_PLATFORM} STREQUAL "arm64")
145 find_nuget_package(Microsoft.DXCore.Linux.arm64fre DXCORE /build/native)
146 find_nuget_package(Microsoft.WSL.Dependencies.arm64fre WSLDEPS /build/native)
147 endif()
148
149 # Wsl Settings packages
150 find_nuget_package(CommunityToolkit.Mvvm CTK_MVVM /)
151 find_nuget_package(CommunityToolkit.WinUI.Animations CTK_ANIMATIONS /)
152 find_nuget_package(CommunityToolkit.WinUI.Controls.SettingsControls CTK_STTNGS_CTRLS /)
153 find_nuget_package(Microsoft.Extensions.Hosting EXTS_HOSTING /)
154 find_nuget_package(Microsoft.NETCore.App.Runtime.win-${TARGET_PLATFORM} DOTNET_RUNTIME /)
155 find_nuget_package(Microsoft.WindowsAppSDK WIN_APP_SDK /)
156 find_nuget_package(Microsoft.Windows.SDK.NET.Ref WINDOWS_SDK_DOTNET /)
157 find_nuget_package(Microsoft.Xaml.Behaviors.WinUI.Managed XAML_BEHAVIORS /)
158 find_nuget_package(WinUIEx WINUIEX /)
159
160 # WSLC C# API packages
161 find_nuget_package(Microsoft.Windows.CsWinRT CSWINRT /)
162
163 set(WSLG_TS_PLUGIN_DLL "WSLDVCPlugin.dll")
164
165 set(SUPPORTED_LANGS cs-CZ;da-DK;de-DE;en-GB;en-US;es-ES;fi-FI;fr-FR;hu-HU;it-IT;ja-JP;ko-KR;nb-NO;nl-NL;pl-PL;pt-BR;pt-PT;ru-RU;sv-SE;tr-TR;zh-CN;zh-TW)
166
167 if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/UserConfig.cmake")
168 find_package(USER REQUIRED PATHS ${CMAKE_CURRENT_LIST_DIR})
169 endif()
170
171 if (WSL_DEVICEHOST_BIN)
172 set(WSL_VIRTIO_NET_IDL_PATH "${WSL_DEVICEHOST_BIN}/WslDeviceHost.idl")
173 set(WSL_DEVICE_HOST_DLL_PATH "${WSL_DEVICEHOST_BIN}/wsldevicehost.dll")
174 set(WSL_DEVICE_HOST_VERSION "9.0.0-localbuild")
175 else()
176 find_nuget_package(Microsoft.WSL.DeviceHost WSL_DEVICE_HOST /build/native)
177 set(WSL_VIRTIO_NET_IDL_PATH "${WSL_DEVICE_HOST_SOURCE_DIR}/idl/WslDeviceHost.idl")
178 set(WSL_DEVICE_HOST_DLL_PATH "${WSL_DEVICE_HOST_SOURCE_DIR}/bin/${TARGET_PLATFORM}/wsldevicehost.dll")
179 endif()
180
181 # Optional target configuration
182
183 if (NOT DEFINED WSL_BUILD_WSL_SETTINGS)
184 set(WSL_BUILD_WSL_SETTINGS false)
185 endif ()
186
187 if (NOT DEFINED WSL_INCLUDE_SDK_CSHARP)
188 set(WSL_INCLUDE_SDK_CSHARP false)
189 endif ()
190
191 # Number of sources combined into each unity translation unit.
192 # Set to 0 to compile every file separately.
193 set(WSL_UNITY_BATCH_SIZE_DEFAULT 0)
194
195 if (NOT DEFINED WSL_UNITY_BATCH_SIZE)
196 set(WSL_UNITY_BATCH_SIZE ${WSL_UNITY_BATCH_SIZE_DEFAULT})
197 endif ()
198
199 if (NOT WSL_UNITY_BATCH_SIZE MATCHES "^[0-9]+$")
200 message(FATAL_ERROR "WSL_UNITY_BATCH_SIZE must be a non-negative integer: got '${WSL_UNITY_BATCH_SIZE}'")
201 endif ()
202
203 # Applies to every target created below. Targets that can't be unified opt out
204 # individually with UNITY_BUILD OFF.
205 # N.B. This is set after the FetchContent dependencies are made available so that
206 # third party targets keep building file by file.
207 if (WSL_UNITY_BATCH_SIZE GREATER 0)
208 set(CMAKE_UNITY_BUILD ON)
209 set(CMAKE_UNITY_BUILD_MODE BATCH)
210 set(CMAKE_UNITY_BUILD_BATCH_SIZE ${WSL_UNITY_BATCH_SIZE})
211 message(STATUS "Unity build enabled with a batch size of ${WSL_UNITY_BATCH_SIZE}")
212 endif ()
213 find_commit_hash(COMMIT_HASH)
214
215 if (NOT PACKAGE_VERSION)
216 find_version(PACKAGE_VERSION WSL_NUGET_PACKAGE_VERSION) # Fetch the package version from git if not specified
217 endif ()
218
219 if (NOT PACKAGE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
220 message(FATAL_ERROR "PACKAGE_VERSION must be four dot-separated numeric components (e.g., '1.2.3.4'): got '${PACKAGE_VERSION}'")
221 endif()
222
223 set(PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
224 set(PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
225 set(PACKAGE_VERSION_REVISION ${CMAKE_MATCH_3})
226
227 # The store requires the revision number to be 0, so enforce this on official builds
228 if (OFFICIAL_BUILD AND NOT PACKAGE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.0$")
229 message(FATAL_ERROR "PACKAGE_VERSION is invalid: '${PACKAGE_VERSION}'. Needs to match '([0-9]+).([0-9]+).([0-9]+).0' for official builds")
230 endif()
231
232 if (${TARGET_PLATFORM} STREQUAL "x64")
233 set(DCAT_PRODUCT_NAME WSL.amd64)
234 endif()
235
236 if (${TARGET_PLATFORM} STREQUAL "arm64")
237 set(DCAT_PRODUCT_NAME WSL.arm64)
238 endif()
239
240 set(DCAT_REGISTRATION_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Update\\TargetingInfo\\DynamicInstalled\\${DCAT_PRODUCT_NAME}")
241
242 # Configure output directories
243 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${TARGET_PLATFORM})
244 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug)
245 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release)
246 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
247
248 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
249
250 # Packaging variables
251 set(BIN ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE})
252 file(MAKE_DIRECTORY ${BIN})
253
254 set (GENERATED_DIR ${CMAKE_BINARY_DIR}/generated)
255 file(MAKE_DIRECTORY ${GENERATED_DIR})
256
257 # Generate Source Link JSON so debuggers can fetch source from GitHub (pipeline builds only)
258 if (DEFINED PIPELINE_BUILD_ID)
259 set(SOURCELINK_JSON "${GENERATED_DIR}/sourcelink.json")
260 file(WRITE "${SOURCELINK_JSON}" "{\"documents\":{\"${CMAKE_SOURCE_DIR}/*\":\"https://raw.githubusercontent.com/microsoft/WSL/${COMMIT_HASH}/*\"}}")
261 endif()
262
263 set(PACKAGE_CERTIFICATE ${GENERATED_DIR}/dev-cert.pfx)
264
265 # Link the third-party binaries we ship (and their PDBs) into bin so packaging
266 # and the pipeline's symbol publishing step find them. Without the PDBs here,
267 # Watson can't resolve function names in their crash frames.
268 string(REPLACE ".dll" ".pdb" WSLG_TS_PLUGIN_PDB ${WSLG_TS_PLUGIN_DLL})
269 file(CREATE_LINK ${WSLG_SOURCE_DIR}/${TARGET_PLATFORM}/${WSLG_TS_PLUGIN_DLL} ${BIN}/${WSLG_TS_PLUGIN_DLL})
270 file(CREATE_LINK ${WSLG_SOURCE_DIR}/${TARGET_PLATFORM}/${WSLG_TS_PLUGIN_PDB} ${BIN}/${WSLG_TS_PLUGIN_PDB})
271 file(CREATE_LINK ${WSLDEPS_SOURCE_DIR}/bin/wsldeps.dll ${BIN}/wsldeps.dll)
272 file(CREATE_LINK ${WSLDEPS_SOURCE_DIR}/bin/wsldeps.pdb ${BIN}/wsldeps.pdb)
273 # wsldevicehost.dll is packaged directly from its NuGet package, so only its PDB
274 # needs linking into bin for symbol publishing.
275 if (NOT WSL_DEVICEHOST_BIN)
276 file(CREATE_LINK ${WSL_DEVICE_HOST_SOURCE_DIR}/bin/${TARGET_PLATFORM}/wsldevicehost.pdb ${BIN}/wsldevicehost.pdb)
277 endif()
278
279 if (${SKIP_PACKAGE_SIGNING})
280 set(PACKAGE_SIGN_COMMAND echo Skipped package signing for:)
281 else()
282 if (NOT EXISTS ${PACKAGE_CERTIFICATE})
283 execute_process(
284 COMMAND powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File "${CMAKE_CURRENT_LIST_DIR}/tools/create-dev-cert.ps1" -OutputPath "${PACKAGE_CERTIFICATE}"
285 COMMAND_ERROR_IS_FATAL ANY)
286 endif()
287
288 set(PACKAGE_SIGN_COMMAND SignTool.exe sign /a /v /fd SHA256 /f ${PACKAGE_CERTIFICATE})
289 endif()
290
291
292 # Generate local test script
293 configure_file(${CMAKE_CURRENT_LIST_DIR}/tools/test/test.bat.in ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/test.bat)
294
295 # Common build flags
296 set(CMAKE_CXX_STANDARD 20)
297
298 if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
299 set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
300 else()
301 set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
302 endif()
303
304 if (${TARGET_PLATFORM} STREQUAL "x64")
305 add_compile_definitions(_AMD64_)
306 set(DISTRO_HOSTTYPE x86_64)
307 endif()
308
309 if (${TARGET_PLATFORM} STREQUAL "arm64")
310 add_compile_definitions(_ARM64_)
311 set(DISTRO_HOSTTYPE aarch64)
312 endif()
313
314 add_definitions(/sdl) # Default-initialize class members
315 add_definitions(/FS) # Enable parallel PDB access
316 add_compile_definitions(UNICODE
317 WIL_SUPPRESS_PRIVATE_API_USE
318 CPPWINRT_SUPPRESS_STATIC_INITIALIZERS
319 NOMINMAX
320 _CRT_SECURE_NO_WARNINGS
321 KERNEL_VERSION="${KERNEL_VERSION}"
322 WSLDEPS_VERSION="${WSLDEPS_VERSION}"
323 WSLG_VERSION="${WSLG_VERSION}"
324 WSLG_TS_PLUGIN_DLL=L"${WSLG_TS_PLUGIN_DLL}"
325 WSL_DEVICE_HOST_VERSION="${WSL_DEVICE_HOST_VERSION}"
326 COMMIT_HASH="${COMMIT_HASH}"
327 WSL_PACKAGE_VERSION="${PACKAGE_VERSION}"
328 MSRDC_VERSION="${MSRDC_VERSION}"
329 DIRECT3D_VERSION="${DIRECT3D_VERSION}"
330 DXCORE_VERSION="${DXCORE_VERSION}"
331 WSL_PACKAGE_VERSION_MAJOR=${PACKAGE_VERSION_MAJOR}
332 WSL_PACKAGE_VERSION_MINOR=${PACKAGE_VERSION_MINOR}
333 WSL_PACKAGE_VERSION_REVISION=${PACKAGE_VERSION_REVISION}
334 DISTRO_HOSTTYPE="${DISTRO_HOSTTYPE}"
335 WSL_BUILD_WSL_SETTINGS=${WSL_BUILD_WSL_SETTINGS}
336 DCAT_PRODUCT_NAME=R"\(${DCAT_PRODUCT_NAME}\)"
337 DCAT_REGISTRATION_KEY=R"\(${DCAT_REGISTRATION_KEY}\)")
338
339 if (${OFFICIAL_BUILD})
340 add_compile_definitions(WSL_OFFICIAL_BUILD)
341 endif()
342
343 if (${WSL_BUILD_THIN_PACKAGE})
344 add_compile_definitions(WSL_DEV_THIN_MSI_PACKAGE="${BIN}/wsl.msi")
345 endif ()
346
347 string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) # make sure /Zi is removed from the debug flags
348 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /W3 /WX /ZH:SHA_256")
349 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Z7 -DDEBUG -DDBG")
350 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi /guard:cf /Qspectre")
351
352 # Linker flags
353 set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /debug:full /debugtype:cv,fixup /guard:cf /DYNAMICBASE")
354 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /debug:full /debugtype:cv,fixup /guard:cf /DYNAMICBASE")
355 if (DEFINED SOURCELINK_JSON)
356 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SOURCELINK:\"${SOURCELINK_JSON}\"")
357 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SOURCELINK:\"${SOURCELINK_JSON}\"")
358 endif()
359 if (${TARGET_PLATFORM} STREQUAL "x64")
360 set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /CETCOMPAT")
361 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /CETCOMPAT")
362 endif()
363
364 # Hybrid CRT: static-link the C++ runtime and STL (/MT|/MTd from CMAKE_MSVC_RUNTIME_LIBRARY),
365 # but dynamic-link the Universal CRT (ucrt.dll) which is an OS component on Windows 10+.
366 # This eliminates the VCRUNTIME/MSVCP redistributable dependency while avoiding the size
367 # cost of statically linking the UCRT. See https://aka.ms/hybridcrt for details.
368 set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libucrt.lib /defaultlib:ucrt.lib")
369 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libucrt.lib /defaultlib:ucrt.lib")
370 set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libucrtd.lib /defaultlib:ucrtd.lib")
371 set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libucrtd.lib /defaultlib:ucrtd.lib")
372
373 # Common link libraries
374 link_directories(${WSLDEPS_SOURCE_DIR}/lib/)
375 set(COMMON_LINK_LIBRARIES
376 ws2_32.lib
377 Userenv.lib
378 RuntimeObject.lib
379 Pathcch.lib
380 ntdll.lib
381 RpcRT4.lib
382 Mswsock.lib
383 Shlwapi.lib
384 synchronization.lib
385 Bcrypt.lib
386 Crypt32.lib
387 icu.lib)
388
389 set(MSI_LINK_LIBRARIES
390 Wintrust.lib
391 msi.lib)
392
393 set(HCS_LINK_LIBRARIES
394 computecore.lib
395 computenetwork.lib
396 Iphlpapi.lib)
397
398 set(SERVICE_LINK_LIBRARIES
399 MI.lib
400 wsldeps.lib)
401
402 # Linux
403 if(${TARGET_PLATFORM} STREQUAL "" OR ${TARGET_PLATFORM} STREQUAL "x64")
404 set(LLVM_ARCH x86_64)
405 elseif(${TARGET_PLATFORM} STREQUAL "arm64")
406 set(LLVM_ARCH aarch64)
407 else()
408 message(FATAL_ERROR "Unsupported platform: '${TARGET_PLATFORM}'")
409 endif()
410
411 # Determine the Visual Studio installation directory which contains LLVM tools.
412 # Supported versions: VS2022 and VS2026.
413 # Prefer VS2022 to keep local clang-format output aligned with pipeline expectations.
414 function(find_vs_install_dir VERSION_RANGE OUTPUT_VAR)
415 execute_process(
416 COMMAND "${VSWHERE_SOURCE_DIR}/vswhere.exe" -version "${VERSION_RANGE}" -products * -requires Microsoft.VisualStudio.Component.VC.Llvm.Clang -property installationPath -prerelease -latest
417 OUTPUT_VARIABLE _vs_install_dir
418 OUTPUT_STRIP_TRAILING_WHITESPACE
419 COMMAND_ERROR_IS_FATAL ANY
420 )
421
422 set(${OUTPUT_VAR} "${_vs_install_dir}" PARENT_SCOPE)
423 endfunction()
424
425 find_vs_install_dir("[17.0,18.0)" VS_INSTALL_DIR)
426
427 if (NOT VS_INSTALL_DIR)
428 find_vs_install_dir("[18.0,19.0)" VS_INSTALL_DIR)
429 if (VS_INSTALL_DIR)
430 message(WARNING "Visual Studio 2022 was not found; using Visual Studio 2026 instead. clang-format output may differ from pipeline expectations.")
431 endif()
432 endif()
433
434 if (NOT VS_INSTALL_DIR)
435 message(FATAL_ERROR "Could not determine Visual Studio installation directory.")
436 endif()
437
438 # Pick the first line returned from vswhere, in case multiple versions are returned.
439 # TODO: Remove this and require VS 2026 once the CI supports it.
440 string(REGEX MATCH "([^\n\r]+)" VS_INSTALL_DIR "${VS_INSTALL_DIR}")
441
442 if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
443 set(LLVM_INSTALL_DIR "${VS_INSTALL_DIR}/VC/Tools/Llvm/x64/bin")
444 else()
445 set(LLVM_INSTALL_DIR "${VS_INSTALL_DIR}/VC/Tools/Llvm/${CMAKE_HOST_SYSTEM_PROCESSOR}/bin")
446 endif()
447
448 if (NOT EXISTS ${LLVM_INSTALL_DIR})
449 message(FATAL_ERROR "C++ Clang Compiler for Windows is not installed at ${LLVM_INSTALL_DIR}. Please install it from the Visual Studio Installer.")
450 endif()
451
452 # Generate the clang-format script which contains a path to clang-format.exe
453 configure_file(${CMAKE_CURRENT_LIST_DIR}/tools/FormatSource.ps1.in ${CMAKE_BINARY_DIR}/FormatSource.ps1)
454
455 # Pre-commit hook mode: warn (default), error, or fix
456 set(WSL_PRE_COMMIT_MODE "warn" CACHE STRING "Pre-commit hook behavior: warn, error, or fix")
457
458 # Generate the pre-commit hook into the build tree
459 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tools/hooks)
460 configure_file(${CMAKE_CURRENT_LIST_DIR}/tools/hooks/pre-commit.in ${CMAKE_BINARY_DIR}/tools/hooks/pre-commit @ONLY)
461
462 set(LINUXSDK_PATH ${LINUXSDK_SOURCE_DIR}/${LLVM_ARCH})
463 set(LLVM_TARGET "${LLVM_ARCH}-unknown-linux-musl")
464 set(LINUX_CC ${LLVM_INSTALL_DIR}/clang.exe)
465 set(LINUX_CXX ${LLVM_INSTALL_DIR}/clang++.exe)
466 set(LINUX_AR ${LLVM_INSTALL_DIR}/llvm-ar.exe)
467 set(LINUX_COMMON_FLAGS --gcc-toolchain=${LINUXSDK_PATH}
468 -fpic
469 -B${LINUXSDK_PATH}
470 -isysroot ${LINUXSDK_PATH}
471 -isystem ${LINUXSDK_PATH}/include/c++/v1
472 -isystem ${LINUXSDK_PATH}/include
473 -isystem ${GSL_SOURCE_DIR}/include
474 -isystem "${WSLDEPS_SOURCE_DIR}/include/lxcore"
475 -isystem "${WSLDEPS_SOURCE_DIR}/include/schemas"
476 -I "${CMAKE_CURRENT_LIST_DIR}/src/linux/inc"
477 -I "${CMAKE_CURRENT_LIST_DIR}/src/linux/mountutil"
478 -I "${CMAKE_CURRENT_LIST_DIR}/src/linux/plan9"
479 -I "${CMAKE_CURRENT_LIST_DIR}/src/shared/configfile"
480 -I "${CMAKE_CURRENT_LIST_DIR}/src/shared/inc"
481 -I "${NLOHMAN_JSON_SOURCE_DIR}/include"
482 -I "${CMAKE_BINARY_DIR}/generated"
483 --no-standard-libraries
484 -Werror
485 -Wall
486 -Wpointer-arith
487 -D_POSIX_C_SOURCE=200809L
488 -Dswprintf_s=swprintf
489 -fms-extensions
490 -target ${LLVM_TARGET}
491 -D_GNU_SOURCE=1
492 -D_LARGEFILE64_SOURCE
493 -DWSL_PACKAGE_VERSION="${PACKAGE_VERSION}"
494 -DWSL_PACKAGE_VERSION_MAJOR=${PACKAGE_VERSION_MAJOR}
495 -DWSL_PACKAGE_VERSION_MINOR=${PACKAGE_VERSION_MINOR}
496 -DWSL_PACKAGE_VERSION_REVISION=${PACKAGE_VERSION_REVISION}
497 )
498
499 if (${TARGET_PLATFORM} STREQUAL "x64")
500 set(LINUX_COMMON_FLAGS ${LINUX_COMMON_FLAGS} -D_AMD64_)
501 endif()
502
503 if (${TARGET_PLATFORM} STREQUAL "arm64")
504 set(LINUX_COMMON_FLAGS ${LINUX_COMMON_FLAGS} -D_ARM64_)
505 endif()
506
507 set(LINUX_CXXFLAGS ${LINUX_COMMON_FLAGS} -std=c++20)
508 set(LINUX_CFLAGS ${LINUX_COMMON_FLAGS} -std=c99)
509
510 string(TOLOWER ${CMAKE_BUILD_TYPE} build_type)
511 if (build_type STREQUAL debug)
512 set(LINUX_BUILD_TYPE_FLAGS -g3 -fno-inline-functions -DDEBUG -DDBG)
513 else()
514 set(LINUX_BUILD_TYPE_FLAGS -g -O2 -DNDEBUG)
515 endif()
516
517 set(LINUX_LDFLAGS -target ${LLVM_TARGET}
518 --gcc-toolchain=${LINUXSDK_PATH}
519 -B${LINUXSDK_PATH}
520 -isysroot ${LINUXSDK_PATH}
521 -nostartfiles
522 --no-standard-libraries
523 -fuse-ld=lld.exe
524 -L${LINUXSDK_PATH}/lib
525 -L${LINUXSDK_PATH}/lib/linux
526 -L${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}
527 -lclang_rt.builtins-${LLVM_ARCH}
528 -l:libc.a
529 -static)
530
531 set(COMMON_LINUX_LINK_LIBRARIES configfile)
532 file(GLOB COMMON_LINUX_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/src/shared/inc/*.h")
533
534 if(DEFINED ENV{WSL_DEV_BINARY_PATH})
535 set(WSL_DEV_BINARY_PATH $ENV{WSL_DEV_BINARY_PATH})
536 endif()
537
538 if (DEFINED WSL_DEV_BINARY_PATH) # Development shortcut to make the package smaller
539 add_compile_definitions(WSL_SYSTEM_DISTRO_PATH="${WSL_DEV_BINARY_PATH}/system.vhd"
540 WSL_KERNEL_PATH="${WSL_DEV_BINARY_PATH}/kernel"
541 WSL_KERNEL_MODULES_PATH="${WSL_DEV_BINARY_PATH}/artifacts.vhd"
542 WSL_DEV_INSTALL_PATH="${WSL_DEV_BINARY_PATH}"
543 WSL_GPU_LIB_PATH="${WSL_DEV_BINARY_PATH}/lib")
544 endif()
545
546 # Common include paths
547 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/wil/include)
548 include_directories(${boost_headers_SOURCE_DIR})
549 include_directories(${WSLDEPS_SOURCE_DIR}/include)
550 include_directories(${WSLDEPS_SOURCE_DIR}/include/Windows)
551 include_directories(${WSLDEPS_SOURCE_DIR}/include/schemas)
552 include_directories(${WSLDEPS_SOURCE_DIR}/include/lxcore)
553 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/shared/inc)
554 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/windows/inc)
555 include_directories(${CMAKE_CURRENT_BINARY_DIR}/src/windows/wsldevicehoststub/inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE})
556 include_directories(${CMAKE_CURRENT_BINARY_DIR}/src/windows/service/inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE})
557 include_directories(${CMAKE_CURRENT_BINARY_DIR}/src/windows/wslinstaller/inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE})
558 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/linux/init/inc)
559 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/windows/common)
560 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/shared/configfile)
561 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/localization)
562 include_directories(${CMAKE_BINARY_DIR}/generated)
563
564 include_directories(${WIL_SOURCE_DIR}/include)
565 include_directories(${GSL_SOURCE_DIR}/include)
566 include_directories(${TAEF_SOURCE_DIR}/build/include)
567
568 include_directories(${NLOHMAN_JSON_SOURCE_DIR}/include)
569 link_directories(${TAEF_SOURCE_DIR}/build/Library/${TARGET_PLATFORM})
570 set(TAEF_LINK_LIBRARIES
571 TE.Common.lib
572 Wex.Common.lib
573 Wex.Logger.lib)
574
575 # Subprojects
576 add_subdirectory(nuget)
577 add_subdirectory(msixgluepackage)
578 add_subdirectory(msipackage)
579 add_subdirectory(msixinstaller)
580 add_subdirectory(src/windows/wsldevicehoststub/inc)
581 add_subdirectory(src/windows/common)
582 add_subdirectory(src/windows/service)
583 add_subdirectory(src/windows/wsldevicehoststub)
584 add_subdirectory(src/windows/wslcsession)
585 add_subdirectory(src/windows/wslinstaller/inc)
586 add_subdirectory(src/windows/wslinstaller/stub)
587 add_subdirectory(src/windows/wslinstaller/exe)
588 add_subdirectory(src/shared/configfile)
589 add_subdirectory(src/windows/wsl)
590 add_subdirectory(src/windows/wslg)
591 add_subdirectory(src/windows/wslhost)
592 add_subdirectory(src/windows/wslrelay)
593 add_subdirectory(src/windows/wslinstall)
594 add_subdirectory(src/windows/wslc)
595 add_subdirectory(src/windows/WslcSDK)
596
597 if (WSL_BUILD_WSL_SETTINGS)
598 add_subdirectory(src/windows/libwsl)
599 add_subdirectory(src/windows/wslsettings)
600 endif()
601
602 add_subdirectory(src/linux/netlinkutil)
603 add_subdirectory(src/linux/mountutil)
604 add_subdirectory(src/linux/plan9)
605 add_subdirectory(src/linux/init)
606 add_subdirectory(localization)
607
608 add_subdirectory(test/windows)
609
610 if (DEFINED PIPELINE_BUILD_ID)
611 add_subdirectory(cloudtest)
612 endif()
613
614
615 if(DEFINED ENV{WSL_POST_BUILD_COMMAND})
616 set(WSL_POST_BUILD_COMMAND $ENV{WSL_POST_BUILD_COMMAND})
617 endif ()