Skip to content

Commit

Permalink
Cmake: use ENV{VCPKG_ROOT}, fix msgfmt + minor.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
rkitover committed Feb 6, 2022
1 parent 5437f0f commit b8d2ed4
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,4 @@ Release/
*.dSYM
/contrib/buildsystems/out
CMakeSettings.json
build*/
30 changes: 19 additions & 11 deletions compat/vcbuild/vcpkg_install.bat
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 53 additions & 23 deletions contrib/buildsystems/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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})


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1106,3 +1134,5 @@ foreach(tsh ${test_scipts})
endforeach()

endif()#BUILD_TESTING

# vim:set sw=8 ts=8 noet:
59 changes: 59 additions & 0 deletions contrib/buildsystems/cmake/NuGet.cmake
Original file line number Diff line number Diff line change
@@ -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:
60 changes: 60 additions & 0 deletions contrib/buildsystems/cmake/Utilities.cmake
Original file line number Diff line number Diff line change
@@ -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:

0 comments on commit b8d2ed4

Please sign in to comment.