Skip to content

Commit 20bd64b

Browse files
committed
Merge pull request #2974 from derrickstolee/maintenance-and-headless
Include Windows-specific maintenance and headless-git
2 parents cffeab9 + bebcf1e commit 20bd64b

File tree

10 files changed

+247
-13
lines changed

10 files changed

+247
-13
lines changed

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2810,6 +2810,13 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
28102810
compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null
28112811
endif
28122812

2813+
headless-git.o: compat/win32/headless.c GIT-CFLAGS
2814+
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
2815+
-fno-stack-protector -o $@ -c -Wall -Wwrite-strings $<
2816+
2817+
headless-git$X: headless-git.o git.res GIT-LDFLAGS
2818+
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -mwindows -o $@ $< git.res
2819+
28132820
git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
28142821
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
28152822

@@ -3683,6 +3690,7 @@ clean: profile-clean coverage-clean cocciclean
36833690
$(RM) po/git.pot po/git-core.pot
36843691
$(RM) git.res
36853692
$(RM) $(OBJECTS)
3693+
$(RM) headless-git.o
36863694
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
36873695
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
36883696
$(RM) $(TEST_PROGRAMS)
@@ -3711,13 +3719,17 @@ endif
37113719
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
37123720
ifdef MSVC
37133721
$(RM) $(patsubst %.o,%.o.pdb,$(OBJECTS))
3722+
$(RM) headless-git.o.pdb
37143723
$(RM) $(patsubst %.exe,%.pdb,$(OTHER_PROGRAMS))
3724+
$(RM) $(patsubst %.exe,%.ilk,$(OTHER_PROGRAMS))
37153725
$(RM) $(patsubst %.exe,%.iobj,$(OTHER_PROGRAMS))
37163726
$(RM) $(patsubst %.exe,%.ipdb,$(OTHER_PROGRAMS))
37173727
$(RM) $(patsubst %.exe,%.pdb,$(PROGRAMS))
3728+
$(RM) $(patsubst %.exe,%.ilk,$(PROGRAMS))
37183729
$(RM) $(patsubst %.exe,%.iobj,$(PROGRAMS))
37193730
$(RM) $(patsubst %.exe,%.ipdb,$(PROGRAMS))
37203731
$(RM) $(patsubst %.exe,%.pdb,$(TEST_PROGRAMS))
3732+
$(RM) $(patsubst %.exe,%.ilk,$(TEST_PROGRAMS))
37213733
$(RM) $(patsubst %.exe,%.iobj,$(TEST_PROGRAMS))
37223734
$(RM) $(patsubst %.exe,%.ipdb,$(TEST_PROGRAMS))
37233735
$(RM) compat/vcbuild/MSVC-DEFS-GEN

builtin/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2064,7 +2064,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
20642064
"</Settings>\n"
20652065
"<Actions Context=\"Author\">\n"
20662066
"<Exec>\n"
2067-
"<Command>\"%s\\git.exe\"</Command>\n"
2067+
"<Command>\"%s\\headless-git.exe\"</Command>\n"
20682068
"<Arguments>--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
20692069
"</Exec>\n"
20702070
"</Actions>\n"

compat/vcbuild/find_vs_env.bat

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ REM ================================================================
9999

100100
SET sdk_dir=%WindowsSdkDir%
101101
SET sdk_ver=%WindowsSDKVersion%
102+
SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%%tgt%
102103
SET si=%sdk_dir%Include\%sdk_ver%
103104
SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared"
104105
SET sl=%sdk_dir%lib\%sdk_ver%
@@ -130,6 +131,7 @@ REM ================================================================
130131

131132
SET sdk_dir=%WindowsSdkDir%
132133
SET sdk_ver=%WindowsSDKVersion%
134+
SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%bin\amd64
133135
SET si=%sdk_dir%Include\%sdk_ver%
134136
SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared" -I"%si%winrt"
135137
SET sl=%sdk_dir%lib\%sdk_ver%
@@ -160,6 +162,11 @@ REM ================================================================
160162
echo msvc_includes=%msvc_includes%
161163
echo msvc_libs=%msvc_libs%
162164

165+
echo sdk_ver_bin_dir=%sdk_ver_bin_dir%
166+
SET X1=%sdk_ver_bin_dir:C:=/C%
167+
SET X2=%X1:\=/%
168+
echo sdk_ver_bin_dir_msys=%X2%
169+
163170
echo sdk_includes=%sdk_includes%
164171
echo sdk_libs=%sdk_libs%
165172

compat/vcbuild/scripts/clink.pl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
my @lflags = ();
1616
my $is_linking = 0;
1717
my $is_debug = 0;
18+
my $is_gui = 0;
1819
while (@ARGV) {
1920
my $arg = shift @ARGV;
2021
if ("$arg" eq "-DDEBUG") {
@@ -67,7 +68,11 @@
6768
}
6869
push(@args, $lib);
6970
} elsif ("$arg" eq "-lexpat") {
71+
if ($is_debug) {
72+
push(@args, "libexpatd.lib");
73+
} else {
7074
push(@args, "libexpat.lib");
75+
}
7176
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
7277
$arg =~ s/^-L/-LIBPATH:/;
7378
push(@lflags, $arg);
@@ -119,11 +124,23 @@
119124
push(@cflags, "-wd4996");
120125
} elsif ("$arg" =~ /^-W[a-z]/) {
121126
# let's ignore those
127+
} elsif ("$arg" eq "-fno-stack-protector") {
128+
# eat this
129+
} elsif ("$arg" eq "-mwindows") {
130+
$is_gui = 1;
122131
} else {
123132
push(@args, $arg);
124133
}
125134
}
126135
if ($is_linking) {
136+
if ($is_gui) {
137+
push(@args, "-ENTRY:wWinMainCRTStartup");
138+
push(@args, "-SUBSYSTEM:WINDOWS");
139+
} else {
140+
push(@args, "-ENTRY:wmainCRTStartup");
141+
push(@args, "-SUBSYSTEM:CONSOLE");
142+
}
143+
127144
push(@args, @lflags);
128145
unshift(@args, "link.exe");
129146
} else {

compat/vcbuild/scripts/rc.pl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/perl -w
2+
######################################################################
3+
# Compile Resources on Windows
4+
#
5+
# This is a wrapper to facilitate the compilation of Git with MSVC
6+
# using GNU Make as the build system. So, instead of manipulating the
7+
# Makefile into something nasty, just to support non-space arguments
8+
# etc, we use this wrapper to fix the command line options
9+
#
10+
######################################################################
11+
use strict;
12+
my @args = ();
13+
my @input = ();
14+
15+
while (@ARGV) {
16+
my $arg = shift @ARGV;
17+
if ("$arg" =~ /^-[dD]/) {
18+
# GIT_VERSION gets passed with too many
19+
# layers of dquote escaping.
20+
$arg =~ s/\\"/"/g;
21+
22+
push(@args, $arg);
23+
24+
} elsif ("$arg" eq "-i") {
25+
my $arg = shift @ARGV;
26+
# TODO complain if NULL or is dashed ??
27+
push(@input, $arg);
28+
29+
} elsif ("$arg" eq "-o") {
30+
my $arg = shift @ARGV;
31+
# TODO complain if NULL or is dashed ??
32+
push(@args, "-fo$arg");
33+
34+
} else {
35+
push(@args, $arg);
36+
}
37+
}
38+
39+
push(@args, "-nologo");
40+
push(@args, "-v");
41+
push(@args, @input);
42+
43+
unshift(@args, "rc.exe");
44+
printf("**** @args\n");
45+
46+
exit (system(@args) != 0);

compat/win32/headless.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* headless Git - run Git without opening a console window on Windows
3+
*/
4+
5+
#define STRICT
6+
#define WIN32_LEAN_AND_MEAN
7+
#define UNICODE
8+
#define _UNICODE
9+
#include <windows.h>
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <wchar.h>
13+
14+
/*
15+
* If `dir` contains the path to a Git exec directory, extend `PATH` to
16+
* include the corresponding `bin/` directory (which is where all those
17+
* `.dll` files needed by `git.exe` are, on Windows).
18+
*/
19+
static int extend_path(wchar_t *dir, size_t dir_len)
20+
{
21+
const wchar_t *suffix = L"\\libexec\\git-core";
22+
size_t suffix_len = wcslen(suffix);
23+
wchar_t *env;
24+
DWORD len;
25+
26+
if (dir_len < suffix_len)
27+
return 0;
28+
29+
dir_len -= suffix_len;
30+
if (memcmp(dir + dir_len, suffix, suffix_len * sizeof(wchar_t)))
31+
return 0;
32+
33+
len = GetEnvironmentVariableW(L"PATH", NULL, 0);
34+
if (!len)
35+
return 0;
36+
37+
env = _alloca((dir_len + 5 + len) * sizeof(wchar_t));
38+
wcsncpy(env, dir, dir_len);
39+
wcscpy(env + dir_len, L"\\bin;");
40+
if (!GetEnvironmentVariableW(L"PATH", env + dir_len + 5, len))
41+
return 0;
42+
43+
SetEnvironmentVariableW(L"PATH", env);
44+
return 1;
45+
}
46+
47+
int WINAPI wWinMain(_In_ HINSTANCE instance,
48+
_In_opt_ HINSTANCE previous_instance,
49+
_In_ LPWSTR command_line, _In_ int show)
50+
{
51+
wchar_t git_command_line[32768];
52+
size_t size = sizeof(git_command_line) / sizeof(wchar_t);
53+
const wchar_t *needs_quotes = L"";
54+
int slash = 0, i;
55+
56+
STARTUPINFO startup_info = {
57+
.cb = sizeof(STARTUPINFO),
58+
.dwFlags = STARTF_USESHOWWINDOW,
59+
.wShowWindow = SW_HIDE,
60+
};
61+
PROCESS_INFORMATION process_info = { 0 };
62+
DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT |
63+
CREATE_NEW_CONSOLE | CREATE_NO_WINDOW;
64+
DWORD exit_code;
65+
66+
/* First, determine the full path of argv[0] */
67+
for (i = 0; _wpgmptr[i]; i++)
68+
if (_wpgmptr[i] == L' ')
69+
needs_quotes = L"\"";
70+
else if (_wpgmptr[i] == L'\\')
71+
slash = i;
72+
73+
if (slash >= size - 11)
74+
return 127; /* Too long path */
75+
76+
/* If it is in Git's exec path, add the bin/ directory to the PATH */
77+
extend_path(_wpgmptr, slash);
78+
79+
/* Then, add the full path of `git.exe` as argv[0] */
80+
i = swprintf_s(git_command_line, size, L"%ls%.*ls\\git.exe%ls",
81+
needs_quotes, slash, _wpgmptr, needs_quotes);
82+
if (i < 0)
83+
return 127; /* Too long path */
84+
85+
if (*command_line) {
86+
/* Now, append the command-line arguments */
87+
i = swprintf_s(git_command_line + i, size - i,
88+
L" %ls", command_line);
89+
if (i < 0)
90+
return 127;
91+
}
92+
93+
startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
94+
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
95+
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
96+
97+
if (!CreateProcess(NULL, /* infer argv[0] from the command line */
98+
git_command_line, /* modified command line */
99+
NULL, /* inherit process handles? */
100+
NULL, /* inherit thread handles? */
101+
FALSE, /* handles inheritable? */
102+
creation_flags,
103+
NULL, /* use this process' environment */
104+
NULL, /* use this process' working directory */
105+
&startup_info, &process_info))
106+
return 129; /* could not start */
107+
WaitForSingleObject(process_info.hProcess, INFINITE);
108+
if (!GetExitCodeProcess(process_info.hProcess, &exit_code))
109+
exit_code = 130; /* Could not determine exit code? */
110+
111+
CloseHandle(process_info.hProcess);
112+
CloseHandle(process_info.hThread);
113+
114+
return (int)exit_code;
115+
}

config.mak.uname

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ ifeq ($(uname_S),Windows)
434434
# link.exe next to, and required by, cl.exe, we have to prepend this
435435
# onto the existing $PATH.
436436
#
437-
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys)
437+
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys):$(sdk_ver_bin_dir_msys)
438438
HAVE_ALLOCA_H = YesPlease
439439
NO_PREAD = YesPlease
440440
NEEDS_CRYPTO_WITH_SSL = YesPlease
@@ -497,12 +497,14 @@ endif
497497
compat/win32/trace2_win32_process_info.o \
498498
compat/win32/dirent.o
499499
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DENSURE_MSYSTEM_IS_SET -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
500-
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE
500+
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO
501501
# invalidcontinue.obj allows Git's source code to close the same file
502502
# handle twice, or to access the osfhandle of an already-closed stdout
503503
# See https://msdn.microsoft.com/en-us/library/ms235330.aspx
504504
EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib
505+
GITLIBS += git.res
505506
PTHREAD_LIBS =
507+
RC = compat/vcbuild/scripts/rc.pl
506508
lib =
507509
BASIC_CFLAGS += $(vcpkg_inc) $(sdk_includes) $(msvc_includes)
508510
ifndef DEBUG
@@ -534,6 +536,8 @@ else
534536
endif
535537
X = .exe
536538

539+
EXTRA_PROGRAMS += headless-git$X
540+
537541
compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
538542
endif
539543
ifeq ($(uname_S),Interix)
@@ -713,6 +717,7 @@ ifeq ($(uname_S),MINGW)
713717
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \
714718
-DENSURE_MSYSTEM_IS_SET -fstack-protector-strong
715719
EXTLIBS += -lntdll
720+
EXTRA_PROGRAMS += headless-git$X
716721
INSTALL = /bin/install
717722
INTERNAL_QSORT = YesPlease
718723
HAVE_LIBCHARSET_H = YesPlease

contrib/buildsystems/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,15 @@ if(WIN32)
747747
else()
748748
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
749749
endif()
750+
751+
add_executable(headless-git ${CMAKE_SOURCE_DIR}/compat/win32/headless.c)
752+
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
753+
target_link_options(headless-git PUBLIC -municode -Wl,-subsystem,windows)
754+
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
755+
target_link_options(headless-git PUBLIC /NOLOGO /ENTRY:wWinMainCRTStartup /SUBSYSTEM:WINDOWS)
756+
else()
757+
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
758+
endif()
750759
elseif(UNIX)
751760
target_link_libraries(common-main pthread rt)
752761
endif()

0 commit comments

Comments
 (0)