1010 This package defines the following CMake targets:
1111
1212 * Microsoft.WindowsAppSDK.Foundation - A target representing the C++/WinRT projection, headers and libraries of
13- the Windows App SDK Foundation APIs. This does not include the necessary runtime components to use the
14- Windows App SDK, and is intended to be used by library authors who want to consume the Windows App SDK
15- Foundation APIs.
13+ the Windows App SDK Foundation APIs. This target does not have any deployment-mode-specific behavior,
14+ however it does forward-declare two variant targets (Foundation_Framework and Foundation_SelfContained) that the wasdk_link_component_variant() helper populates based on the consumer's WindowsAppSDKSelfContained property.
1615
1716 * Microsoft.WindowsAppSDK.Foundation_Framework - A target representing the Windows App SDK Foundation APIs for
1817 framework-dependent deployment scenarios. Auto-initialization behavior is controlled by target properties
@@ -51,7 +50,7 @@ if(CMAKE_VERSION VERSION_LESS 3.31)
5150 message (FATAL_ERROR "Microsoft.WindowsAppSDK.Foundation requires at least CMake 3.31, but CMake ${CMAKE_VERSION } is in use." )
5251endif ()
5352
54-
53+ find_package ( Microsoft.WindowsAppSDK.Base CONFIG REQUIRED )
5554find_package (Microsoft.WindowsAppSDK.InteractiveExperiences CONFIG REQUIRED )
5655
5756block (SCOPE_FOR VARIABLES )
@@ -78,6 +77,17 @@ block(SCOPE_FOR VARIABLES)
7877 ${PACKAGE_LOCATION} /include
7978 )
8079
80+ # Forward-declare deployment-mode variant targets adjacent to the basic target.
81+ # Populated further below; this declaration lets wasdk_link_component_variant() enforce
82+ # the contract that both variants exist at configure time.
83+ add_library (Microsoft.WindowsAppSDK.Foundation_Framework INTERFACE )
84+ add_library (Microsoft.WindowsAppSDK.Foundation_SelfContained INTERFACE )
85+
86+ # Basic target as variant selector
87+ # Resolves to _Framework or _SelfContained based on the consumer's WindowsAppSDKSelfContained
88+ # property at generation time.
89+ wasdk_link_component_variant (Foundation )
90+
8191 #[[ ====================================================================================================================
8292 Target: Microsoft.WindowsAppSDK.Foundation_DynamicDependencyBootstrap
8393
@@ -217,7 +227,7 @@ block(SCOPE_FOR VARIABLES)
217227 IMPORTED_LOCATION "${FRAMEWORK_DLLS} "
218228 )
219229
220- add_library ( Microsoft.WindowsAppSDK.Foundation_SelfContained INTERFACE )
230+ # _SelfContained interface target was forward-declared near the basic target above.
221231
222232 wasdk_transform_appxfragment (
223233 Microsoft.WindowsAppSDK.Foundation_SelfContained
@@ -271,7 +281,7 @@ block(SCOPE_FOR VARIABLES)
271281
272282 If the Runtime package is not found, _Framework is not available.
273283 ====================================================================================================================]] #
274- add_library ( Microsoft.WindowsAppSDK.Foundation_Framework INTERFACE )
284+ # _Framework interface target was forward-declared near the basic target above.
275285
276286 target_link_libraries (Microsoft.WindowsAppSDK.Foundation_Framework
277287 INTERFACE
@@ -353,107 +363,104 @@ block(SCOPE_FOR VARIABLES)
353363 )
354364
355365 #[[ ====================================================================================================================
356- wasdk_generate_appx_manifest()
357-
358- Generates an AppxManifest.xml for packaged apps. For framework-dependent apps, automatically
359- includes the <PackageDependency> entry for the Windows App Runtime Framework package.
360-
361- wasdk_generate_appx_manifest(
362- TARGET <target>
363- OUTPUT <output-path>
364- IDENTITY_NAME <name>
365- IDENTITY_PUBLISHER <publisher>
366- IDENTITY_VERSION <version>
367- [DISPLAY_NAME <name>]
368- [DESCRIPTION <description>]
369- [LOGO <path>]
370- )
371-
372- The TARGET must already be defined via add_executable(). If the target links
373- Microsoft.WindowsAppSDK.Foundation_Framework, a <PackageDependency> for the Windows App Runtime
374- Framework package is automatically included. If the target links _SelfContained, no
375- PackageDependency is added.
376- ====================================================================================================================]] #
377- function (wasdk_generate_appx_manifest )
378- set (ONE_VALUE_KEYWORDS TARGET OUTPUT IDENTITY_NAME IDENTITY_PUBLISHER IDENTITY_VERSION DISPLAY_NAME DESCRIPTION LOGO)
379- cmake_parse_arguments (PARSE_ARGV 0 APPX "" "${ONE_VALUE_KEYWORDS} " "" )
366+ Foundation auto-init configuration validation (deferred)
380367
381- if (NOT APPX_TARGET)
382- message (FATAL_ERROR "wasdk_generate_appx_manifest: TARGET is required" )
383- endif ()
384- if (NOT APPX_OUTPUT)
385- set (APPX_OUTPUT "${CMAKE_CURRENT_BINARY_DIR } /AppxManifest.xml" )
386- endif ()
387- if (NOT APPX_IDENTITY_NAME OR NOT APPX_IDENTITY_PUBLISHER OR NOT APPX_IDENTITY_VERSION)
388- message (FATAL_ERROR "wasdk_generate_appx_manifest: IDENTITY_NAME, IDENTITY_PUBLISHER, and IDENTITY_VERSION are required" )
389- endif ()
390- if (NOT APPX_DISPLAY_NAME)
391- set (APPX_DISPLAY_NAME "${APPX_IDENTITY_NAME} " )
368+ Runs at end of consumer's directory configure. Walks targets that link
369+ any Microsoft.WindowsAppSDK* and validates 2 configuration rules:
370+
371+ Rule A: FW Unpackaged + WindowsAppSdkBootstrapInitialize=FALSE
372+ → "The Windows App SDK Bootstrapper is required for framework-dependent unpackaged apps"
373+
374+ Rule B: SelfContained + downlevel SDK (< 19H1) + WindowsAppSdkUndockedRegFreeWinRTInitialize=FALSE
375+ → "Undocked Reg-Free WinRT activation is required for self-contained apps targeting Windows versions prior to 10.0.18362.0"
376+
377+ Both produce configure-time FATAL_ERROR. This Foundation-side validator only fires when Foundation
378+ IS loaded.
379+ ====================================================================================================================]] #
380+ function (_wasdk_foundation_validate_target target )
381+ get_target_property (_type ${target} TYPE)
382+ if (NOT _type STREQUAL "EXECUTABLE" )
383+ return ()
392384 endif ()
393- if (NOT APPX_DESCRIPTION)
394- set (APPX_DESCRIPTION "${APPX_DISPLAY_NAME} " )
385+
386+ get_target_property (_link_libs ${target} LINK_LIBRARIES )
387+ if (NOT _link_libs)
388+ return ()
395389 endif ()
396- if (NOT APPX_LOGO)
397- set (APPX_LOGO "Logo.png" )
390+ set (_uses_wasdk FALSE )
391+ foreach (_lib IN LISTS _link_libs)
392+ if (_lib MATCHES "^Microsoft\\ .WindowsAppSDK" )
393+ set (_uses_wasdk TRUE )
394+ break ()
395+ endif ()
396+ endforeach ()
397+ if (NOT _uses_wasdk)
398+ return ()
398399 endif ()
399400
400- # Determine architecture
401- wasdk_detect_platform ()
402- if (PLATFORM_IDENTIFIER STREQUAL "x64" )
403- set (_PROC_ARCH "x64" )
404- elseif (PLATFORM_IDENTIFIER STREQUAL "arm64" )
405- set (_PROC_ARCH "arm64" )
406- else ()
407- set (_PROC_ARCH "x64" )
401+ get_target_property (_pkg_type ${target} WindowsPackageType)
402+ get_target_property (_sc ${target} WindowsAppSDKSelfContained)
403+ get_target_property (_bootstrap ${target} WindowsAppSdkBootstrapInitialize)
404+ get_target_property (_urf ${target} WindowsAppSdkUndockedRegFreeWinRTInitialize)
405+
406+ # Rule A: FW Unpackaged + BootstrapInit=FALSE → error
407+ if (_pkg_type STREQUAL "None" AND NOT _sc AND _bootstrap STREQUAL "FALSE" )
408+ message (FATAL_ERROR
409+ "The Windows App SDK Bootstrapper is required for framework-dependent unpackaged apps. "
410+ "Target '${target} ' has WindowsPackageType=\" None\" and "
411+ "WindowsAppSdkBootstrapInitialize=FALSE. Either set "
412+ "WindowsAppSdkBootstrapInitialize=TRUE, change the deployment model, or "
413+ "make the app self-contained." )
408414 endif ()
409415
410- # Build the PackageDependency section if framework info is available
411- set (_PACKAGE_DEPENDENCY "" )
412- if (DEFINED WINDOWSAPPSDK_FRAMEWORK_PACKAGE_NAME)
413- set (_PACKAGE_DEPENDENCY " <PackageDependency Name=\" ${WINDOWSAPPSDK_FRAMEWORK_PACKAGE_NAME} \" MinVersion=\" ${WINDOWSAPPSDK_FRAMEWORK_MIN_VERSION} \" Publisher=\" ${WINDOWSAPPSDK_FRAMEWORK_PUBLISHER} \" />\n " )
416+ # Rule B: SC + downlevel SDK + URFInit=FALSE → error
417+ if (_sc AND _urf STREQUAL "FALSE" )
418+ # Detect the target's MINIMUM supported OS version.
419+ # CMAKE_SYSTEM_VERSION (set via -DCMAKE_SYSTEM_VERSION or by toolchain
420+ # file) is the canonical CMake variable for the target MIN OS version.
421+ # CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION is the BUILD SDK that VS
422+ # selects to compile against (often newer than the target min); not
423+ # what we want for this check. Falls back to env if neither set.
424+ set (_tpv "" )
425+ if (NOT "${CMAKE_SYSTEM_VERSION } " STREQUAL "" )
426+ set (_tpv "${CMAKE_SYSTEM_VERSION } " )
427+ elseif (NOT "${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} " STREQUAL "" )
428+ set (_tpv "${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} " )
429+ elseif (DEFINED ENV{WindowsSDKVersion})
430+ string (REGEX REPLACE "^([0-9]+\\ .[0-9]+\\ .[0-9]+\\ .[0-9]+).*" "\\ 1" _tpv "$ENV{WindowsSDKVersion} " )
431+ endif ()
432+ if (_tpv AND _tpv VERSION_LESS "10.0.18362.0" )
433+ message (FATAL_ERROR
434+ "Undocked Reg-Free WinRT activation is required for self-contained apps targeting Windows versions prior to 10.0.18362.0. "
435+ "Target '${target} ' is self-contained, targets SDK version ${_tpv} , and has "
436+ "WindowsAppSdkUndockedRegFreeWinRTInitialize=FALSE. Either remove the "
437+ "explicit FALSE override, raise the target SDK version, or switch to "
438+ "framework-dependent deployment." )
439+ endif ()
414440 endif ()
441+ endfunction ()
415442
416- # Generate the manifest
417- file (WRITE "${APPX_OUTPUT} "
418- "<?xml version=\" 1.0\" encoding=\" utf-8\" ?>
419- <Package xmlns=\" http://schemas.microsoft.com/appx/manifest/foundation/windows10\"
420- xmlns:uap=\" http://schemas.microsoft.com/appx/manifest/uap/windows10\"
421- xmlns:rescap=\" http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities\"
422- IgnorableNamespaces=\" uap rescap\" >
423- <Identity Name=\" ${APPX_IDENTITY_NAME} \"
424- Version=\" ${APPX_IDENTITY_VERSION} \"
425- Publisher=\" ${APPX_IDENTITY_PUBLISHER} \"
426- ProcessorArchitecture=\" ${_PROC_ARCH} \" />
427- <Properties>
428- <DisplayName>${APPX_DISPLAY_NAME} </DisplayName>
429- <PublisherDisplayName>${APPX_IDENTITY_PUBLISHER} </PublisherDisplayName>
430- <Description>${APPX_DESCRIPTION} </Description>
431- <Logo>${APPX_LOGO} </Logo>
432- </Properties>
433- <Dependencies>
434- <TargetDeviceFamily Name=\" Windows.Desktop\" MinVersion=\" 10.0.17763.0\" MaxVersionTested=\" 10.0.26100.0\" />
435- ${_PACKAGE_DEPENDENCY} </Dependencies>
436- <Resources>
437- <Resource Language=\" en-us\" />
438- </Resources>
439- <Applications>
440- <Application Id=\" App\" Executable=\" ${APPX_TARGET} .exe\" EntryPoint=\" Windows.FullTrustApplication\" >
441- <uap:VisualElements DisplayName=\" ${APPX_DISPLAY_NAME} \" Description=\" ${APPX_DESCRIPTION} \"
442- BackgroundColor=\" transparent\" Square150x150Logo=\" ${APPX_LOGO} \" Square44x44Logo=\" ${APPX_LOGO} \" >
443- <uap:DefaultTile Wide310x150Logo=\" ${APPX_LOGO} \" />
444- </uap:VisualElements>
445- </Application>
446- </Applications>
447- <Capabilities>
448- <rescap:Capability Name=\" runFullTrust\" />
449- </Capabilities>
450- </Package>
451- " )
452-
453- # Copy manifest + logo to output directory post-build
454- add_custom_command (TARGET ${APPX_TARGET} POST_BUILD
455- COMMAND ${CMAKE_COMMAND } -E copy_if_different "${APPX_OUTPUT} " $<TARGET_FILE_DIR :${APPX_TARGET} >
456- )
443+ function (_wasdk_foundation_validate_recursive _dir )
444+ get_directory_property (_targets DIRECTORY ${_dir} BUILDSYSTEM_TARGETS)
445+ foreach (_t IN LISTS _targets)
446+ _wasdk_foundation_validate_target (${_t} )
447+ endforeach ()
448+
449+ get_directory_property (_subdirs DIRECTORY ${_dir} SUBDIRECTORIES)
450+ foreach (_sub IN LISTS _subdirs)
451+ _wasdk_foundation_validate_recursive (${_sub} )
452+ endforeach ()
453+ endfunction ()
454+
455+ function (_wasdk_foundation_validate )
456+ _wasdk_foundation_validate_recursive (${CMAKE_CURRENT_SOURCE_DIR } )
457457 endfunction ()
458458
459+ # Register DEFER hook; idempotent per directory.
460+ get_directory_property (_already_deferred _WASDK_FOUNDATION_VALIDATE_DEFERRED)
461+ if (NOT _already_deferred)
462+ set_property (DIRECTORY PROPERTY _WASDK_FOUNDATION_VALIDATE_DEFERRED TRUE )
463+ cmake_language (DEFER CALL _wasdk_foundation_validate )
464+ endif ()
465+
459466endblock ()
0 commit comments