| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| # file Copyright.txt or https://cmake.org/licensing for details. |
| |
| # Author: Alex Turbov |
| |
| if(CMAKE_BINARY_DIR) |
| message(FATAL_ERROR "CPackNuGet.cmake may only be used by CPack internally.") |
| endif() |
| |
| function(_cpack_nuget_debug) |
| if(CPACK_NUGET_PACKAGE_DEBUG) |
| message("CPackNuGet:Debug: " ${ARGN}) |
| endif() |
| endfunction() |
| |
| function(_cpack_nuget_debug_var NAME) |
| if(CPACK_NUGET_PACKAGE_DEBUG) |
| message("CPackNuGet:Debug: ${NAME}=`${${NAME}}`") |
| endif() |
| endfunction() |
| |
| function(_cpack_nuget_variable_fallback OUTPUT_VAR_NAME NUGET_VAR_NAME) |
| if(ARGN) |
| list(JOIN ARGN "`, `" _va_args) |
| set(_va_args ", ARGN: `${_va_args}`") |
| endif() |
| _cpack_nuget_debug( |
| "_cpack_nuget_variable_fallback: " |
| "OUTPUT_VAR_NAME=`${OUTPUT_VAR_NAME}`, " |
| "NUGET_VAR_NAME=`${NUGET_VAR_NAME}`" |
| "${_va_args}" |
| ) |
| |
| set(_options USE_CDATA) |
| set(_one_value_args LIST_GLUE) |
| set(_multi_value_args FALLBACK_VARS) |
| cmake_parse_arguments(PARSE_ARGV 0 _args "${_options}" "${_one_value_args}" "${_multi_value_args}") |
| |
| if(CPACK_NUGET_PACKAGE_COMPONENT) |
| string( |
| TOUPPER "${CPACK_NUGET_PACKAGE_COMPONENT}" |
| CPACK_NUGET_PACKAGE_COMPONENT_UPPER |
| ) |
| endif() |
| |
| if(CPACK_NUGET_PACKAGE_COMPONENT |
| AND CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME} |
| ) |
| set( |
| _result |
| "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}}" |
| ) |
| _cpack_nuget_debug( |
| " CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}: " |
| "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`" |
| ) |
| |
| elseif(CPACK_NUGET_PACKAGE_COMPONENT_UPPER |
| AND CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME} |
| ) |
| set( |
| _result |
| "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}}" |
| ) |
| _cpack_nuget_debug( |
| " CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}: " |
| "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`" |
| ) |
| |
| elseif(CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}) |
| set(_result "${CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}}") |
| _cpack_nuget_debug( |
| " CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}: " |
| "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`" |
| ) |
| |
| else() |
| foreach(_var IN LISTS _args_FALLBACK_VARS) |
| _cpack_nuget_debug(" Fallback: ${_var} ...") |
| if(${_var}) |
| _cpack_nuget_debug(" ${_var}=`${${_var}}`") |
| set(_result "${${_var}}") |
| _cpack_nuget_debug( |
| " ${_var}: OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`" |
| ) |
| break() |
| endif() |
| endforeach() |
| endif() |
| |
| if(_result) |
| if(_args_USE_CDATA) |
| set(_value_before "<![CDATA[") |
| set(_value_after "]]>") |
| endif() |
| |
| list(LENGTH _result _result_len) |
| if(_result_len GREATER 1 AND _args_LIST_GLUE) |
| list(JOIN _result "${_args_LIST_GLUE}" _result) |
| endif() |
| |
| set(${OUTPUT_VAR_NAME} "${_value_before}${_result}${_value_after}" PARENT_SCOPE) |
| endif() |
| |
| endfunction() |
| |
| function(_cpack_nuget_variable_fallback_and_wrap_into_element ELEMENT NUGET_VAR_NAME) |
| set(_options) |
| set(_one_value_args) |
| set(_multi_value_args FALLBACK_VARS ATTRIBUTES) |
| cmake_parse_arguments(PARSE_ARGV 2 _args "${_options}" "${_one_value_args}" "${_multi_value_args}") |
| |
| if(_args_ATTRIBUTES) |
| list(JOIN _args_ATTRIBUTES " " _attributes) |
| string(PREPEND _attributes " ") |
| endif() |
| |
| _cpack_nuget_variable_fallback(_value ${NUGET_VAR_NAME} ${ARGN} USE_CDATA) |
| |
| string(TOUPPER "${ELEMENT}" _ELEMENT_UP) |
| if(_value) |
| set( |
| _CPACK_NUGET_${_ELEMENT_UP}_TAG |
| "<${ELEMENT}${_attributes}>${_value}</${ELEMENT}>" |
| PARENT_SCOPE |
| ) |
| elseif(_attributes) |
| set( |
| _CPACK_NUGET_${_ELEMENT_UP}_TAG |
| "<${ELEMENT}${_attributes} />" |
| PARENT_SCOPE |
| ) |
| endif() |
| endfunction() |
| |
| # Warn of obsolete nuspec fields, referencing CMake variables and suggested |
| # replacement, if any |
| function(_cpack_nuget_deprecation_warning NUGET_ELEMENT VARNAME REPLACEMENT) |
| if(${VARNAME}) |
| if(REPLACEMENT) |
| message(DEPRECATION "nuspec element `${NUGET_ELEMENT}` is deprecated in NuGet; consider replacing `${VARNAME}` with `${REPLACEMENT}`") |
| else() |
| message(DEPRECATION "nuspec element `${NUGET_ELEMENT}` is deprecated in NuGet; consider removing `${VARNAME}`") |
| endif() |
| endif() |
| endfunction() |
| |
| # Print some debug info |
| _cpack_nuget_debug("---[CPack NuGet Input Variables]---") |
| _cpack_nuget_debug_var(CPACK_PACKAGE_NAME) |
| _cpack_nuget_debug_var(CPACK_PACKAGE_VERSION) |
| _cpack_nuget_debug_var(CPACK_TOPLEVEL_TAG) |
| _cpack_nuget_debug_var(CPACK_TOPLEVEL_DIRECTORY) |
| _cpack_nuget_debug_var(CPACK_TEMPORARY_DIRECTORY) |
| _cpack_nuget_debug_var(CPACK_NUGET_GROUPS) |
| if(CPACK_NUGET_GROUPS) |
| foreach(_group IN LISTS CPACK_NUGET_GROUPS) |
| string(MAKE_C_IDENTIFIER "${_group}" _group_up) |
| string(TOUPPER "${_group_up}" _group_up) |
| _cpack_nuget_debug_var(CPACK_NUGET_${_group_up}_GROUP_COMPONENTS) |
| endforeach() |
| endif() |
| _cpack_nuget_debug_var(CPACK_NUGET_COMPONENTS) |
| _cpack_nuget_debug_var(CPACK_NUGET_ALL_IN_ONE) |
| _cpack_nuget_debug_var(CPACK_NUGET_ORDINAL_MONOLITIC) |
| _cpack_nuget_debug("-----------------------------------") |
| |
| function(_cpack_nuget_render_spec) |
| # Make a variable w/ upper-cased component name |
| if(CPACK_NUGET_PACKAGE_COMPONENT) |
| string(TOUPPER "${CPACK_NUGET_PACKAGE_COMPONENT}" CPACK_NUGET_PACKAGE_COMPONENT_UPPER) |
| endif() |
| |
| # Set mandatory variables (not wrapped into XML elements) |
| # https://docs.microsoft.com/en-us/nuget/reference/nuspec#required-metadata-elements |
| if(CPACK_NUGET_PACKAGE_COMPONENT) |
| if(CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME) |
| set( |
| CPACK_NUGET_PACKAGE_NAME |
| "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME}" |
| ) |
| elseif(NOT CPACK_NUGET_PACKAGE_COMPONENT STREQUAL "Unspecified") |
| set( |
| CPACK_NUGET_PACKAGE_NAME |
| "${CPACK_PACKAGE_NAME}.${CPACK_NUGET_PACKAGE_COMPONENT}" |
| ) |
| else() |
| set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") |
| endif() |
| elseif(NOT CPACK_NUGET_PACKAGE_NAME) |
| set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") |
| endif() |
| |
| # Warn about deprecated nuspec elements; warnings only display if |
| # variable is set |
| # Note that while nuspec's "summary" element is deprecated, there |
| # is no suggested replacement so (for now) no deprecation warning |
| # is shown for `CPACK_NUGET_*_DESCRIPTION_SUMMARY` |
| _cpack_nuget_deprecation_warning("licenseUrl" CPACK_NUGET_PACKAGE_LICENSEURL |
| "CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME or CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION") |
| _cpack_nuget_deprecation_warning("licenseUrl" CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_LICENSEURL |
| "CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_LICENSE_FILE_NAME or CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_LICENSE_EXPRESSION") |
| _cpack_nuget_deprecation_warning("iconUrl" CPACK_NUGET_PACKAGE_ICONURL |
| "CPACK_NUGET_PACKAGE_ICON") |
| _cpack_nuget_deprecation_warning("iconUrl" CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_ICONURL |
| "CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_ICON") |
| |
| # Set nuspec fields |
| _cpack_nuget_variable_fallback( |
| CPACK_NUGET_PACKAGE_VERSION VERSION |
| FALLBACK_VARS |
| CPACK_PACKAGE_VERSION |
| ) |
| _cpack_nuget_variable_fallback( |
| CPACK_NUGET_PACKAGE_DESCRIPTION DESCRIPTION |
| FALLBACK_VARS |
| CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT}_DESCRIPTION |
| CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DESCRIPTION |
| CPACK_COMPONENT_GROUP_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DESCRIPTION |
| CPACK_PACKAGE_DESCRIPTION |
| USE_CDATA |
| ) |
| _cpack_nuget_variable_fallback( |
| CPACK_NUGET_PACKAGE_AUTHORS AUTHORS |
| FALLBACK_VARS |
| CPACK_PACKAGE_VENDOR |
| USE_CDATA |
| LIST_GLUE "," |
| ) |
| |
| # Set optional variables (wrapped into XML elements) |
| # https://docs.microsoft.com/en-us/nuget/reference/nuspec#optional-metadata-elements |
| _cpack_nuget_variable_fallback_and_wrap_into_element( |
| title |
| TITLE |
| FALLBACK_VARS |
| CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT}_DISPLAY_NAME |
| CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DISPLAY_NAME |
| CPACK_COMPONENT_GROUP_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DISPLAY_NAME |
| ) |
| _cpack_nuget_variable_fallback_and_wrap_into_element(owners OWNERS LIST_GLUE ",") |
| _cpack_nuget_variable_fallback_and_wrap_into_element( |
| projectUrl |
| HOMEPAGE_URL |
| FALLBACK_VARS |
| CPACK_PACKAGE_HOMEPAGE_URL |
| ) |
| |
| # "licenseUrl" is deprecated in favor of "license" |
| _cpack_nuget_variable_fallback_and_wrap_into_element(licenseUrl LICENSEURL) |
| |
| # "iconUrl" is deprecated in favor of "icon" |
| _cpack_nuget_variable_fallback_and_wrap_into_element(iconUrl ICONURL) |
| |
| # "license" takes a "type" attribute of either "file" or "expression" |
| # "file" refers to a file path of a .txt or .md file relative to the installation root |
| # "expression" refers to simple or compound expression of license identifiers |
| # listed at https://spdx.org/licenses/ |
| # Note that only one of CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME and |
| # CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION may be specified. If both are specified, |
| # CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME takes precedence and CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION is ignored. |
| if(CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME) |
| _cpack_nuget_variable_fallback_and_wrap_into_element( |
| license LICENSE_FILE_NAME |
| ATTRIBUTES [[type="file"]] |
| ) |
| elseif(CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION) |
| _cpack_nuget_variable_fallback_and_wrap_into_element( |
| license LICENSE_EXPRESSION |
| ATTRIBUTES [[type="expression"]] |
| ) |
| endif() |
| |
| # "icon" refers to a file path relative to the installation root |
| _cpack_nuget_variable_fallback_and_wrap_into_element(icon ICON) |
| # "summary" is deprecated in favor of "description" |
| _cpack_nuget_variable_fallback_and_wrap_into_element( |
| summary DESCRIPTION_SUMMARY |
| FALLBACK_VARS |
| CPACK_PACKAGE_DESCRIPTION_SUMMARY |
| ) |
| if(CPACK_NUGET_PACKAGE_REQUIRE_LICENSE_ACCEPTANCE) |
| set( |
| _CPACK_NUGET_REQUIRELICENSEACCEPTANCE_TAG |
| "<requireLicenseAcceptance>true</requireLicenseAcceptance>" |
| ) |
| endif() |
| _cpack_nuget_variable_fallback_and_wrap_into_element(releaseNotes RELEASE_NOTES) |
| _cpack_nuget_variable_fallback_and_wrap_into_element(copyright COPYRIGHT) |
| # "language" is a locale identifier such as "en_CA" |
| _cpack_nuget_variable_fallback_and_wrap_into_element(language LANGUAGE) |
| _cpack_nuget_variable_fallback_and_wrap_into_element(tags TAGS LIST_GLUE " ") |
| # "repository" holds repository metadata consisting of four optional |
| # attributes: "type", "url", "branch", and "commit". While all fields are |
| # considered optional, they are not independent. Currently unsupported. |
| |
| # Handle dependencies |
| _cpack_nuget_variable_fallback(_deps DEPENDENCIES) |
| set(_collected_deps) |
| foreach(_dep IN LISTS _deps) |
| _cpack_nuget_debug(" checking dependency `${_dep}`") |
| |
| _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep}_VERSION) |
| |
| if(NOT _ver) |
| string(TOUPPER "${_dep}" _dep_upper) |
| _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_upper}_VERSION) |
| endif() |
| |
| if(_ver) |
| _cpack_nuget_debug(" got `${_dep}` dependency version ${_ver}") |
| string(CONCAT _collected_deps "${_collected_deps}" " <dependency id=\"${_dep}\" version=\"${_ver}\" />\n") |
| endif() |
| endforeach() |
| |
| # Render deps into the variable |
| if(_collected_deps) |
| string(CONCAT _CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n" "${_collected_deps}" " </dependencies>") |
| endif() |
| |
| # Render the spec file |
| # NOTE The spec filename doesn't matter. Being included into a package, |
| # NuGet will name it properly. |
| _cpack_nuget_debug("Rendering `${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec` file...") |
| configure_file( |
| "${CMAKE_ROOT}/Modules/Internal/CPack/CPack.NuGet.nuspec.in" |
| "${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec" |
| @ONLY |
| ) |
| endfunction() |
| |
| function(_cpack_nuget_make_files_tag) |
| set(_files) |
| foreach(_comp IN LISTS ARGN) |
| string(APPEND _files " <file src=\"${_comp}/**\" target=\".\" />\n") |
| endforeach() |
| set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE) |
| endfunction() |
| |
| find_program(NUGET_EXECUTABLE nuget) |
| _cpack_nuget_debug_var(NUGET_EXECUTABLE) |
| if(NOT NUGET_EXECUTABLE) |
| message(FATAL_ERROR "NuGet executable not found") |
| endif() |
| |
| # Add details for debug run |
| if(CPACK_NUGET_PACKAGE_DEBUG) |
| list(APPEND CPACK_NUGET_PACK_ADDITIONAL_OPTIONS "-Verbosity" "detailed") |
| endif() |
| |
| # Case one: ordinal all-in-one package |
| if(CPACK_NUGET_ORDINAL_MONOLITIC) |
| # This variable `CPACK_NUGET_ALL_IN_ONE` set by C++ code: |
| # Meaning to pack all installed files into a single package |
| _cpack_nuget_debug("---[Making an ordinal monolitic package]---") |
| _cpack_nuget_render_spec() |
| execute_process( |
| COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS} |
| WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" |
| RESULT_VARIABLE _nuget_result |
| ) |
| if(NOT _nuget_result EQUAL 0) |
| message(FATAL_ERROR "Nuget pack failed") |
| endif() |
| |
| elseif(CPACK_NUGET_ALL_IN_ONE) |
| # This variable `CPACK_NUGET_ALL_IN_ONE` set by C++ code: |
| # Meaning to pack all installed components into a single package |
| _cpack_nuget_debug("---[Making a monolitic package from installed components]---") |
| |
| # Prepare the `files` element which include files from several components |
| _cpack_nuget_make_files_tag(${CPACK_NUGET_COMPONENTS}) |
| _cpack_nuget_render_spec() |
| execute_process( |
| COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS} |
| WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" |
| RESULT_VARIABLE _nuget_result |
| ) |
| if(NOT _nuget_result EQUAL 0) |
| message(FATAL_ERROR "Nuget pack failed") |
| endif() |
| |
| else() |
| # Is there any grouped component? |
| if(CPACK_NUGET_GROUPS) |
| _cpack_nuget_debug("---[Making grouped component(s) package(s)]---") |
| foreach(_group IN LISTS CPACK_NUGET_GROUPS) |
| _cpack_nuget_debug("Starting to make the package for group `${_group}`") |
| string(MAKE_C_IDENTIFIER "${_group}" _group_up) |
| string(TOUPPER "${_group_up}" _group_up) |
| |
| # Render a spec file which includes all components in the current group |
| unset(_CPACK_NUGET_FILES_TAG) |
| _cpack_nuget_make_files_tag(${CPACK_NUGET_${_group_up}_GROUP_COMPONENTS}) |
| # Temporary set `CPACK_NUGET_PACKAGE_COMPONENT` to the group name |
| # to properly collect various per group settings |
| set(CPACK_NUGET_PACKAGE_COMPONENT ${_group}) |
| _cpack_nuget_render_spec() |
| unset(CPACK_NUGET_PACKAGE_COMPONENT) |
| execute_process( |
| COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS} |
| WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" |
| RESULT_VARIABLE _nuget_result |
| ) |
| if(NOT _nuget_result EQUAL 0) |
| message(FATAL_ERROR "Nuget pack failed") |
| endif() |
| endforeach() |
| endif() |
| # Is there any single component package needed? |
| if(CPACK_NUGET_COMPONENTS) |
| _cpack_nuget_debug("---[Making single-component(s) package(s)]---") |
| foreach(_comp IN LISTS CPACK_NUGET_COMPONENTS) |
| _cpack_nuget_debug("Starting to make the package for component `${_comp}`") |
| # Render a spec file which includes only given component |
| unset(_CPACK_NUGET_FILES_TAG) |
| _cpack_nuget_make_files_tag(${_comp}) |
| # Temporary set `CPACK_NUGET_PACKAGE_COMPONENT` to the current |
| # component name to properly collect various per group settings |
| set(CPACK_NUGET_PACKAGE_COMPONENT ${_comp}) |
| _cpack_nuget_render_spec() |
| unset(CPACK_NUGET_PACKAGE_COMPONENT) |
| execute_process( |
| COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS} |
| WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" |
| RESULT_VARIABLE _nuget_result |
| ) |
| if(NOT _nuget_result EQUAL 0) |
| message(FATAL_ERROR "Nuget pack failed") |
| endif() |
| endforeach() |
| endif() |
| endif() |
| |
| file(GLOB_RECURSE GEN_CPACK_OUTPUT_FILES "${CPACK_TEMPORARY_DIRECTORY}/*.nupkg") |
| if(NOT GEN_CPACK_OUTPUT_FILES) |
| message(FATAL_ERROR "NuGet package was not generated at `${CPACK_TEMPORARY_DIRECTORY}`!") |
| endif() |
| |
| _cpack_nuget_debug("Generated files: ${GEN_CPACK_OUTPUT_FILES}") |