From 396ff7547d8b3f6a933069f048d09380d515a10b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 19 Jun 2019 14:05:59 -0700 Subject: mingw: replace mingw_startup() hack Git for Windows has special code to retrieve the command-line parameters (and even the environment) in UTF-16 encoding, so that they can be converted to UTF-8. This is necessary because Git for Windows wants to use UTF-8 encoded strings throughout its code, and the main() function does not get the parameters in that encoding. To do that, we used the __wgetmainargs() function, which is not even a Win32 API function, but provided by the MINGW "runtime" instead. Obviously, this method would not work with any compiler other than GCC, and in preparation for compiling with Visual C++, we would like to avoid precisely that. Lucky us, there is a much more elegant way: we can simply implement the UTF-16 variant of `main()`: `wmain()`. To make that work, we need to link with -municode. The command-line parameters are passed to `wmain()` encoded in UTF-16, as desired, and this method also works with GCC, and also with Visual C++ after adjusting the MSVC linker flags to force it to use `wmain()`. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 53 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) (limited to 'compat/mingw.c') diff --git a/compat/mingw.c b/compat/mingw.c index 9b6d2400e1..0d8713e515 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2301,18 +2301,13 @@ static void setup_windows_environment(void) setenv("TERM", "cygwin", 1); } +#if !defined(_MSC_VER) /* * Disable MSVCRT command line wildcard expansion (__getmainargs called from * mingw startup code, see init.c in mingw runtime). */ int _CRT_glob = 0; - -typedef struct { - int newmode; -} _startupinfo; - -extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob, - _startupinfo *si); +#endif static NORETURN void die_startup(void) { @@ -2390,22 +2385,25 @@ static void maybe_redirect_std_handles(void) GENERIC_WRITE, FILE_FLAG_NO_BUFFERING); } -void mingw_startup(void) +/* + * We implement wmain() and compile with -municode, which would + * normally ignore main(), but we call the latter from the former + * so that we can handle non-ASCII command-line parameters + * appropriately. + * + * To be more compatible with the core git code, we convert + * argv into UTF8 and pass them directly to main(). + */ +int wmain(int argc, const wchar_t **wargv) { - int i, maxlen, argc; - char *buffer; - wchar_t **wenv, **wargv; - _startupinfo si; + int i, maxlen, exit_status; + char *buffer, **save; + const char **argv; trace2_initialize_clock(); maybe_redirect_std_handles(); - /* get wide char arguments and environment */ - si.newmode = 0; - if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0) - die_startup(); - /* determine size of argv and environ conversion buffer */ maxlen = wcslen(wargv[0]); for (i = 1; i < argc; i++) @@ -2415,9 +2413,16 @@ void mingw_startup(void) maxlen = 3 * maxlen + 1; buffer = malloc_startup(maxlen); - /* convert command line arguments and environment to UTF-8 */ + /* + * Create a UTF-8 version of w_argv. Also create a "save" copy + * to remember all the string pointers because parse_options() + * will remove claimed items from the argv that we pass down. + */ + ALLOC_ARRAY(argv, argc + 1); + ALLOC_ARRAY(save, argc + 1); for (i = 0; i < argc; i++) - __argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen); + argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen); + argv[i] = save[i] = NULL; free(buffer); /* fix Windows specific environment settings */ @@ -2436,6 +2441,16 @@ void mingw_startup(void) /* initialize Unicode console */ winansi_init(); + + /* invoke the real main() using our utf8 version of argv. */ + exit_status = main(argc, argv); + + for (i = 0; i < argc; i++) + free(save[i]); + free(save); + free(argv); + + return exit_status; } int uname(struct utsname *buf) -- cgit v1.2.3 From 12fb9bd85ee9e673c70df90cf5a926e82d98eda8 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Wed, 19 Jun 2019 14:06:02 -0700 Subject: msvc: mark a variable as non-const VS2015 complains when using a const pointer in memcpy()/free(). Signed-off-by: Jeff Hostetler Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'compat/mingw.c') diff --git a/compat/mingw.c b/compat/mingw.c index 0d8713e515..d14d33308d 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1553,7 +1553,10 @@ static int try_shell_exec(const char *cmd, char *const *argv) if (prog) { int exec_id; int argc = 0; - const char **argv2; +#ifndef _MSC_VER + const +#endif + char **argv2; while (argv[argc]) argc++; ALLOC_ARRAY(argv2, argc + 1); argv2[0] = (char *)cmd; /* full path to the script file */ -- cgit v1.2.3 From dce7d295514f0acebb897cc37a451963d60588f5 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Tue, 25 Jun 2019 07:49:39 -0700 Subject: msvc: support building Git using MS Visual C++ With this patch, Git can be built using the Microsoft toolchain, via: make MSVC=1 [DEBUG=1] Third party libraries are built from source using the open source "vcpkg" tool set. See https://github.com/Microsoft/vcpkg On a first build, the vcpkg tools and the third party libraries are automatically downloaded and built. DLLs for the third party libraries are copied to the top-level (and t/helper) directory to facilitate debugging. See compat/vcbuild/README. A series of .bat files are invoked by the Makefile to find the location of the installed version of Visual Studio and the associated compiler tools (essentially replicating the environment setup performed by a "Developer Command Prompt"). This should find the most recent VS2015 or VS2017 installation. Output from these scripts are used by the Makefile to define compiler and linker pathnames and -I and -L arguments. The build produces .pdb files for both debug and release builds. Note: This commit was squashed from an organic series of commits developed between 2016 and 2018 in Git for Windows' `master` branch. This combined commit eliminates the obsolete commits related to fetching NuGet packages for third party libraries. It is difficult to use NuGet packages for C/C++ sources because they may be built by earlier versions of the MSVC compiler and have CRT version and linking issues. Additionally, the C/C++ NuGet packages that we were using tended to not be updated concurrently with the sources. And in the case of cURL and OpenSSL, this could expose us to security issues. Helped-by: Yue Lin Ho Helped-by: Philip Oakley Signed-off-by: Jeff Hostetler Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'compat/mingw.c') diff --git a/compat/mingw.c b/compat/mingw.c index d14d33308d..c063ae62be 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2388,6 +2388,12 @@ static void maybe_redirect_std_handles(void) GENERIC_WRITE, FILE_FLAG_NO_BUFFERING); } +#ifdef _MSC_VER +#ifdef _DEBUG +#include +#endif +#endif + /* * We implement wmain() and compile with -municode, which would * normally ignore main(), but we call the latter from the former -- cgit v1.2.3 From 556702f86cb043f18bf46dceec25fe1e783c4590 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Tue, 25 Jun 2019 07:49:40 -0700 Subject: msvc: add a compile-time flag to allow detailed heap debugging MS Visual C comes with a few neat features we can use to analyze the heap consumption (i.e. leaks, max memory, etc). With this patch, we introduce support via the build-time flag `USE_MSVC_CRTDBG`. Signed-off-by: Jeff Hostetler Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'compat/mingw.c') diff --git a/compat/mingw.c b/compat/mingw.c index c063ae62be..667285887a 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2411,6 +2411,12 @@ int wmain(int argc, const wchar_t **wargv) trace2_initialize_clock(); +#ifdef _MSC_VER +#ifdef USE_MSVC_CRTDBG + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#endif +#endif + maybe_redirect_std_handles(); /* determine size of argv and environ conversion buffer */ -- cgit v1.2.3 From 446df60367be5f3a97f7bac12071878d1fdbebd2 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Tue, 25 Jun 2019 07:49:41 -0700 Subject: msvc: do not pretend to support all signals This special-cases various signals that are not supported on Windows, such as SIGPIPE. These cause the UCRT to throw asserts (at least in debug mode). Signed-off-by: Jeff Hostetler Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'compat/mingw.c') diff --git a/compat/mingw.c b/compat/mingw.c index 667285887a..d01e88c2f8 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2119,8 +2119,33 @@ int mingw_raise(int sig) sigint_fn(SIGINT); return 0; +#if defined(_MSC_VER) + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGTERM: + case SIGBREAK: + case SIGABRT: + case SIGABRT_COMPAT: + /* + * The header in the MS C Runtime defines 8 signals + * as being supported on the platform. Anything else causes an + * "Invalid signal or error" (which in DEBUG builds causes the + * Abort/Retry/Ignore dialog). We by-pass the CRT for things we + * already know will fail. + */ + return raise(sig); + default: + errno = EINVAL; + return -1; + +#else + default: return raise(sig); + +#endif + } } -- cgit v1.2.3 From f6a6393771b1f9676f6c019b6e9d35ef172a79e9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 25 Jun 2019 07:49:42 -0700 Subject: msvc: avoid debug assertion windows in Debug Mode For regular debugging, it is pretty helpful when a debug assertion in a running application triggers a window that offers to start the debugger. However, when running the test suite, it is not so helpful, in particular when the debug assertions are then suppressed anyway because we disable the invalid parameter checking (via invalidcontinue.obj, see the comment in config.mak.uname about that object for more information). So let's simply disable that window in Debug Mode (it is already disabled in Release Mode). Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'compat/mingw.c') diff --git a/compat/mingw.c b/compat/mingw.c index d01e88c2f8..433838391f 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2437,6 +2437,10 @@ int wmain(int argc, const wchar_t **wargv) trace2_initialize_clock(); #ifdef _MSC_VER +#ifdef _DEBUG + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); +#endif + #ifdef USE_MSVC_CRTDBG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif -- cgit v1.2.3