1# This performs basic variable replacement on the contents of the WinRT manifest template, as
2# specified by WINRT_MANIFEST. The resulting manifest file is written to the output directory.
3# While the most common options are covered by the default template, the developer is expected
4# to make an application-level copy of the template in order to customize the manifest further.
5# Afterwards, they can override the default template by assigning their template to WINRT_MANIFEST.
6#
7# All subkeys in WINRT_MANIFEST will be replaced if defined/found, so new variables can be easily
8# added.
9
10# The manifest is generated for each build pass for normal apps, and only once for vcapps.
11# - Normal apps have their package root directory in the same place as the target (one for each build pass).
12# - Visual Studio requires a design-mode manifest in the same location as the vcproj.
13!isEmpty(WINRT_MANIFEST): \
14    if(build_pass:equals(TEMPLATE, "app"))| \
15    if(!build_pass:equals(TEMPLATE, "vcapp")) {
16
17    manifest_file.input = $$WINRT_MANIFEST
18
19    contains(TEMPLATE, "vc.*") {
20        BUILD_DIR = $$OUT_PWD
21    } else {
22        load(resolve_target)
23        BUILD_DIR = $$dirname(QMAKE_RESOLVED_TARGET)
24    }
25
26    contains(TEMPLATE, "vc.*"): \
27        manifest_file.output = $$BUILD_DIR/Package.appxmanifest
28    else: \
29        manifest_file.output = $$BUILD_DIR/AppxManifest.xml
30
31    !contains(WINRT_MANIFEST.CONFIG, "verbatim") {
32        # Provide the C-runtime dependency
33        equals(TEMPLATE, "app") {
34            VCLIBS = Microsoft.VCLibs.$$replace(MSVC_VER, \\., ).00
35            CONFIG(debug, debug|release): \
36                VCLIBS = $${VCLIBS}.Debug
37            else: \
38                VCLIBS = $${VCLIBS}
39            # VS 2017 and 2019 still use vclibs 140
40            contains(MSVC_VER, "15.0"): VCLIBS = $$replace(VCLIBS, 150, 140)
41            contains(MSVC_VER, "16.0"): VCLIBS = $$replace(VCLIBS, 160, 140)
42            VCLIBS = "$${VCLIBS}\" MinVersion=\"14.0.0.0\" Publisher=\"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
43            WINRT_MANIFEST.dependencies += $$VCLIBS
44        }
45
46        # Provide default values for required variables
47        isEmpty(WINRT_MANIFEST.target): WINRT_MANIFEST.target = $$TARGET
48        isEmpty(WINRT_MANIFEST.identity) {
49            # Reuse the existing UUID if possible
50            UUID_CACHE = $$OUT_PWD/.qmake.winrt_uuid_$$TARGET
51            exists($$UUID_CACHE) {
52                include($$UUID_CACHE)
53            } else {
54                WINRT_UUID = $$system(uuidgen)
55                isEmpty(WINRT_UUID): error("Unable to generate a UUID. Make sure uuidgen is in your PATH.")
56                WINRT_UUID = "WINRT_MANIFEST.identity = $$WINRT_UUID"
57                write_file($$UUID_CACHE, WINRT_UUID)|error("Unable to write the UUID cache; aborting.")
58                eval($$WINRT_UUID)
59            }
60        }
61        isEmpty(WINRT_MANIFEST.name): WINRT_MANIFEST.name = $$TARGET
62        isEmpty(WINRT_MANIFEST.architecture): WINRT_MANIFEST.architecture = $$VCPROJ_ARCH
63        isEmpty(WINRT_MANIFEST.version): WINRT_MANIFEST.version = 1.0.0.0
64        isEmpty(WINRT_MANIFEST.publisher): WINRT_MANIFEST.publisher = Default publisher display name
65        isEmpty(WINRT_MANIFEST.publisherid): WINRT_MANIFEST.publisherid = CN=$$(USERNAME)
66        isEmpty(WINRT_MANIFEST.phone_product_id): WINRT_MANIFEST.phone_product_id = $$WINRT_MANIFEST.identity
67        isEmpty(WINRT_MANIFEST.phone_publisher_id): WINRT_MANIFEST.phone_publisher_id = 00000000-0000-0000-0000-000000000000
68        isEmpty(WINRT_MANIFEST.description): WINRT_MANIFEST.description = Default package description
69        isEmpty(WINRT_MANIFEST.background): WINRT_MANIFEST.background = green
70        isEmpty(WINRT_MANIFEST.foreground): WINRT_MANIFEST.foreground = light
71        isEmpty(WINRT_MANIFEST.default_language): WINRT_MANIFEST.default_language = en
72        isEmpty(WINRT_MANIFEST.minVersion): \
73            WINRT_MANIFEST.minVersion = $$WINDOWS_TARGET_PLATFORM_VERSION
74        isEmpty(WINRT_MANIFEST.maxVersionTested): \
75            WINRT_MANIFEST.maxVersionTested = $$WINDOWS_TARGET_PLATFORM_MIN_VERSION
76
77        INDENT = "$$escape_expand(\\r\\n)        "
78
79        VS_XML_NAMESPACE = "m2"
80        WINRT_MANIFEST.rotation_preference = $$unique(WINRT_MANIFEST.rotation_preference)
81        !isEmpty(WINRT_MANIFEST.rotation_preference) {
82            MANIFEST_ROTATION += "<$${VS_XML_NAMESPACE}:InitialRotationPreference>"
83            for(ROTATION, WINRT_MANIFEST.rotation_preference): \
84                MANIFEST_ROTATION += "  <$${VS_XML_NAMESPACE}:Rotation Preference=\"$$ROTATION\" />"
85            MANIFEST_ROTATION += "</$${VS_XML_NAMESPACE}:InitialRotationPreference>"
86
87            WINRT_MANIFEST.rotation_preference = $$join(MANIFEST_ROTATION, $$INDENT, $$INDENT)
88        }
89
90        INDENT = "$$escape_expand(\\r\\n)  "
91
92        # All Windows 10 applications need to have internetClient.
93        WINRT_MANIFEST.capabilities += internetClient
94
95        contains(WINRT_MANIFEST.capabilities, defaults) {
96            WINRT_MANIFEST.capabilities -= defaults
97            WINRT_MANIFEST.capabilities += $$WINRT_MANIFEST.capabilities_default
98        }
99
100        contains(WINRT_MANIFEST.capabilities_device, defaults) {
101            WINRT_MANIFEST.capabilities_device -= defaults
102            WINRT_MANIFEST.capabilities_device += $$WINRT_MANIFEST.capabilities_device_default
103        }
104
105        UAP_CAPABILITIES += \
106            appointments \
107            blockedChatMessages \
108            chat \
109            contacts \
110            enterpriseAuthentication \
111            # internetClient is special, as it needs to be written without namespace
112            #internetClient \
113            musicLibrary \
114            objects3D \
115            phoneCall \
116            picturesLibrary \
117            removableStorage \
118            sharedUserCertificates \
119            userAccountInformation \
120            videosLibrary \
121            voipCall
122
123        UAP3_CAPABILITIES += backgroundMediaPlayback remoteSystem userNotificationListener
124
125        IOT_CAPABILITIES += systemManagement
126
127        # Capabilities are given as a string list and may change with the configuration (network, sensors, etc.)
128        WINRT_MANIFEST.capabilities = $$unique(WINRT_MANIFEST.capabilities)
129        WINRT_MANIFEST.capabilities_device = $$unique(WINRT_MANIFEST.capabilities_device)
130        !isEmpty(WINRT_MANIFEST.capabilities)|!isEmpty(WINRT_MANIFEST.capabilities_device) {
131            MANIFEST_CAPABILITIES += "<Capabilities>"
132            for (CAPABILITY, WINRT_MANIFEST.capabilities) {
133                contains(UAP_CAPABILITIES, $$CAPABILITY): \
134                    MANIFEST_CAPABILITIES += "  <uap:Capability Name=\"$$CAPABILITY\" />"
135                else:contains(UAP3_CAPABILITIES, $$CAPABILITY): \
136                    MANIFEST_CAPABILITIES += "  <uap3:Capability Name=\"$$CAPABILITY\" />"
137                else:contains(IOT_CAPABILITIES, $$CAPABILITY): \
138                    MANIFEST_CAPABILITIES += "  <iot:Capability Name=\"$$CAPABILITY\" />"
139                else: \
140                    MANIFEST_CAPABILITIES += "  <Capability Name=\"$$CAPABILITY\" />"
141            }
142            for(CAPABILITY, WINRT_MANIFEST.capabilities_device): \
143                MANIFEST_CAPABILITIES += "  <DeviceCapability Name=\"$$CAPABILITY\" />"
144            MANIFEST_CAPABILITIES += "</Capabilities>"
145
146            WINRT_MANIFEST.capabilities = $$join(MANIFEST_CAPABILITIES, $$INDENT, $$INDENT)
147        }
148
149        # Dependencies are given as a string list. The CRT dependency is added automatically above.
150        # For MSVC2015/2017 the dependencies are added in conjunction with TargetDeviceFamily
151        # Due to the hard coded dependency on "Windows.Universal" the <Dependencies> tag
152        # is already inside the MSVC2015 manifest.
153        WINRT_MANIFEST.dependencies = $$unique(WINRT_MANIFEST.dependencies)
154        !isEmpty(WINRT_MANIFEST.dependencies) {
155            for(DEPENDENCY, WINRT_MANIFEST.dependencies): \
156                MANIFEST_DEPENDENCIES += "  <PackageDependency Name=\"$$DEPENDENCY\" />"
157
158            WINRT_MANIFEST.dependencies = $$join(MANIFEST_DEPENDENCIES, $$INDENT, $$INDENT)
159        }
160
161        # Provide default icons where needed
162        isEmpty(WINRT_ASSETS_PATH): WINRT_ASSETS_PATH = $$[QT_HOST_DATA/get]/mkspecs/common/winrt_winphone/assets
163        TEMPLATE_CONTENTS = $$cat($$WINRT_MANIFEST, lines)
164        ICONS_FOUND = $$find(TEMPLATE_CONTENTS, \\\$\\\$\\{WINRT_MANIFEST\\.(logo|tile)_)
165        ICONS_FOUND ~= s/.*\\\$\\\$\\{WINRT_MANIFEST\\.((logo|tile)_[^\}]+)\\}.*/\\1/g
166        for (ICON_NAME, ICONS_FOUND) {
167            ICON_FILE = $$eval(WINRT_MANIFEST.$$ICON_NAME)
168            isEmpty(ICON_FILE) {
169                equals(ICON_NAME, "logo_310x150"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_wide)
170                else: equals(ICON_NAME, "logo_150x150"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_large)
171                # Windows Phone specifics
172                else: equals(ICON_NAME, "logo_480x800"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_splash)
173                else: equals(ICON_NAME, "logo_71x71"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_medium)
174                else: equals(ICON_NAME, "logo_44x44"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_small)
175                # Windows RT specifics
176                else: equals(ICON_NAME, "logo_620x300"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_splash)
177                else: equals(ICON_NAME, "logo_70x70"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_medium)
178                else: equals(ICON_NAME, "logo_30x30"): ICON_FILE = $$eval(WINRT_MANIFEST.logo_small)
179            }
180            isEmpty(ICON_FILE): ICON_FILE = $$WINRT_ASSETS_PATH/$${ICON_NAME}.png
181            icon_$${ICON_NAME}.input = $$ICON_FILE
182            icon_$${ICON_NAME}.output = $$BUILD_DIR/assets/$$basename(ICON_FILE)
183            icon_$${ICON_NAME}.CONFIG = verbatim
184            QMAKE_SUBSTITUTES += icon_$${ICON_NAME}
185            WINRT_MANIFEST.$${ICON_NAME} = assets/$$basename(ICON_FILE)
186        }
187
188        !contains(TEMPLATE, "vc.*") {
189            winrt_manifest_install.files = $$manifest_file.output
190            winrt_manifest_install.path = $$target.path
191            winrt_assets_install.files = $$BUILD_DIR/assets/*
192            winrt_assets_install.path = $$target.path/assets
193            INSTALLS += winrt_manifest_install winrt_assets_install
194        }
195    } else {
196        manifest_file.CONFIG += verbatim
197    }
198
199    QMAKE_SUBSTITUTES += manifest_file
200}
201