Skip to content

Commit

Permalink
build: add nuget_install() in cmake/NuGet.cmake
Browse files Browse the repository at this point in the history
This function downloads nuget.exe to out_dir/nuget if necessary and
installs the passed-in NuGet package to that directory.

If the package contains a tools/bin directory, it is added to
CMAKE_PROGRAM_PATH for find_program() to find any utilities.

Add the supporting function file_download() to cmake/Utilities.cmake,
which is a wrapper for the cmake file(DOWNLOAD ...) that takes a
REQUIRED parameter to throw a fatal error if there are any problems.

Signed-off-by: Rafael Kitover <[email protected]>
  • Loading branch information
rkitover committed Feb 15, 2022
1 parent f201457 commit 62ae805
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
73 changes: 73 additions & 0 deletions contrib/buildsystems/cmake/NuGet.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
include(Utilities)

#
# nuget_install([pkg_name] [QUIET])
#
# Installs nuget.exe in the output directory if not already present
# and uses it to install pkg_name if provided.
#
# If the package contains a 'tools/bin' directory, it will be
# appended to CMAKE_PROGRAM_PATH.
#
# With the QUIET option, no status messages will be printed.
#
# Throws a fatal error if any problems are encountered.
#
function(nuget_install pkg)
if(ARGV1 STREQUAL QUIET)
set(quiet TRUE)
endif()

if(NOT EXISTS "${CMAKE_BINARY_DIR}/nuget/nuget.exe")
file_download("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" "${CMAKE_BINARY_DIR}/nuget/nuget.exe" REQUIRED)

# Add nuget package source if not already present.
execute_process(
COMMAND nuget sources add -Name "NuGet official package source" -Source "https://api.nuget.org/v3/index.json"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/nuget"
OUTPUT_QUIET
ERROR_QUIET
)
endif()

if("${pkg}" STREQUAL "")
return()
endif()

execute_process(
COMMAND nuget.exe install "${pkg}" -OutputDirectory "${CMAKE_BINARY_DIR}/nuget"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/nuget"
OUTPUT_VARIABLE install_output
RESULT_VARIABLE install_exit_status
)

if(NOT install_exit_status EQUAL 0)
message(FATAL_ERROR "NuGet installation of package '${pkg}' failed, exit code: ${install_exit_status}")
endif()

string(REGEX REPLACE ".* package '[^0-9]+([0-9.]+)'.*" "\\1" pkg_ver "${install_output}")

set(pkg_dir "${CMAKE_BINARY_DIR}/nuget/${pkg}.${pkg_ver}")

if(NOT IS_DIRECTORY "${pkg_dir}")
message(FATAL_ERROR "NuGet installation of package '${pkg}' failed, package directory '${pkg_dir}' does not exist.")
endif()

if(NOT quiet)
message(STATUS "Installed NuGet package '${pkg}' successfully.")
endif()

set(pkg_bin "${pkg_dir}/tools/bin")

if(IS_DIRECTORY "${pkg_bin}")
list(APPEND CMAKE_PROGRAM_PATH "${pkg_bin}")
set(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH}" PARENT_SCOPE)
set(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH}" CACHE STRING "External Program Search Path" FORCE)

if(NOT quiet)
message(STATUS "Added tools/bin from NuGet package '${pkg}' to CMAKE_PROGRAM_PATH.")
endif()
endif()
endfunction()

# vim:set sw=8 ts=8 noet:
40 changes: 40 additions & 0 deletions contrib/buildsystems/cmake/Utilities.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
#
# file_download(
# url dest_path
# [STATUS status_out_var]
# [REQUIRED]
# )
#
# Wrapper for cmake file(DOWNLOAD ...) with optional error
# checking. If REQUIRED is passed in, a fatal error will be thrown
# on failure. Otherwise if STATUS is passed in, it will store the
# status list in the out var just like file(DOWNLOAD ...).
#
function(file_download url dest_path)
if(NOT url OR NOT dest_path)
message(FATAL_ERROR "file_download: syntax: file_download(url destination_path [OPTIONS]")
endif()

file(DOWNLOAD "${url}" "${dest_path}" STATUS status_list)
list(GET status_list 0 status)

if("STATUS" IN_LIST ARGN)
list(FIND ARGN STATUS status_idx)
math(EXPR out_var_idx "${status_idx} + 1")
list(GET ARGN "${out_var_idx}" out_var)

if("${out_var}" STREQUAL "")
message(FATAL_ERROR "STATUS must be followed by output variable name for the status list.")
endif()

set("${out_var}" "${status_list}" PARENT_SCOPE)
endif()

if ("REQUIRED" IN_LIST ARGN)
if(NOT status EQUAL 0)
list(GET status_list 1 error_str)
message(FATAL_ERROR "Download of '${url}' failed: ${error_str}")
endif()
endif()
endfunction()

#
# build_option(
# opt_name type help_string [default]
Expand Down

0 comments on commit 62ae805

Please sign in to comment.