From 3eccc7b99d4f47991ca3a647ad27680a45a82517 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 25 Sep 2020 14:28:29 +0000 Subject: [PATCH 01/10] cmake: ignore files generated by CMake as run in Visual Studio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of recent Visual Studio versions, CMake support is built-in: https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=vs-2019 All that needs to be done is to open the worktree as a folder, and Visual Studio will find the `CMakeLists.txt` file and automatically generate the project files. Let's ignore the entirety of those generated files. Helped-by: Đoàn Trần Công Danh Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d0f692a35520bc..6521f3cf22baa0 100644 --- a/.gitignore +++ b/.gitignore @@ -241,3 +241,4 @@ Release/ /git.VC.VC.opendb /git.VC.db *.dSYM +/contrib/buildsystems/out From 72b6eeb81b163d3b9e4e9546f8041160b2d759c9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 28 Sep 2020 21:09:07 +0000 Subject: [PATCH 02/10] cmake: do find Git for Windows' shell interpreter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default, Git for Windows does not install its `sh.exe` into the `PATH`. However, our current `CMakeLists.txt` expects to find a shell interpreter in the `PATH`. So let's fall back to looking in the default location where Git for Windows _does_ install a relatively convenient `sh.exe`: `C:\Program Files\Git\bin\sh.exe` Helped-by: Øystein Walle Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 5007f173f1ed32..1847a6fd581544 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -41,7 +41,7 @@ cmake_minimum_required(VERSION 3.14) #set the source directory to root of git set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -find_program(SH_EXE sh) +find_program(SH_EXE sh PATHS "C:/Program Files/Git/bin") if(NOT SH_EXE) message(FATAL_ERROR "sh: shell interpreter was not found in your path, please install one." "On Windows, you can get it as part of 'Git for Windows' install at https://gitforwindows.org/") From e18ae4e7a6cd687ba9dac8be1e88a3d99f676fd5 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 28 Sep 2020 21:09:08 +0000 Subject: [PATCH 03/10] cmake: ensure that the `vcpkg` packages are found on Windows On Windows, we use the `vcpkg` project to manage the dependencies, via `compat/vcbuild/`. Let's make sure that these dependencies are found by default. This is needed because we are about to recommend loading the Git worktree as a folder into Visual Studio, relying on the automatic CMake support (which would make it relatively cumbersome to adjust the search path used by CMake manually). Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 1847a6fd581544..12268f61bab207 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -40,6 +40,13 @@ cmake_minimum_required(VERSION 3.14) #set the source directory to root of git set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +if(WIN32) + set(VCPKG_DIR "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg") + list(APPEND CMAKE_PREFIX_PATH "${VCPKG_DIR}/installed/x64-windows") + + # In the vcpkg edition, we need this to be able to link to libcurl + set(CURL_NO_CURL_CMAKE ON) +endif() find_program(SH_EXE sh PATHS "C:/Program Files/Git/bin") if(NOT SH_EXE) From 8f4513872517b72fb49d914ee9af8d44c836fc5a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Sep 2020 15:26:18 +0000 Subject: [PATCH 04/10] cmake: fall back to using `vcpkg`'s `msgfmt.exe` on Windows We are already relying on `vcpkg` to manage our dependencies, including `libiconv`. Let's also use the `msgfmt.exe` from there. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 12268f61bab207..02241dcc7784f6 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -152,7 +152,11 @@ endif() find_program(MSGFMT_EXE msgfmt) if(NOT MSGFMT_EXE) - message(WARNING "Text Translations won't be build") + set(MSGFMT_EXE ${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg/downloads/tools/msys2/msys64/usr/bin/msgfmt.exe) + if(NOT EXISTS ${MSGFMT_EXE}) + message(WARNING "Text Translations won't be built") + unset(MSGFMT_EXE) + endif() endif() #Force all visual studio outputs to CMAKE_BINARY_DIR From f1bd7379570d74f5ea70ef8bb89fa82d9a219c8e Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Sep 2020 15:26:19 +0000 Subject: [PATCH 05/10] cmake: quote the path accurately when editing `test-lib.sh` By default, the build directory will be called something like `contrib/buildsystems/out/build/x64-Debug (default)` (note the space and the parentheses). We need to make sure that such a path is quoted properly when editing the assignment of the `GIT_BUILD_DIR` variable. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 02241dcc7784f6..3bb74337e118de 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -949,7 +949,7 @@ if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH}) file(WRITE ${CMAKE_BINARY_DIR}/CTestCustom.cmake "file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh GIT_BUILD_DIR_REPL REGEX \"GIT_BUILD_DIR=(.*)\")\n" "file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh content NEWLINE_CONSUME)\n" - "string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY\\\"/../${BUILD_DIR_RELATIVE}\" content \"\${content}\")\n" + "string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY/../${BUILD_DIR_RELATIVE}\\\"\" content \"\${content}\")\n" "file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})") #misc copies file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/) From 8c35e82898f6418bb010c2f3bb5025b52023ba91 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Sep 2020 15:26:20 +0000 Subject: [PATCH 06/10] cmake (Windows): let the `.dll` files be found when running the tests Contrary to Unix-ish platforms, the dependencies' shared libraries are not usually found in one central place. In our case, since we use `vcpkg`, they are to be found inside the `compat/vcbuild/vcpkg/` tree. Let's make sure that they are in the search path when running the tests. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 3bb74337e118de..55d09600022d87 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -939,6 +939,9 @@ file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "X='${EXE_EXTENSION}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_GETTEXT='${NO_GETTEXT}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "RUNTIME_PREFIX='${RUNTIME_PREFIX}'\n") file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PYTHON='${NO_PYTHON}'\n") +if(WIN32) + file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\"\n") +endif() #Make the tests work when building out of the source tree get_filename_component(CACHE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../CMakeCache.txt ABSOLUTE) From 2d9eb4ed2cd8a0105c65167fdc9ddb0ddcde42c5 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Sep 2020 15:26:21 +0000 Subject: [PATCH 07/10] cmake (Windows): complain when encountering an unknown compiler We have some custom handling regarding the link options, which are specific to each compiler. Therefore: let's not just continue without setting the link options if configuring for a currently unhandled compiler, but error out. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 55d09600022d87..78b90abe5ebd41 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -617,6 +617,8 @@ if(WIN32) target_link_options(common-main PUBLIC -municode -Wl,-nxcompat -Wl,-dynamicbase -Wl,-entry:wmainCRTStartup -Wl,invalidcontinue.obj) elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") target_link_options(common-main PUBLIC /IGNORE:4217 /IGNORE:4049 /NOLOGO /ENTRY:wmainCRTStartup /SUBSYSTEM:CONSOLE invalidcontinue.obj) + else() + message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}") endif() elseif(UNIX) target_link_libraries(common-main pthread rt) From b490283d5200952b87f49ac43457da7a332b4598 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Sep 2020 15:26:22 +0000 Subject: [PATCH 08/10] cmake (Windows): initialize vcpkg/build dependencies automatically The idea of having CMake support in Git's source tree is to enable contributors on Windows to start contributing with little effort. To that end, we just added some sensible defaults that will let users open the worktree in Visual Studio and start building. This expects the dependencies (such as zlib) to be available already, though. If they are not available, we expect the user to run `compat/vcbuild/vcpkg_install.bat`. Rather than requiring this step to be manual, detect the situation and run it as part of the CMake configuration step. Note that this obviously only applies to the scenario when we want to compile in Visual Studio (i.e. with MS Visual C), not with GCC. Therefore, we guard this new code block behind the `MSVC` conditional. This concludes our journey to make it as effortless as possible to start developing Git in Visual Studio: all the developer needs to do is to clone Git's repository, open the worktree via `File>Open>Folder...` and wait for CMake to finish configuring. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 78b90abe5ebd41..ebadae22711ca3 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -42,6 +42,10 @@ cmake_minimum_required(VERSION 3.14) set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) if(WIN32) set(VCPKG_DIR "${CMAKE_SOURCE_DIR}/compat/vcbuild/vcpkg") + if(MSVC AND 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) + endif() list(APPEND CMAKE_PREFIX_PATH "${VCPKG_DIR}/installed/x64-windows") # In the vcpkg edition, we need this to be able to link to libcurl From f2f1250c47fd967b7678cad329438e8deac62038 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Sep 2020 15:26:23 +0000 Subject: [PATCH 09/10] cmake (Windows): recommend using Visual Studio's built-in CMake support It is a lot more convenient to use than having to specify the configuration in CMake manually (does not matter whether using the command-line or CMake's GUI). While at it, recommend using `contrib/buildsystems/out/` as build directory also in the part that talks about running CMake manually. Helped-by: Junio C Hamano Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- contrib/buildsystems/CMakeLists.txt | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index ebadae22711ca3..df539a44fa0a1b 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -4,17 +4,25 @@ #[[ -Instructions to run CMake: +Instructions how to use this in Visual Studio: -cmake `relative-path-to-CMakeLists.txt` -DCMAKE_BUILD_TYPE=Release -Eg. -From the root of git source tree - `cmake contrib/buildsystems/ ` -This will build the git binaries at the root +Open the worktree as a folder. Visual Studio 2019 and later will detect +the CMake configuration automatically and set everything up for you, +ready to build. You can then run the tests in `t/` via a regular Git Bash. -For out of source builds, say build in 'git/git-build/' - `mkdir git-build;cd git-build; cmake ../contrib/buildsystems/` -This will build the git binaries in git-build directory +Note: Visual Studio also has the option of opening `CMakeLists.txt` +directly; Using this option, Visual Studio will not find the source code, +though, therefore the `File>Open>Folder...` option is preferred. + +Instructions to run CMake manually: + + mkdir -p contrib/buildsystems/out + cd contrib/buildsystems/out + cmake ../ -DCMAKE_BUILD_TYPE=Release + +This will build the git binaries in contrib/buildsystems/out +directory (our top-level .gitignore file knows to ignore contents of +this directory). Possible build configurations(-DCMAKE_BUILD_TYPE) with corresponding compiler flags From 0ad621f61e4b2adc3a7bad088c25ebf2c8b9f43d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 30 Sep 2020 15:26:24 +0000 Subject: [PATCH 10/10] hashmap_for_each_entry(): workaround MSVC's runtime check failure #3 The OFFSETOF_VAR(var, member) macro is implemented in terms of offsetof(typeof(*var), member) with compilers that know typeof(), but its fallback implemenation compares &(var->member) and (var) and count the distance in bytes, i.e. ((uintptr_t)&(var)->member - (uintptr_t)(var)) MSVC's runtime check, when fed an uninitialized 'var', flags this as a use of an uninitialized variable (and that is legit---uninitialized contents of 'var' is subtracted) in a debug build. After auditing all 6 uses of OFFSETOF_VAR(), 1 of them does feed a potentially uninitialized 'var' to the macro in the beginning of the for() loop: #define hashmap_for_each_entry(map, iter, var, member) \ for (var = hashmap_iter_first_entry_offset(map, iter, \ OFFSETOF_VAR(var, member)); \ var; \ var = hashmap_iter_next_entry_offset(iter, \ OFFSETOF_VAR(var, member))) We can work around this by making sure that var has _some_ value when OFFSETOF_VAR() is called. Strictly speaking, it invites undefined behaviour to use NULL here if we end up with pointer comparison, but MSVC runtime seems to be happy with it, and most other systems have typeof() and don't even need pointer comparison fallback code. Signed-off-by: Junio C Hamano Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- hashmap.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hashmap.h b/hashmap.h index ef220de4c64dab..b011b394fefe34 100644 --- a/hashmap.h +++ b/hashmap.h @@ -449,7 +449,8 @@ static inline struct hashmap_entry *hashmap_iter_first(struct hashmap *map, * containing a @member which is a "struct hashmap_entry" */ #define hashmap_for_each_entry(map, iter, var, member) \ - for (var = hashmap_iter_first_entry_offset(map, iter, \ + for (var = NULL, /* for systems without typeof */ \ + var = hashmap_iter_first_entry_offset(map, iter, \ OFFSETOF_VAR(var, member)); \ var; \ var = hashmap_iter_next_entry_offset(iter, \