Skip to content

Commit

Permalink
Merge pull request #2974 from derrickstolee/maintenance-and-headless
Browse files Browse the repository at this point in the history
Include Windows-specific maintenance and headless-git
  • Loading branch information
dscho committed Jul 14, 2021
2 parents 30c23d6 + 94d63a1 commit d35d5a9
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 13 deletions.
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2566,6 +2566,13 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null
endif

headless-git.o: compat/win32/headless.c GIT-CFLAGS
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
-fno-stack-protector -o $@ -c -Wall -Wwrite-strings $<

headless-git$X: headless-git.o git.res GIT-LDFLAGS
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -mwindows -o $@ $< git.res

git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)

Expand Down Expand Up @@ -3215,6 +3222,7 @@ cocciclean:
clean: profile-clean coverage-clean cocciclean
$(RM) *.res
$(RM) $(OBJECTS)
$(RM) headless-git.o
$(RM) $(LIB_FILE) $(XDIFF_LIB)
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
$(RM) $(TEST_PROGRAMS)
Expand Down Expand Up @@ -3243,13 +3251,17 @@ endif
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
ifdef MSVC
$(RM) $(patsubst %.o,%.o.pdb,$(OBJECTS))
$(RM) headless-git.o.pdb
$(RM) $(patsubst %.exe,%.pdb,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.ilk,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.iobj,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.ipdb,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.pdb,$(PROGRAMS))
$(RM) $(patsubst %.exe,%.ilk,$(PROGRAMS))
$(RM) $(patsubst %.exe,%.iobj,$(PROGRAMS))
$(RM) $(patsubst %.exe,%.ipdb,$(PROGRAMS))
$(RM) $(patsubst %.exe,%.pdb,$(TEST_PROGRAMS))
$(RM) $(patsubst %.exe,%.ilk,$(TEST_PROGRAMS))
$(RM) $(patsubst %.exe,%.iobj,$(TEST_PROGRAMS))
$(RM) $(patsubst %.exe,%.ipdb,$(TEST_PROGRAMS))
$(RM) compat/vcbuild/MSVC-DEFS-GEN
Expand Down
2 changes: 1 addition & 1 deletion builtin/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
"</Settings>\n"
"<Actions Context=\"Author\">\n"
"<Exec>\n"
"<Command>\"%s\\git.exe\"</Command>\n"
"<Command>\"%s\\headless-git.exe\"</Command>\n"
"<Arguments>--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
"</Exec>\n"
"</Actions>\n"
Expand Down
7 changes: 7 additions & 0 deletions compat/vcbuild/find_vs_env.bat
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ REM ================================================================

SET sdk_dir=%WindowsSdkDir%
SET sdk_ver=%WindowsSDKVersion%
SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%%tgt%
SET si=%sdk_dir%Include\%sdk_ver%
SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared"
SET sl=%sdk_dir%lib\%sdk_ver%
Expand Down Expand Up @@ -130,6 +131,7 @@ REM ================================================================

SET sdk_dir=%WindowsSdkDir%
SET sdk_ver=%WindowsSDKVersion%
SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%bin\amd64
SET si=%sdk_dir%Include\%sdk_ver%
SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared" -I"%si%winrt"
SET sl=%sdk_dir%lib\%sdk_ver%
Expand Down Expand Up @@ -160,6 +162,11 @@ REM ================================================================
echo msvc_includes=%msvc_includes%
echo msvc_libs=%msvc_libs%

echo sdk_ver_bin_dir=%sdk_ver_bin_dir%
SET X1=%sdk_ver_bin_dir:C:=/C%
SET X2=%X1:\=/%
echo sdk_ver_bin_dir_msys=%X2%

echo sdk_includes=%sdk_includes%
echo sdk_libs=%sdk_libs%

Expand Down
17 changes: 17 additions & 0 deletions compat/vcbuild/scripts/clink.pl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
my @lflags = ();
my $is_linking = 0;
my $is_debug = 0;
my $is_gui = 0;
while (@ARGV) {
my $arg = shift @ARGV;
if ("$arg" eq "-DDEBUG") {
Expand Down Expand Up @@ -67,7 +68,11 @@
}
push(@args, $lib);
} elsif ("$arg" eq "-lexpat") {
if ($is_debug) {
push(@args, "libexpatd.lib");
} else {
push(@args, "libexpat.lib");
}
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
$arg =~ s/^-L/-LIBPATH:/;
push(@lflags, $arg);
Expand Down Expand Up @@ -119,11 +124,23 @@
push(@cflags, "-wd4996");
} elsif ("$arg" =~ /^-W[a-z]/) {
# let's ignore those
} elsif ("$arg" eq "-fno-stack-protector") {
# eat this
} elsif ("$arg" eq "-mwindows") {
$is_gui = 1;
} else {
push(@args, $arg);
}
}
if ($is_linking) {
if ($is_gui) {
push(@args, "-ENTRY:wWinMainCRTStartup");
push(@args, "-SUBSYSTEM:WINDOWS");
} else {
push(@args, "-ENTRY:wmainCRTStartup");
push(@args, "-SUBSYSTEM:CONSOLE");
}

push(@args, @lflags);
unshift(@args, "link.exe");
} else {
Expand Down
46 changes: 46 additions & 0 deletions compat/vcbuild/scripts/rc.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/perl -w
######################################################################
# Compile Resources on Windows
#
# This is a wrapper to facilitate the compilation of Git with MSVC
# using GNU Make as the build system. So, instead of manipulating the
# Makefile into something nasty, just to support non-space arguments
# etc, we use this wrapper to fix the command line options
#
######################################################################
use strict;
my @args = ();
my @input = ();

while (@ARGV) {
my $arg = shift @ARGV;
if ("$arg" =~ /^-[dD]/) {
# GIT_VERSION gets passed with too many
# layers of dquote escaping.
$arg =~ s/\\"/"/g;

push(@args, $arg);

} elsif ("$arg" eq "-i") {
my $arg = shift @ARGV;
# TODO complain if NULL or is dashed ??
push(@input, $arg);

} elsif ("$arg" eq "-o") {
my $arg = shift @ARGV;
# TODO complain if NULL or is dashed ??
push(@args, "-fo$arg");

} else {
push(@args, $arg);
}
}

push(@args, "-nologo");
push(@args, "-v");
push(@args, @input);

unshift(@args, "rc.exe");
printf("**** @args\n");

exit (system(@args) != 0);
114 changes: 114 additions & 0 deletions compat/win32/headless.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* headless Git - run Git without opening a console window on Windows
*/

#define STRICT
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

/*
* If `dir` contains the path to a Git exec directory, extend `PATH` to
* include the corresponding `bin/` directory (which is where all those
* `.dll` files needed by `git.exe` are, on Windows).
*/
static int extend_path(wchar_t *dir, size_t dir_len)
{
const wchar_t *suffix = L"\\libexec\\git-core";
size_t suffix_len = wcslen(suffix);
wchar_t *env;
DWORD len;

if (dir_len < suffix_len)
return 0;

dir_len -= suffix_len;
if (memcmp(dir + dir_len, suffix, suffix_len * sizeof(wchar_t)))
return 0;

len = GetEnvironmentVariableW(L"PATH", NULL, 0);
if (!len)
return 0;

env = _alloca((dir_len + 5 + len) * sizeof(wchar_t));
wcsncpy(env, dir, dir_len);
wcscpy(env + dir_len, L"\\bin;");
if (!GetEnvironmentVariableW(L"PATH", env + dir_len + 5, len))
return 0;

SetEnvironmentVariableW(L"PATH", env);
return 1;
}

int WINAPI wWinMain(HINSTANCE instance, HINSTANCE previous_instance,
wchar_t *command_line, int show)
{
wchar_t git_command_line[32768];
size_t size = sizeof(git_command_line) / sizeof(wchar_t);
const wchar_t *needs_quotes = L"";
int slash = 0, i;

STARTUPINFO startup_info = {
.dwFlags = STARTF_USESHOWWINDOW,
.wShowWindow = SW_HIDE,
};
PROCESS_INFORMATION process_info = { 0 };
DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT |
CREATE_NEW_CONSOLE | CREATE_NO_WINDOW;
DWORD exit_code;

/* First, determine the full path of argv[0] */
for (i = 0; _wpgmptr[i]; i++)
if (_wpgmptr[i] == L' ')
needs_quotes = L"\"";
else if (_wpgmptr[i] == L'\\')
slash = i;

if (slash + 11 >= sizeof(git_command_line) / sizeof(wchar_t))
return 127; /* Too long path */

/* If it is in Git's exec path, add the bin/ directory to the PATH */
extend_path(_wpgmptr, slash);

/* Then, add the full path of `git.exe` as argv[0] */
i = swprintf_s(git_command_line, size, L"%ls%.*ls\\git.exe%ls",
needs_quotes, slash, _wpgmptr, needs_quotes);
if (i < 0)
return 127; /* Too long path */

if (*command_line) {
/* Now, append the command-line arguments */
i = swprintf_s(git_command_line + i, size - i,
L" %ls", command_line);
if (i < 0)
return 127;
}

startup_info.cb = sizeof(STARTUPINFO);

startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);

if (!CreateProcess(NULL, /* infer argv[0] from the command line */
git_command_line, /* modified command line */
NULL, /* inherit process handles? */
NULL, /* inherit thread handles? */
FALSE, /* handles inheritable? */
creation_flags,
NULL, /* use this process' environment */
NULL, /* use this process' working directory */
&startup_info, &process_info))
return 129; /* could not start */
WaitForSingleObject(process_info.hProcess, INFINITE);
if (!GetExitCodeProcess(process_info.hProcess, &exit_code)) {
CloseHandle(process_info.hProcess);
return 130; /* Could not determine exit code? */
}

return (int)exit_code;
}
9 changes: 7 additions & 2 deletions config.mak.uname
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ ifeq ($(uname_S),Windows)
# link.exe next to, and required by, cl.exe, we have to prepend this
# onto the existing $PATH.
#
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys)
SANE_TOOL_PATH ?= $(msvc_bin_dir_msys):$(sdk_ver_bin_dir_msys)
HAVE_ALLOCA_H = YesPlease
NO_PREAD = YesPlease
NEEDS_CRYPTO_WITH_SSL = YesPlease
Expand Down Expand Up @@ -453,12 +453,14 @@ endif
compat/win32/trace2_win32_process_info.o \
compat/win32/dirent.o
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\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO
# invalidcontinue.obj allows Git's source code to close the same file
# handle twice, or to access the osfhandle of an already-closed stdout
# See https://msdn.microsoft.com/en-us/library/ms235330.aspx
EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib
GITLIBS += git.res
PTHREAD_LIBS =
RC = compat/vcbuild/scripts/rc.pl
lib =
BASIC_CFLAGS += $(vcpkg_inc) $(sdk_includes) $(msvc_includes)
ifndef DEBUG
Expand Down Expand Up @@ -490,6 +492,8 @@ else
endif
X = .exe

EXTRA_PROGRAMS += headless-git$X

compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
Expand Down Expand Up @@ -632,6 +636,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
RC = windres -O coff
NATIVE_CRLF = YesPlease
X = .exe
EXTRA_PROGRAMS += headless-git$X
ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
htmldir = doc/git/html/
prefix =
Expand Down
3 changes: 3 additions & 0 deletions contrib/buildsystems/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,9 @@ if(WIN32)
else()
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
endif()

add_executable(headless-git ${CMAKE_SOURCE_DIR}/compat/win32/headless.c)
target_link_options(headless-git PUBLIC /NOLOGO /ENTRY:wWinMainCRTStartup /SUBSYSTEM:WINDOWS)
elseif(UNIX)
target_link_libraries(common-main pthread rt)
endif()
Expand Down
Loading

0 comments on commit d35d5a9

Please sign in to comment.