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..ac06d6ac012c3b 100644 --- a/compat/vcbuild/vcpkg_install.bat +++ b/compat/vcbuild/vcpkg_install.bat @@ -4,25 +4,26 @@ REM This script installs the "vcpkg" source package manager and uses REM it to build the third-party libraries that git requires when it REM is built using MSVC. REM -REM [1] Install VCPKG. -REM [a] Create /compat/vcbuild/vcpkg/ +REM [1] Install VCPKG (unless already exists.) +REM [a] Create %VCPKG_ROOT% defaulting to +REM /compat/vcbuild/vcpkg/. REM [b] Download "vcpkg". REM [c] Compile using the currently installed version of VS. -REM [d] Create /compat/vcbuild/vcpkg/vcpkg.exe +REM [d] Create %VCPKG_ROOT%/vcpkg.exe REM -REM [2] Install third-party libraries. +REM [2] Install third-party libraries (unless already installed.) REM [a] Download each (which may also install CMAKE). REM [b] Compile in RELEASE mode and install in: -REM vcpkg/installed//{bin,lib} +REM %VCPKG_ROOT%/installed//{bin,lib} REM [c] Compile in DEBUG mode and install in: -REM vcpkg/installed//debug/{bin,lib} +REM %VCPKG_ROOT%/installed//debug/{bin,lib} REM [d] Install headers in: -REM vcpkg/installed//include +REM %VCPKG_ROOT%/installed//include REM REM [3] Create a set of MAKE definitions for the top-level REM Makefile to allow "make MSVC=1" to find the above REM third-party libraries. -REM [a] Write vcpkg/VCPGK-DEFS +REM [a] Write %VCPKG_ROOT%/VCPGK-DEFS REM REM https://blogs.msdn.microsoft.com/vcblog/2016/09/19/vcpkg-a-tool-to-acquire-and-build-c-open-source-libraries-on-windows/ REM https://github.com/Microsoft/vcpkg @@ -33,45 +34,55 @@ REM ================================================================ SET arch=%1 IF NOT DEFINED arch ( - echo defaulting to 'x64-windows`. Invoke %0 with 'x86-windows', 'x64-windows', or 'arm64-windows' + echo defaulting to 'x64-windows`. Invoke %0 with 'x86-windows', 'x64-windows', or 'arm64-windows', append '-static' for static builds. >&2 set arch=x64-windows ) @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. >&2 + 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 *** >&2 + echo Git not found. Please adjust your CMD path or Git install option. >&2 + echo *** >&2 + 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 - IF NOT EXIST "packages\%%i_%arch%" CALL :sub__install_one %%i - IF ERRORLEVEL 1 ( EXIT /B 1 ) + echo Installing third-party libraries(%arch%), this may take a while... + FOR %%i IN (zlib expat libiconv openssl libssh2 curl gettext) DO ( + IF NOT DEFINED NO_%%i ( + 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 @@ -129,3 +140,7 @@ goto :EOF :curl_features set features=[core,openssl,schannel] goto :EOF + +:gettext_features +set features=[tools] +goto :EOF diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 8ee457258485b9..c0d0888f3e35d0 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -44,8 +44,19 @@ 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 avoid this, add `-DUSE_VCPKG=FALSE` to +the command line when configuring. + +To use your own vcpkg clone, set the environment variable VCPKG_ROOT +to the path or pass the path as `-DVCPKG_DIR=/your/clone/of/vcpkg`. + +To set the vcpkg arch (target triplet) pass `VCPKG_ARCH` or +`VCPKG_TARGET_TRIPLET` e.g.: `-DVCPKG_ARCH=x64-windows`. + +By default for vcpkg, gettext is not built and translations do not +work because gettext is a very long compile. To enable translations +pass `-DNO_GETTEXT=FALSE`. The Visual Studio default generator changed in v16.6 from its Visual Studio implemenation to `Ninja` This required changes to many CMake scripts. @@ -56,35 +67,57 @@ 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) + +include(Utilities) + 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) endif() +set(gettext_default TRUE) + +# Turn off gettext by default when using vcpkg because it's a very +# long compile. +if(NOT USE_VCPKG) + set(gettext_default FALSE) +endif() + +build_option( + NO_GETTEXT + BOOL "Set to TRUE/ON to disable internationalization support using gettext and building translations using msgfmt from gettext-tools." + ${gettext_default} + ALIASES ENV{NO_GETTEXT} +) + if(NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS) set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) message("settting CMAKE_EXPORT_COMPILE_COMMANDS: ${CMAKE_EXPORT_COMPILE_COMMANDS}") endif() if(USE_VCPKG) - set(VCPKG_DIR "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg") - message("WIN32: ${WIN32}") # show its underlying text values - message("VCPKG_DIR: ${VCPKG_DIR}") - message("VCPKG_ARCH: ${VCPKG_ARCH}") # maybe unset - message("MSVC: ${MSVC}") - message("CMAKE_GENERATOR: ${CMAKE_GENERATOR}") - message("CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}") - 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() + build_option( + VCPKG_DIR + PATH "Path to vcpkg clone." + "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg" + ALIASES ENV{VCPKG_ROOT} + ) + + build_option( + VCPKG_ARCH + STRING "vcpkg arch/triplet, e.g. x64-windows." + x64-windows + ALIASES VCPKG_TARGET_TRIPLET + ) + + message(STATUS "WIN32: ${WIN32}") + message(STATUS "VCPKG_DIR: ${VCPKG_DIR}") + message(STATUS "VCPKG_ARCH: ${VCPKG_ARCH}") + message(STATUS "CMAKE_GENERATOR: ${CMAKE_GENERATOR}") + message(STATUS "CMAKE_EXPORT_COMPILE_COMMANDS: ${CMAKE_EXPORT_COMPILE_COMMANDS}") + message(STATUS "ENV(CMAKE_EXPORT_COMPILE_COMMANDS): $ENV{CMAKE_EXPORT_COMPILE_COMMANDS}") + 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 @@ -123,6 +156,14 @@ project(git VERSION ${git_version} LANGUAGES C) +# Some diagnostic output about the detected toolchain, must be +# below project() call. +if(WIN32) + message(STATUS "MSVC: ${MSVC}") +endif() +message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}") +message(STATUS "CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}") + #TODO gitk git-gui gitweb #TODO Enable NLS on windows natively @@ -173,8 +214,7 @@ find_package(CURL) find_package(EXPAT) find_package(Iconv) -#Don't use libintl on Windows Visual Studio and Clang builds -if(NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL "Clang"))) +if(NOT NO_GETTEXT) find_package(Intl) endif() @@ -207,18 +247,10 @@ 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() +if(NOT NO_GETTEXT) 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 +845,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}) @@ -1033,7 +1066,6 @@ set(NO_PYTHON ) set(PAGER_ENV "LESS=FRX LV=-c") set(DC_SHA1 YesPlease) set(RUNTIME_PREFIX true) -set(NO_GETTEXT ) if(NOT CURL_FOUND) set(NO_CURL 1) @@ -1043,10 +1075,6 @@ if(NOT EXPAT_FOUND) set(NO_EXPAT 1) endif() -if(NOT Intl_FOUND) - set(NO_GETTEXT 1) -endif() - if(NOT PERL_TESTS) set(NO_PERL 1) endif() @@ -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/Utilities.cmake b/contrib/buildsystems/cmake/Utilities.cmake new file mode 100644 index 00000000000000..f90019b7b20c52 --- /dev/null +++ b/contrib/buildsystems/cmake/Utilities.cmake @@ -0,0 +1,102 @@ +# +# 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. If the default is +# empty string or not provided, the value "OFF" is used, this is +# the behavior of option() in cmake. +# +# An alias can be an environment variable, specify ENV{ENV_VAR} in +# this case. If the type is BOOL and the found/default value is +# OFF/FALSE the environment variable will be unset. +# +# 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) + set(aliases "${ARGN}") + + if(default STREQUAL ALIASES) + if(ARGC LESS 5) + message(FATAL_ERROR "build_option: ALIASES specified with no alias names.") + endif() + + unset(default) + elseif(NOT ARGV4 STREQUAL ALIASES) + message(FATAL_ERROR "build_option: Syntax error.") + elseif(ARGC LESS 6) + message(FATAL_ERROR "build_option: ALIASES specified with no alias names.") + else() + list(REMOVE_AT aliases 0) + endif() + + if(default STREQUAL "") + if(NOT type STREQUAL BOOL) + message(FATAL_ERROR "build_option: Empty or unspecified default options must be of type BOOL.") + endif() + + set(default OFF) + endif() + + # First find the first non-empty value in the option and + # aliases, with the priority being the order listed. + # If not found, use the default. + unset(val) + + foreach(var IN LISTS opt aliases) + if(var STREQUAL "") + message(FATAL_ERROR "build_option: Option or alias names cannot be empty string.") + endif() + + set(env_var "") + if(var MATCHES "^ENV\\{") + string( + REGEX REPLACE "^ENV\\{([^}]+)}$" + "\\1" env_var "${var}" + ) + endif() + + if(NOT env_var STREQUAL "") + set(val "$ENV{${env_var}}") + else() + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) + set(val "$CACHE{${var}}") + endif() + + if(val STREQUAL "") + set(val "${${var}}") + endif() + endif() + + if(NOT val STREQUAL "") + break() + endif() + endforeach() + + if(val STREQUAL "") + set(val "${default}") + endif() + + foreach(var IN LISTS opt aliases) + if(var MATCHES "^ENV\\{") + # Unset env var for bool OFF/FALSE. + if(type STREQUAL BOOL AND NOT val) + unset("${var}") + else() + set("${var}" "${val}") + endif() + else() + set("${var}" "${val}" PARENT_SCOPE) + set("${var}" "${val}" CACHE "${type}" "${help_string}" FORCE) + endif() + endforeach() +endfunction() + +# vim:set sw=8 ts=8 noet: