msix-packaging/cmake/msix_resources.cmake

353 строки
20 KiB
CMake

# Copyright (C) 2017 Microsoft. All rights reserved.
# See LICENSE file in the project root for full license information.
# This file creates a zip file for our resources and produce MSIXResource.hpp.
# MSIXResource.hpp contains a std::uint8_t array that is the zip file as bytes. Internally,
# we create a stream from it, treat as a stream and use our own ZipObject implementation to read data from it.
set(RESOURCES_CERTS)
set(RESOURCES_BLOCKMAP)
set(RESOURCES_CONTENTTYPE)
set(RESOURCES_APPXTYPES)
set(RESOURCES_APPXMANIFEST)
set(RESOURCES_APPXBUNDLEMANIFEST)
set(RESOURCES_DIR "${MSIX_PROJECT_ROOT}/resources")
if(CRYPTO_LIB MATCHES openssl) # Only OpenSSL needs to carry the certificates.
list(APPEND RESOURCES_CERTS
"certs/base64_MSFT_RCA_2010.cer"
"certs/base64_MSFT_RCA_2011.cer"
"certs/base64_STORE_PCA_2011.cer"
"certs/base64_Windows_Production.cer"
"certs/base64_Windows_Production_PCA_2011.cer"
"certs/Microsoft_MarketPlace_PCA_2011.cer")
endif()
if ((XML_PARSER MATCHES msxml6) OR (XML_PARSER MATCHES xerces))
# Used by namespace manager
if (XML_PARSER MATCHES msxml6)
set(CHAR_TYPE "wchar_t")
set(STR_COMP "wcscmp")
set(STR_PREFIX "L")
else() # xerces
set(CHAR_TYPE "char")
set(STR_COMP "strcmp")
set(STR_PREFIX "u8")
endif()
if(USE_VALIDATION_PARSER)
add_definitions(-DVALIDATING=1)
# Schemas are defined in triplets in the form of
# <namespace> <alias> <file location relative to root/resources>
list(APPEND CONTENT_TYPES
"http://schemas.openxmlformats.org/package/2006/content-types" "a" "AppxPackaging/[Content_Types]/opc-contentTypes.xsd")
list(APPEND RESOURCES_CONTENTTYPE
CONTENT_TYPES)
# Block map
list(APPEND BLOCKMAP_SCHEMA
"http://schemas.microsoft.com/appx/2010/blockmap" "a" "AppxPackaging/BlockMap/schema/BlockMapSchema.xsd")
list(APPEND BLOCKMAP_SCHEMA_2015
"http://schemas.microsoft.com/appx/2015/blockmap" "b" "AppxPackaging/BlockMap/schema/BlockMapSchema2015.xsd")
list(APPEND BLOCKMAP_SCHEMA_2017
"http://schemas.microsoft.com/appx/2017/blockmap" "c" "AppxPackaging/BlockMap/schema/BlockMapSchema2017.xsd")
list(APPEND RESOURCES_BLOCKMAP
BLOCKMAP_SCHEMA
BLOCKMAP_SCHEMA_2015
BLOCKMAP_SCHEMA_2017)
# Used by AppxManifest and AppxBundleManifest
list(APPEND APPX_TYPES
"http://schemas.microsoft.com/appx/manifest/types" "t" "AppxPackaging/Manifest/Schema/2015/AppxManifestTypes.xsd")
list(APPEND RESOURCES_APPXTYPES
APPX_TYPES)
# Appx Manifest
list(APPEND MANIFEST_FOUNDATION
"http://schemas.microsoft.com/appx/manifest/foundation/windows10" "win10foundation" "AppxPackaging/Manifest/Schema/2015/FoundationManifestSchema.xsd")
list(APPEND MANIFEST_UAP
"http://schemas.microsoft.com/appx/manifest/uap/windows10" "win10uap" "AppxPackaging/Manifest/Schema/2015/UapManifestSchema.xsd")
list(APPEND MANIFEST_PHONE
"http://schemas.microsoft.com/appx/2014/phone/manifest" "mp" "AppxPackaging/Manifest/Schema/2015/AppxPhoneManifestSchema2014.xsd")
list(APPEND MANIFEST_FOUNDATION2
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/2" "foundation2" "AppxPackaging/Manifest/Schema/2015/FoundationManifestSchema_v2.xsd")
list(APPEND MANIFEST_UAP2
"http://schemas.microsoft.com/appx/manifest/uap/windows10/2" "uap2" "AppxPackaging/Manifest/Schema/2015/UapManifestSchema_v2.xsd")
list(APPEND MANIFEST_UAP3
"http://schemas.microsoft.com/appx/manifest/uap/windows10/3" "uap3" "AppxPackaging/Manifest/Schema/2015/UapManifestSchema_v3.xsd")
list(APPEND MANIFEST_UAP4
"http://schemas.microsoft.com/appx/manifest/uap/windows10/4" "uap4" "AppxPackaging/Manifest/Schema/2016/UapManifestSchema_v4.xsd")
list(APPEND MANIFEST_WINCAP
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/windowscapabilities" "win10wincap" "AppxPackaging/Manifest/Schema/2015/WindowsCapabilitiesManifestSchema.xsd")
list(APPEND MANIFEST_WINCAP2
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/windowscapabilities/2" "wincap2" "AppxPackaging/Manifest/Schema/2015/WindowsCapabilitiesManifestSchema_v2.xsd")
list(APPEND MANIFEST_WINCAP3
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/windowscapabilities/3" "wincap3" "AppxPackaging/Manifest/Schema/2016/WindowsCapabilitiesManifestSchema_v3.xsd")
list(APPEND MANIFEST_RESCAP
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" "win10rescap" "AppxPackaging/Manifest/Schema/2015/RestrictedCapabilitiesManifestSchema.xsd")
list(APPEND MANIFEST_RESCAP2
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/2" "rescap2" "AppxPackaging/Manifest/Schema/2015/RestrictedCapabilitiesManifestSchema_v2.xsd")
list(APPEND MANIFEST_RESCAP3
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/3" "rescap3" "AppxPackaging/Manifest/Schema/2016/RestrictedCapabilitiesManifestSchema_v3.xsd")
list(APPEND MANIFEST_RESCAP4
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/4" "rescap4" "AppxPackaging/Manifest/Schema/2017/RestrictedCapabilitiesManifestSchema_v4.xsd")
list(APPEND MANIFEST_RESCAP5
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/5" "rescap5" "AppxPackaging/Manifest/Schema/2018/RestrictedCapabilitiesManifestSchema_v5.xsd")
list(APPEND MANIFEST_RESCAP6
"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/6" "rescap6" "AppxPackaging/Manifest/Schema/2018/RestrictedCapabilitiesManifestSchema_v6.xsd")
list(APPEND MANIFEST_MOBILE
"http://schemas.microsoft.com/appx/manifest/mobile/windows10" "win10mobile" "AppxPackaging/Manifest/Schema/2015/MobileManifestSchema.xsd")
list(APPEND MANIFEST_IOT
"http://schemas.microsoft.com/appx/manifest/iot/windows10" "win10iot" "AppxPackaging/Manifest/Schema/2015/IotManifestSchema.xsd")
list(APPEND MANIFEST_IOT2
"http://schemas.microsoft.com/appx/manifest/iot/windows10/2" "iot2" "AppxPackaging/Manifest/Schema/2017/IotManifestSchema_v2.xsd")
list(APPEND MANIFEST_HOLO
"http://schemas.microsoft.com/appx/manifest/holographic/windows10" "holo" "AppxPackaging/Manifest/Schema/2015/HolographicManifestSchema.xsd")
list(APPEND MANIFEST_SERVER
"http://schemas.microsoft.com/appx/manifest/serverpreview/windows10" "win10serverpreview" "AppxPackaging/Manifest/Schema/2015/ServerManifestSchema.xsd")
list(APPEND MANIFEST_DESK
"http://schemas.microsoft.com/appx/manifest/desktop/windows10" "desktop" "AppxPackaging/Manifest/Schema/2015/DesktopManifestSchema.xsd")
list(APPEND MANIFEST_DESK2
"http://schemas.microsoft.com/appx/manifest/desktop/windows10/2" "desktop2" "AppxPackaging/Manifest/Schema/2016/DesktopManifestSchema_v2.xsd")
list(APPEND MANIFEST_DESK3
"http://schemas.microsoft.com/appx/manifest/desktop/windows10/3" "desktop3" "AppxPackaging/Manifest/Schema/2017/DesktopManifestSchema_v3.xsd")
list(APPEND MANIFEST_DESK4
"http://schemas.microsoft.com/appx/manifest/desktop/windows10/4" "desktop4" "AppxPackaging/Manifest/Schema/2017/DesktopManifestSchema_v4.xsd")
list(APPEND MANIFEST_DESK5
"http://schemas.microsoft.com/appx/manifest/desktop/windows10/5" "desktop5" "AppxPackaging/Manifest/Schema/2018/DesktopManifestSchema_v5.xsd")
list(APPEND MANIFEST_DESK6
"http://schemas.microsoft.com/appx/manifest/desktop/windows10/6" "desktop6" "AppxPackaging/Manifest/Schema/2018/DesktopManifestSchema_v6.xsd")
list(APPEND MANIFEST_COM
"http://schemas.microsoft.com/appx/manifest/com/windows10" "com" "AppxPackaging/Manifest/Schema/2015/ComManifestSchema.xsd")
list(APPEND MANIFEST_COM2
"http://schemas.microsoft.com/appx/manifest/com/windows10/2" "com2" "AppxPackaging/Manifest/Schema/2017/ComManifestSchema_v2.xsd")
list(APPEND MANIFEST_UAP5
"http://schemas.microsoft.com/appx/manifest/uap/windows10/5" "uap5" "AppxPackaging/Manifest/Schema/2017/UapManifestSchema_v5.xsd")
list(APPEND MANIFEST_UAP6
"http://schemas.microsoft.com/appx/manifest/uap/windows10/6" "uap6" "AppxPackaging/Manifest/Schema/2017/UapManifestSchema_v6.xsd")
list(APPEND MANIFEST_UAP7
"http://schemas.microsoft.com/appx/manifest/uap/windows10/7" "uap7" "AppxPackaging/Manifest/Schema/2018/UapManifestSchema_v7.xsd")
list(APPEND MANIFEST_UAP8
"http://schemas.microsoft.com/appx/manifest/uap/windows10/8" "uap8" "AppxPackaging/Manifest/Schema/2018/UapManifestSchema_v8.xsd")
list(APPEND RESOURCES_APPXMANIFEST
MANIFEST_FOUNDATION
MANIFEST_UAP
MANIFEST_PHONE
MANIFEST_FOUNDATION2
MANIFEST_UAP2
MANIFEST_UAP3
MANIFEST_UAP4
MANIFEST_WINCAP
MANIFEST_WINCAP2
MANIFEST_WINCAP3
MANIFEST_RESCAP
MANIFEST_RESCAP2
MANIFEST_RESCAP3
MANIFEST_RESCAP4
MANIFEST_RESCAP5
MANIFEST_RESCAP6
MANIFEST_MOBILE
MANIFEST_IOT
MANIFEST_IOT2
MANIFEST_HOLO
MANIFEST_SERVER
MANIFEST_DESK
MANIFEST_DESK2
MANIFEST_DESK3
MANIFEST_DESK4
MANIFEST_DESK5
MANIFEST_DESK6
MANIFEST_COM
MANIFEST_COM2
MANIFEST_UAP5
MANIFEST_UAP6
MANIFEST_UAP7
MANIFEST_UAP8)
# Bundle manifest
list(APPEND BUNDLE_2014
"http://schemas.microsoft.com/appx/2013/bundle" "b" "AppxPackaging/Manifest/Schema/2015/BundleManifestSchema2014.xsd")
list(APPEND BUNDLE_2016
"http://schemas.microsoft.com/appx/2016/bundle" "b2" "AppxPackaging/Manifest/Schema/2016/BundleManifestSchema2016.xsd")
list(APPEND BUNDLE_2017
"http://schemas.microsoft.com/appx/2017/bundle" "b3" "AppxPackaging/Manifest/Schema/2017/BundleManifestSchema2017.xsd")
list(APPEND BUNDLE_2018
"http://schemas.microsoft.com/appx/2018/bundle" "b4" "AppxPackaging/Manifest/Schema/2018/BundleManifestSchema2018.xsd")
list(APPEND RESOURCES_APPXBUNDLEMANIFEST
BUNDLE_2014
BUNDLE_2016
BUNDLE_2017
BUNDLE_2018)
if (XML_PARSER MATCHES xerces)
file(COPY ${RESOURCES_DIR} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
set(RESOURCES_DIR "${CMAKE_CURRENT_BINARY_DIR}/resources")
# For xerces we replace all the maxOccurs="<high number>" to maxOccurs="<unbounded>"
# where high number is >=100. This means that it is possible to accept a manifest
# that will fail for windows.
# From xerces limitations:
# In certain complex content models specifying large values for the minOccurs or
# maxOccurs attributes may result in poor performance and/or large amount of
# memory being allocated by the parser. In such situations large values for
# minOccurs should be avoided, and unbounded should be used instead.
# See: https://xerces.apache.org/xerces-c/schema-3.html
foreach(TRIPLET ${RESOURCES_APPXMANIFEST} ${RESOURCES_APPXBUNDLEMANIFEST})
list(GET ${TRIPLET} 2 SCHEMA)
file(READ "${RESOURCES_DIR}/${SCHEMA}" SCHEMA_TEXT)
string(REGEX REPLACE "maxOccurs=\"[1-9][0-9][0-9]+\"" "maxOccurs=\"unbounded\"" SCHEMA_TEXT "${SCHEMA_TEXT}")
file(WRITE "${RESOURCES_DIR}/${SCHEMA}" "${SCHEMA_TEXT}")
endforeach()
# AppxManifestTypes.xsd uses some XML 1.0 non standard regex patterns
list(GET APPX_TYPES 2 APPX_TYPES_FILE)
file(READ "${RESOURCES_DIR}/${APPX_TYPES_FILE}" APPTYPES_TEXT)
# The only valid characters between \x01-\x1f are x9 (tab) xA (new line) xD (carriage return)
# ST_Description ST_FileNameCharSet
string(REGEX REPLACE
[[\\x01-\\x1f]]
[[\\t\\n\\r]]
APPTYPES_TEXT "${APPTYPES_TEXT}")
# Word boundaries
# ST_ResourceReference and ST_WebAccountProviderUrl
string(REGEX REPLACE
[[\\bms-resource]]
"ms-resource"
APPTYPES_TEXT "${APPTYPES_TEXT}")
string(REGEX REPLACE
[[\\w]]
[[a-zA-Z0-9_]]
APPTYPES_TEXT "${APPTYPES_TEXT}")
# Ilegal escaped characters
# ST_WebAccountProviderUrl
string(REGEX REPLACE
[[\\/]]
[[/]]
APPTYPES_TEXT "${APPTYPES_TEXT}")
# Negative lookahead. I am not sure if we can do something here... maybe a semantic check?
# ST_Parameters
string(REGEX REPLACE
[[\(\(\?\!\\%\[Ii\].*\\%\[Ii\]\)\.\)\*]]
".*"
APPTYPES_TEXT "${APPTYPES_TEXT}")
file(WRITE "${RESOURCES_DIR}/${APPX_TYPES_FILE}" "${APPTYPES_TEXT}")
endif()
function(CreateNamespaceManager LIST OUTPUT)
foreach(TRIPLET ${LIST})
list(GET ${TRIPLET} 0 NAMESPACE)
list(GET ${TRIPLET} 1 ALIAS)
list(GET ${TRIPLET} 2 FILE)
string(APPEND RESULT "SchemaEntry(" "${STR_PREFIX}" \" "${NAMESPACE}" \", "${STR_PREFIX}" \" "${ALIAS}" \" , u8\" "${FILE}" \" "),\n\t\t")
endforeach()
set(${OUTPUT} ${RESULT} PARENT_SCOPE)
endfunction()
CreateNamespaceManager("${RESOURCES_CONTENTTYPE}" SCHEMAENTRY_CONTENTTYPE)
CreateNamespaceManager("${RESOURCES_BLOCKMAP}" SCHEMAENTRY_BLOCKMAP)
CreateNamespaceManager("${RESOURCES_APPXTYPES}" SCHEMAENTRY_APPXTYPES)
CreateNamespaceManager("${RESOURCES_APPXMANIFEST}" SCHEMAENTRY_APPXMANIFEST)
CreateNamespaceManager("${RESOURCES_APPXBUNDLEMANIFEST}" SCHEMAENTRY_APPXBUNDLEMANIFEST)
endif(USE_VALIDATION_PARSER)
# Namespace manager
set(NAMESPACE_MANAGER_HPP "
struct SchemaEntry
{
const ${CHAR_TYPE}* uri;
const ${CHAR_TYPE}* alias;
const char* schema;
SchemaEntry(const ${CHAR_TYPE}* u, const ${CHAR_TYPE}* a, const char* s) : uri(u), alias(a), schema(s) {}
inline bool operator==(const ${CHAR_TYPE}* otherUri) const {
return 0 == ${STR_COMP}(uri, otherUri);
}
};
typedef std::vector<SchemaEntry> NamespaceManager;
// ALL THE URIs MUST BE LOWER-CASE, ordering of schema entries defines order of placement of schema into schema cache.
extern const NamespaceManager s_xmlNamespaces[];")
set(NAMESPACE_MANAGER_CPP "
const NamespaceManager s_xmlNamespaces[] = {
{ // XmlContentType::ContentTypeXml
${SCHEMAENTRY_CONTENTTYPE}
},
{ // XmlContentType::AppxBlockMapXml
${SCHEMAENTRY_BLOCKMAP}
},
{ // XmlContentType::AppxManifestXml
${SCHEMAENTRY_APPXTYPES}
${SCHEMAENTRY_APPXMANIFEST}
},
{ // XmlContentType::AppxBundleManifestXml
${SCHEMAENTRY_APPXTYPES}
${SCHEMAENTRY_APPXBUNDLEMANIFEST}
}};")
string(CONFIGURE "${NAMESPACE_MANAGER_HPP}" NAMESPACE_MANAGER_HPP)
string(CONFIGURE "${NAMESPACE_MANAGER_CPP}" NAMESPACE_MANAGER_CPP)
endif()
# Create zip file. Use execute_process to run the command while CMake is procesing.
message(STATUS "Resource files:")
set(FILES_TO_ZIP)
foreach(TRIPLET ${RESOURCES_BLOCKMAP} ${RESOURCES_CONTENTTYPE} ${RESOURCES_APPXTYPES} ${RESOURCES_APPXMANIFEST} ${RESOURCES_APPXBUNDLEMANIFEST})
list(GET ${TRIPLET} 2 FILE)
message(STATUS "\t${FILE}")
list(APPEND FILES_TO_ZIP "${FILE}")
endforeach()
foreach(FILE ${RESOURCES_CERTS})
message(STATUS "\t${FILE}")
list(APPEND FILES_TO_ZIP "${FILE}")
endforeach()
# Starting in cmake 3.15, the tar command will error if it receives no files.
# So we catch that case and make the resulting resource blob even smaller.
list(LENGTH FILES_TO_ZIP FILES_TO_ZIP_LENGTH)
if(FILES_TO_ZIP_LENGTH GREATER 0)
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar cvf "${MSIX_BINARY_ROOT}/resources.zip" --format=zip -- ${FILES_TO_ZIP}
WORKING_DIRECTORY "${RESOURCES_DIR}"
OUTPUT_QUIET
)
file(READ "${MSIX_BINARY_ROOT}/resources.zip" RESOURCE_HEX HEX)
else()
# If no files to zip, we will just create the smallest blob we can without angering C++ syntax
message(STATUS "\t<no resource files>")
set(RESOURCE_HEX "00")
endif()
# Create a list by matching every 2 charactes. CMake separates lists with ;
string(REGEX MATCHALL ".." RESOURCE_HEX_LIST "${RESOURCE_HEX}")
list(LENGTH RESOURCE_HEX_LIST RESOURCE_LENGTH)
# The list is just a string, so change ; for ", 0x" to initialize the vector.
# Just remember the first element won't have 0x.
string(REGEX REPLACE ";" ", 0x" RESOURCE_BYTES "${RESOURCE_HEX_LIST}")
function(GetResourceHpp LIST OUTPUT)
foreach(TRIPLET ${LIST})
list(GET ${TRIPLET} 2 FILE)
string(APPEND RESULT result.push_back(std::make_pair(\"${FILE}\", std::move(factory->GetResource(\"${FILE}\")))) ";\n\t\t\t\t")
endforeach()
set(${OUTPUT} ${RESULT} PARENT_SCOPE)
endfunction()
GetResourceHpp("${RESOURCES_BLOCKMAP}" BLOCKMAP_HPP)
GetResourceHpp("${RESOURCES_CONTENTTYPE}" CONTENTTYPE_HPP)
GetResourceHpp("${RESOURCES_APPXMANIFEST}" APPXMANIFEST_HPP)
GetResourceHpp("${RESOURCES_APPXBUNDLEMANIFEST}" APPXBUNDLEMANIFEST_HPP)
GetResourceHpp("${RESOURCES_APPXTYPES}" APPXTYPES_HPP)
foreach(FILE ${RESOURCES_CERTS})
string(APPEND CERTS_HPP result.push_back(std::make_pair(\"${FILE}\", std::move(factory->GetResource(\"${FILE}\")))) ";\n\t\t\t\t")
endforeach()
configure_file(${MSIX_PROJECT_ROOT}/src/inc/internal/MSIXResource.hpp.cmakein ${MSIX_PROJECT_ROOT}/src/inc/internal/MSIXResource.hpp CRLF)
configure_file(${MSIX_PROJECT_ROOT}/src/msix/common/MSIXResource.cpp.cmakein ${MSIX_PROJECT_ROOT}/src/msix/common/MSIXResource.cpp CRLF)