From b8d2ed43b636603e1171acf9d3a0700f44403a2e Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Sun, 6 Feb 2022 22:34:48 +0000 Subject: [PATCH] Cmake: use ENV{VCPKG_ROOT}, fix msgfmt + minor. Set VCPKG_DIR from ENV{VCPKG_ROOT} if set, otherwise set ENV{VCPKG_ROOT}. Set VCPKG_ARCH from VCPKG_TARGET_TRIPLET if set. Fix check for VCPKG_ARCH being defined. Describe options in comment at the top of the file. Add build*/ out-of-source build dirs to toplevel .gitignore. Change vcpkg_install.bat to use %VCPKG_ROOT% set by cmake or present in the environment, and update/install only what's necessary. Use Gettext.Tools from nuget on Windows for msgfmt. Fix cmake hardlinking script invocation by adding WORKING_DIRECTORY. Signed-off-by: Rafael Kitover --- .gitignore | 1 + compat/vcbuild/vcpkg_install.bat | 30 +++++---- contrib/buildsystems/CMakeLists.txt | 76 +++++++++++++++------- contrib/buildsystems/cmake/NuGet.cmake | 59 +++++++++++++++++ contrib/buildsystems/cmake/Utilities.cmake | 60 +++++++++++++++++ 5 files changed, 192 insertions(+), 34 deletions(-) create mode 100644 contrib/buildsystems/cmake/NuGet.cmake create mode 100644 contrib/buildsystems/cmake/Utilities.cmake diff --git a/.gitignore b/.gitignore index ff241d0cec571f..0ba169f30a5830 100644 --- a/.gitignore +++ b/.gitignore @@ -245,3 +245,4 @@ Release/ *.dSYM /contrib/buildsystems/out CMakeSettings.json +build*/ diff --git a/compat/vcbuild/vcpkg_install.bat b/compat/vcbuild/vcpkg_install.bat index 575c65c20ba307..52d987d59ef4f3 100644 --- a/compat/vcbuild/vcpkg_install.bat +++ b/compat/vcbuild/vcpkg_install.bat @@ -40,38 +40,46 @@ REM ================================================================ @FOR /F "delims=" %%D IN ("%~dp0") DO @SET cwd=%%~fD cd %cwd% - dir vcpkg\vcpkg.exe >nul 2>nul && GOTO :install_libraries + IF NOT DEFINED VCPKG_ROOT ( + set VCPKG_ROOT=%cwd%\vcpkg + ) ELSE (IF NOT EXIST %VCPKG_ROOT%\..\ ( + echo Invalid VCPKG_ROOT: %VCPKG_ROOT%, not under a valid directory. + exit /B 1 + )) + + IF EXIST %VCPKG_ROOT%\vcpkg.exe goto :install_libraries git.exe version 2>nul IF ERRORLEVEL 1 ( - echo "***" - echo "Git not found. Please adjust your CMD path or Git install option." - echo "***" - EXIT /B 1 ) + echo *** + echo Git not found. Please adjust your CMD path or Git install option. + echo *** + EXIT /B 1 + ) - echo Fetching vcpkg in %cwd%vcpkg - git.exe clone https://github.com/Microsoft/vcpkg vcpkg + echo Fetching vcpkg in %VCPKG_ROOT% + git.exe clone https://github.com/Microsoft/vcpkg %VCPKG_ROOT% IF ERRORLEVEL 1 ( EXIT /B 1 ) - cd vcpkg + cd %VCPKG_ROOT% echo Building vcpkg powershell -exec bypass scripts\bootstrap.ps1 IF ERRORLEVEL 1 ( EXIT /B 1 ) - echo Successfully installed %cwd%vcpkg\vcpkg.exe + echo Successfully installed %VCPKG_ROOT%\vcpkg.exe :install_libraries echo Installing third-party libraries(%arch%)... FOR %%i IN (zlib expat libiconv openssl libssh2 curl) DO ( - cd %cwd%vcpkg + cd %VCPKG_ROOT% IF NOT EXIST "packages\%%i_%arch%" CALL :sub__install_one %%i IF ERRORLEVEL 1 ( EXIT /B 1 ) ) :install_defines cd %cwd% - SET inst=%cwd%vcpkg\installed\%arch% + SET inst=%VCPKG_ROOT%\installed\%arch% echo vcpkg_inc=-I"%inst%\include">VCPKG-DEFS echo vcpkg_rel_lib=-L"%inst%\lib">>VCPKG-DEFS diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 8ee457258485b9..4e9ae781e26709 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -44,8 +44,15 @@ This process generates a Makefile(Linux/*BSD/MacOS), Visual Studio solution(Wind Run `make` to build Git on Linux/*BSD/MacOS. Open git.sln on Windows and build Git. -NOTE: By default CMake will install vcpkg locally to your source tree on configuration, -to avoid this, add `-DNO_VCPKG=TRUE` to the command line when configuring. +NOTE: By default CMake will install vcpkg locally to your source tree on +configuration, to use your own VCPKG tree, set `$env:VCPKG_ROOT` to the +path or pass `VCPKG_DIR`. + +To set the vcpkg arch (target triplet) pass `VCPKG_ARCH` e.g.: +`-DVCPKG_ARCH=x64-windows`. + +To not use VCPKG, add `-DUSE_VCPKG=FALSE` to the command line when +configuring. The Visual Studio default generator changed in v16.6 from its Visual Studio implemenation to `Ninja` This required changes to many CMake scripts. @@ -56,6 +63,8 @@ cmake_minimum_required(VERSION 3.14) #set the source directory to root of git set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + option(USE_VCPKG "Whether or not to use vcpkg for obtaining dependencies. Only applicable to Windows platforms" ON) if(NOT WIN32) set(USE_VCPKG OFF CACHE BOOL FORCE) @@ -67,7 +76,27 @@ if(NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS) endif() if(USE_VCPKG) - set(VCPKG_DIR "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg") + if(NOT DEFINED VCPKG_DIR) + if(DEFINED ENV{VCPKG_ROOT}) + set(VCPKG_DIR "$ENV{VCPKG_ROOT}") + else() + set(VCPKG_DIR "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg") + endif() + + # Make sure ENV{VCPKG_ROOT} is set for vcpkg_install.bat + # and anything else that may need it. + set(ENV{VCPKG_ROOT} "${VCPKG_DIR}") + endif() + + if(NOT DEFINED VCPKG_ARCH) + if(DEFINED VCPKG_TARGET_TRIPLET) + set(VCPKG_ARCH "${VCPKG_TARGET_TRIPLET}") + else() + message("VCPKG_ARCH: unset, using 'x64-windows'") + set(VCPKG_ARCH "x64-windows") + endif() + endif() + message("WIN32: ${WIN32}") # show its underlying text values message("VCPKG_DIR: ${VCPKG_DIR}") message("VCPKG_ARCH: ${VCPKG_ARCH}") # maybe unset @@ -77,14 +106,8 @@ if(USE_VCPKG) message("CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}") message("CMAKE_EXPORT_COMPILE_COMMANDS: ${CMAKE_EXPORT_COMPILE_COMMANDS}") message("ENV(CMAKE_EXPORT_COMPILE_COMMANDS): $ENV{CMAKE_EXPORT_COMPILE_COMMANDS}") - if(NOT EXISTS ${VCPKG_DIR}) - message("Initializing vcpkg and building the Git's dependencies (this will take a while...)") - execute_process(COMMAND ${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg_install.bat ${VCPKG_ARCH}) - endif() - if(NOT EXISTS ${VCPKG_ARCH}) - message("VCPKG_ARCH: unset, using 'x64-windows'") - set(VCPKG_ARCH "x64-windows") # default from vcpkg_install.bat - endif() + message("Initializing vcpkg and building the Git's dependencies (this may take a while...)") + execute_process(COMMAND ${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg_install.bat ${VCPKG_ARCH}) list(APPEND CMAKE_PREFIX_PATH "${VCPKG_DIR}/installed/${VCPKG_ARCH}") # In the vcpkg edition, we need this to be able to link to libcurl @@ -207,18 +230,22 @@ if(WIN32 AND NOT MSVC)#not required for visual studio builds endif() endif() -if(NO_GETTEXT) - message(STATUS "msgfmt not used under NO_GETTEXT") -else() + +find_program(MSGFMT_EXE msgfmt) + +if(NOT MSGFMT_EXE) + if(WIN32) + include(NuGet) + nuget_install(Gettext.Tools) + endif() + + unset(MSGFMT_EXE) + unset(MSGFMT_EXE CACHE) + find_program(MSGFMT_EXE msgfmt) + if(NOT MSGFMT_EXE) - if(USE_VCPKG) - set(MSGFMT_EXE ${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg/downloads/tools/msys2/msys64/usr/bin/msgfmt.exe) - endif() - if(NOT EXISTS ${MSGFMT_EXE}) - message(WARNING "Text Translations won't be built") - unset(MSGFMT_EXE) - endif() + message(WARNING "msgfmt not available and/or could not be installed, text translations won't be built.") endif() endif() @@ -813,7 +840,8 @@ endif() add_custom_command(OUTPUT ${git_links} ${git_http_links} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/CreateLinks.cmake - DEPENDS git git-remote-http) + DEPENDS git git-remote-http + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_custom_target(git-links ALL DEPENDS ${git_links} ${git_http_links}) @@ -1074,7 +1102,7 @@ file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "RUNTIME_PREFIX='${RUNTIME_PRE file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PYTHON='${NO_PYTHON}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "SUPPORTS_SIMPLE_IPC='${SUPPORTS_SIMPLE_IPC}'\n") if(USE_VCPKG) - file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/${VCPKG_ARCH}/bin\"\n") + file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PATH=\"$PATH:${VCPKG_DIR}/installed/${VCPKG_ARCH}/bin\"\n") endif() #Make the tests work when building out of the source tree @@ -1106,3 +1134,5 @@ foreach(tsh ${test_scipts}) endforeach() endif()#BUILD_TESTING + +# vim:set sw=8 ts=8 noet: diff --git a/contrib/buildsystems/cmake/NuGet.cmake b/contrib/buildsystems/cmake/NuGet.cmake new file mode 100644 index 00000000000000..dd5b0a71b755e8 --- /dev/null +++ b/contrib/buildsystems/cmake/NuGet.cmake @@ -0,0 +1,59 @@ +include(Utilities) + +# +# nuget_install([pkg_name]) +# +# 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. +# +# Throws a fatal error if any problems are encountered. +# +function(nuget_install pkg) + if(NOT EXISTS "${CMAKE_BINARY_DIR}/nuget.exe") + file_download("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" "${CMAKE_BINARY_DIR}/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}" + 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}" + 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() + + 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) + endif() +endfunction() + +# vim:set sw=8 ts=8 noet: diff --git a/contrib/buildsystems/cmake/Utilities.cmake b/contrib/buildsystems/cmake/Utilities.cmake new file mode 100644 index 00000000000000..22b440a2d7f8ff --- /dev/null +++ b/contrib/buildsystems/cmake/Utilities.cmake @@ -0,0 +1,60 @@ +# +# 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] +# ["ALIASES" alias1 [alias2 ...]] +# ) +# +# If PRIMARY_OPT is not set, uses the value of any alias name +# provided, in order of precedence provides, to set PRIMARY_OPT and +# all listed aliases. Otherwise set all aliases to the value of +# PRIMARY_OPT, or the default if not set either. +# +# On cmake >= 3.13 precedence is given to CACHE variables, and the +# namesake normal variable is overwritten with the CACHE value. On +# earlier versions, the cache variable will be overwritten with the +# normal variable. +# +function(build_option opt type help_string default) +endfunction() + +# vim:set sw=8 ts=8 noet: