Merge pull request #773 from jeffhostetler/vs2015

Build with VS2015
This commit is contained in:
Johannes Schindelin
2018-06-08 13:42:38 +02:00
16 changed files with 809 additions and 24 deletions

2
.gitignore vendored
View File

@@ -222,5 +222,7 @@
*.user
*.idb
*.pdb
*.ilk
.vs/
/Debug/
/Release/

View File

@@ -1179,7 +1179,7 @@ endif
ifdef SANE_TOOL_PATH
SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix "$(SANE_TOOL_PATH_SQ)"|'
PATH := $(SANE_TOOL_PATH):${PATH}
else
BROKEN_PATH_FIX = '/^\# @@BROKEN_PATH_FIX@@$$/d'
@@ -2749,6 +2749,28 @@ install: all
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)'
ifdef MSVC
$(INSTALL) compat/vcbuild/GEN.DEPS/bin/*.dll '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) compat/vcbuild/GEN.DEPS/bin/*.pdb '$(DESTDIR_SQ)$(bindir_SQ)'
# We DO NOT install the individual foo.o.pdb files because they
# have already been rolled up into the exe's pdb file.
# We DO NOT have pdb files for the builtin commands (like git-status.exe)
# because it is just a copy/hardlink of git.exe, rather than a unique binary.
$(INSTALL) git.pdb '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) git-shell.pdb '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) git-upload-pack.pdb '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) git-credential-store.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-daemon.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-fast-import.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-http-backend.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-http-fetch.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-http-push.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-imap-send.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-remote-http.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-remote-testsvn.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-sh-i18n--envsubst.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git-show-index.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
endif
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
$(INSTALL) -m 644 mergetools/* '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
@@ -2949,6 +2971,12 @@ endif
$(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
$(RM) GIT-USER-AGENT GIT-PREFIX
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
ifdef MSVC
$(RM) $(patsubst %.o,%.o.pdb,$(OBJECTS))
$(RM) $(patsubst %.exe,%.pdb,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.pdb,$(PROGRAMS))
$(RM) $(patsubst %.exe,%.pdb,$(TEST_PROGRAMS))
endif
.PHONY: all install profile-clean cocciclean clean strip
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell

View File

@@ -5,8 +5,8 @@
#include "cache-tree.h"
#include "object-store.h"
#ifndef DEBUG
#define DEBUG 0
#ifndef DEBUG_CACHE_TREE
#define DEBUG_CACHE_TREE 0
#endif
struct cache_tree *cache_tree(void)
@@ -110,7 +110,7 @@ static int do_invalidate_path(struct cache_tree *it, const char *path)
int namelen;
struct cache_tree_sub *down;
#if DEBUG
#if DEBUG_CACHE_TREE
fprintf(stderr, "cache-tree invalidate <%s>\n", path);
#endif
@@ -393,7 +393,7 @@ static int update_one(struct cache_tree *it,
strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz);
#if DEBUG
#if DEBUG_CACHE_TREE
fprintf(stderr, "cache-tree update-one %o %.*s\n",
mode, entlen, path + baselen);
#endif
@@ -416,7 +416,7 @@ static int update_one(struct cache_tree *it,
strbuf_release(&buffer);
it->entry_count = to_invalidate ? -1 : i - *skip_count;
#if DEBUG
#if DEBUG_CACHE_TREE
fprintf(stderr, "cache-tree update-one (%d ent, %d subtree) %s\n",
it->entry_count, it->subtree_nr,
oid_to_hex(&it->oid));
@@ -455,7 +455,7 @@ static void write_one(struct strbuf *buffer, struct cache_tree *it,
strbuf_add(buffer, path, pathlen);
strbuf_addf(buffer, "%c%d %d\n", 0, it->entry_count, it->subtree_nr);
#if DEBUG
#if DEBUG_CACHE_TREE
if (0 <= it->entry_count)
fprintf(stderr, "cache-tree <%.*s> (%d ent, %d subtree) %s\n",
pathlen, path, it->entry_count, it->subtree_nr,
@@ -529,7 +529,7 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
size -= rawsz;
}
#if DEBUG
#if DEBUG_CACHE_TREE
if (0 <= it->entry_count)
fprintf(stderr, "cache-tree <%s> (%d ent, %d subtree) %s\n",
*buffer, it->entry_count, subtree_nr,

View File

@@ -1285,6 +1285,147 @@ static char *path_lookup(const char *cmd, int exe_only)
return prog;
}
#if defined(_MSC_VER)
/* We need a stable sort */
#ifndef INTERNAL_QSORT
#include "qsort.c"
#endif
/* Compare only keys */
static int wenvcmp(const void *a, const void *b)
{
wchar_t *p = *(wchar_t **)a, *q = *(wchar_t **)b;
size_t p_len, q_len;
int ret;
/* Find end of keys */
for (p_len = 0; p[p_len] && p[p_len] != L'='; p_len++)
; /* do nothing */
for (q_len = 0; q[q_len] && q[q_len] != L'='; q_len++)
; /* do nothing */
/* Are keys identical (modulo case)? */
if (p_len == q_len && !_wcsnicmp(p, q, p_len))
return 0;
ret = _wcsnicmp(p, q, p_len < q_len ? p_len : q_len);
return ret ? ret : (p_len < q_len ? -1 : +1);
}
/*
* Build an environment block combining the inherited environment
* merged with the given list of settings.
*
* Values of the form "KEY=VALUE" in deltaenv override inherited values.
* Values of the form "KEY" in deltaenv delete inherited values.
*
* Multiple entries in deltaenv for the same key are explicitly allowed.
*
* We return a contiguous block of UNICODE strings with a final trailing
* zero word.
*/
static wchar_t *make_environment_block(char **deltaenv)
{
/*
* The CRT (at least as of UCRT) secretly declares "_wenviron"
* as a function that returns a pointer to a mostly static table.
* Grab the pointer and cache it for the duration of our loop.
*/
const wchar_t *wenv = GetEnvironmentStringsW(), *p;
size_t delta_size = 0, size = 1; /* for extra NUL at the end */
wchar_t **array = NULL;
size_t alloc = 0, nr = 0, i;
const char *p2;
wchar_t *wdeltaenv;
wchar_t *result, *p3;
/*
* If there is no deltaenv to apply, simply return a copy
*/
if (!deltaenv || !*deltaenv) {
for (p = wenv; p && *p; ) {
size_t s = wcslen(p) + 1;
size += s;
p += s;
}
ALLOC_ARRAY(result, size);
memcpy(result, wenv, size * sizeof(*wenv));
FreeEnvironmentStringsW(wenv);
return result;
}
/*
* If there is a deltaenv, let's accumulate all keys into `array`,
* sort them using the stable git_qsort() and then copy, skipping
* duplicate keys
*/
for (p = wenv; p && *p; ) {
size_t s = wcslen(p) + 1;
size += s;
ALLOC_GROW(array, nr + 1, alloc);
array[nr++] = p;
p += s;
}
/* (over-)assess size needed for wchar version of deltaenv */
for (i = 0; deltaenv[i]; i++) {
size_t s = strlen(deltaenv[i]) + 1;
delta_size += s;
}
ALLOC_ARRAY(wdeltaenv, delta_size);
/* convert the deltaenv, appending to array */
for (i = 0, p3 = wdeltaenv; deltaenv[i]; i++) {
size_t s = strlen(deltaenv[i]) + 1, wlen;
wlen = xutftowcs(p3, deltaenv[i], s * 2);
ALLOC_GROW(array, nr + 1, alloc);
array[nr++] = p3;
p3 += wlen + 1;
}
git_qsort(array, nr, sizeof(*array), wenvcmp);
ALLOC_ARRAY(result, size + delta_size);
for (p3 = result, i = 0; i < nr; i++) {
wchar_t *equal = wcschr(array[i], L'=');;
/* Skip "to delete" entry */
if (!equal)
continue;
p = array[i];
/* Skip any duplicate */
if (i + 1 < nr) {
wchar_t *next = array[i + 1];
size_t n = equal - p;
if (!_wcsnicmp(p, next, n) && (!next[n] || next[n] == L'='))
continue;
}
size = wcslen(p) + 1;
memcpy(p3, p, size * sizeof(*p));
p3 += size;
}
*p3 = L'\0';
free(array);
FreeEnvironmentStringsW(wenv);
return result;
}
#else
static int do_putenv(char **env, const char *name, int size, int free_old);
/* used number of elements of environ array, including terminating NULL */
@@ -1331,6 +1472,7 @@ static wchar_t *make_environment_block(char **deltaenv)
free(tmpenv);
return wenvblk;
}
#endif
static void do_unset_environment_variables(void)
{
@@ -1548,7 +1690,10 @@ static int try_shell_exec(const char *cmd, char *const *argv)
prog = path_lookup(interpr, 1);
if (prog) {
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 */
@@ -1621,6 +1766,70 @@ int mingw_kill(pid_t pid, int sig)
return -1;
}
#if defined(_MSC_VER)
/* UTF8 versions of getenv and putenv (and unsetenv).
* Internally, they use the CRT's stock UNICODE routines
* to avoid data loss.
*
* Unlike the mingw version, we DO NOT directly write to
* the CRT variables. We also DO NOT try to manage/replace
* the CRT storage.
*/
char *msc_getenv(const char *name)
{
int len_key, len_value;
wchar_t *w_key;
char *value;
const wchar_t *w_value;
if (!name || !*name)
return NULL;
len_key = strlen(name) + 1;
w_key = calloc(len_key, sizeof(wchar_t));
xutftowcs(w_key, name, len_key);
w_value = _wgetenv(w_key);
free(w_key);
if (!w_value)
return NULL;
len_value = wcslen(w_value) * 3 + 1;
value = calloc(len_value, sizeof(char));
xwcstoutf(value, w_value, len_value);
/* TODO Warning: We return "value" which is an allocated
* value and the caller is NOT expecting to have to free
* it, so we leak memory.
*/
return value;
}
int msc_putenv(const char *name)
{
int len, result;
char *equal;
wchar_t *wide;
if (!name || !*name)
return 0;
len = strlen(name);
equal = strchr(name, '=');
wide = calloc(len+1+!equal, sizeof(wchar_t));
xutftowcs(wide, name, len+1);
if (!equal)
wcscat(wide, L"=");
result = _wputenv(wide);
free(wide);
return result;
}
#else
/*
* Compare environment entries by key (i.e. stopping at '=' or '\0').
*/
@@ -1749,6 +1958,8 @@ int mingw_putenv(const char *namevalue)
return 0;
}
#endif
/*
* Note, this isn't a complete replacement for getaddrinfo. It assumes
* that service contains a numerical port, or that it is null. It
@@ -2307,8 +2518,34 @@ int mingw_raise(int sig)
sigint_fn(SIGINT);
return 0;
#if defined(_MSC_VER)
/*
* <signal.h> in the CRT 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.
*/
/*case SIGINT:*/
case SIGILL:
case SIGFPE:
case SIGSEGV:
case SIGTERM:
case SIGBREAK:
case SIGABRT:
case SIGABRT_COMPAT:
return raise(sig);
default:
errno = EINVAL;
return -1;
#else
default:
return raise(sig);
#endif
}
}
@@ -2406,7 +2643,10 @@ typedef struct _REPARSE_DATA_BUFFER {
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
_ANONYMOUS_UNION union {
#ifndef _MSC_VER
_ANONYMOUS_UNION
#endif
union {
struct {
WORD SubstituteNameOffset;
WORD SubstituteNameLength;
@@ -2784,6 +3024,7 @@ int handle_long_path(wchar_t *path, int len, int max_path, int expand)
}
}
#if !defined(_MSC_VER)
/*
* Disable MSVCRT command line wildcard expansion (__getmainargs called from
* mingw startup code, see init.c in mingw runtime).
@@ -2796,6 +3037,7 @@ typedef struct {
extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
_startupinfo *si);
#endif
static NORETURN void die_startup(void)
{
@@ -2873,6 +3115,95 @@ static void maybe_redirect_std_handles(void)
GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
}
#if defined(_MSC_VER)
/*
* This routine sits between wmain() and "main" in git.exe.
* We receive UNICODE (wchar_t) values for argv and env.
*
* To be more compatible with the core git code, we convert
* argv into UTF8 and pass them directly to the "main" routine.
*
* We don't bother converting the given UNICODE env vector,
* but rather leave them in the CRT. We replaced the various
* getenv/putenv routines to pull them directly from the CRT.
*
* This is unlike the MINGW version:
* [] It does the UNICODE-2-UTF8 conversion on both sets and
* stuffs the values back into the CRT using exported symbols.
* [] It also maintains a private copy of the environment and
* tries to track external changes to it.
*/
int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env)
{
char **my_utf8_argv = NULL, **save = NULL;
char *buffer = NULL;
int maxlen;
int k, exit_status;
#ifdef USE_MSVC_CRTDBG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
maybe_redirect_std_handles();
/* determine size of argv conversion buffer */
maxlen = wcslen(_wpgmptr);
for (k = 1; k < argc; k++)
maxlen = max(maxlen, wcslen(w_argv[k]));
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
maxlen = 3 * maxlen + 1;
buffer = malloc_startup(maxlen);
/*
* 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(my_utf8_argv, argc + 1);
ALLOC_ARRAY(save, argc + 1);
save[0] = my_utf8_argv[0] = wcstoutfdup_startup(buffer, _wpgmptr, maxlen);
for (k = 1; k < argc; k++)
save[k] = my_utf8_argv[k] = wcstoutfdup_startup(buffer, w_argv[k], maxlen);
save[k] = my_utf8_argv[k] = NULL;
free(buffer);
/* fix Windows specific environment settings */
setup_windows_environment();
unset_environment_variables = xstrdup("PERL5LIB");
/* initialize critical section for waitpid pinfo_t list */
InitializeCriticalSection(&pinfo_cs);
InitializeCriticalSection(&phantom_symlinks_cs);
/* set up default file mode and file modes for stdin/out/err */
_fmode = _O_BINARY;
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
_setmode(_fileno(stderr), _O_BINARY);
/* initialize Unicode console */
winansi_init();
/* init length of current directory for handle_long_path */
current_directory_len = GetCurrentDirectoryW(0, NULL);
/* invoke the real main() using our utf8 version of argv. */
exit_status = msc_main(argc, my_utf8_argv);
for (k = 0; k < argc; k++)
free(save[k]);
free(save);
free(my_utf8_argv);
return exit_status;
}
#else
void mingw_startup(void)
{
int i, maxlen, argc;
@@ -2951,6 +3282,8 @@ void mingw_startup(void)
current_directory_len = GetCurrentDirectoryW(0, NULL);
}
#endif
int uname(struct utsname *buf)
{
unsigned v = (unsigned)GetVersion();

View File

@@ -265,12 +265,53 @@ char *mingw_getcwd(char *pointer, int len);
#error "NO_UNSETENV is incompatible with the MinGW startup code!"
#endif
#if defined(_MSC_VER)
/*
* We bind *env() routines (even the mingw_ ones) to private msc_ versions.
* These talk to the CRT using UNICODE/wchar_t, but maintain the original
* narrow-char API.
*
* Note that the MSCRT maintains both ANSI (getenv()) and UNICODE (_wgetenv())
* routines and stores both versions of each environment variable in parallel
* (and secretly updates both when you set one or the other), but it uses CP_ACP
* to do the conversion rather than CP_UTF8.
*
* Since everything in the git code base is UTF8, we define the msc_ routines
* to access the CRT using the UNICODE routines and manually convert them to
* UTF8. This also avoids round-trip problems.
*
* This also helps with our linkage, since "_wenviron" is publicly exported
* from the CRT. But to access "_environ" we would have to statically link
* to the CRT (/MT).
*
* We also use "wmain(argc,argv,env)" and get the initial UNICODE setup for us.
* This avoids the need for the msc_startup() to import and convert the
* inherited environment.
*
* We require NO_SETENV (and let gitsetenv() call our msc_putenv).
*/
#define getenv msc_getenv
#define putenv msc_putenv
#define unsetenv msc_putenv
#define mingw_getenv msc_getenv
#define mingw_putenv msc_putenv
char *msc_getenv(const char *name);
int msc_putenv(const char *name);
#ifndef NO_SETENV
#error "NO_SETENV is required for MSC startup code!"
#endif
#else
char *mingw_getenv(const char *name);
#define getenv mingw_getenv
int mingw_putenv(const char *namevalue);
#define putenv mingw_putenv
#define unsetenv mingw_putenv
#endif
int mingw_gethostname(char *host, int namelen);
#define gethostname mingw_gethostname
@@ -353,11 +394,13 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
#ifndef __MINGW64_VERSION_MAJOR
#define off_t off64_t
#define lseek _lseeki64
#ifndef _MSC_VER
struct timespec {
time_t tv_sec;
long tv_nsec;
};
#endif
#endif
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
{
@@ -654,7 +697,26 @@ extern CRITICAL_SECTION pinfo_cs;
/*
* A replacement of main() that adds win32 specific initialization.
*
* Note that the end of these macros are unterminated so that the
* brace group following the use of the macro is the body of the
* function.
*/
#if defined(_MSC_VER)
int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env);
extern int msc_main(int argc, const char **argv);
#define main(c,v) dummy_decl_msc_main(void); \
int wmain(int my_argc, \
wchar_t **my_w_argv, \
wchar_t **my_w_env) \
{ \
return msc_startup(my_argc, my_w_argv, my_w_env); \
} \
int msc_main(c, v)
#else
void mingw_startup(void);
#define main(c,v) dummy_decl_mingw_main(void); \
@@ -666,6 +728,8 @@ int main(int argc, const char **argv) \
} \
static int mingw_main(c,v)
#endif
/*
* Used by Pthread API implementation for Windows
*/

View File

@@ -24,6 +24,12 @@ static __inline int strcasecmp (const char *s1, const char *s2)
#undef ERROR
#define ftello _ftelli64
typedef int sigset_t;
/* open for reading, writing, or both (not in fcntl.h) */
#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR)
#include "compat/mingw.h"
#endif

1
compat/vcbuild/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
GEN.*

147
compat/vcbuild/Makefile Normal file
View File

@@ -0,0 +1,147 @@
## Makefile to install nuget package dependencies.
##################################################################
INST=GEN.DEPS
INST_INC=$(INST)/include
INST_LIB=$(INST)/lib
INST_BIN=$(INST)/bin
PKGDIR=GEN.PKGS
NUGET ?= nuget.exe
ifneq ($(shell $(NUGET) help 2>/dev/null; echo $$?),0)
NUGET := /usr/src/build-extra/nuget/nuget.exe
endif
##################################################################
all: unpack expat libssh libssh_redist curl curl_redist openssl zlib \
libiconv libiconv_redist
unpack:
[ -d $(PKGDIR) ] || mkdir $(PKGDIR)
"$(NUGET)" restore packages.config -ConfigFile nuget.config \
-NonInteractive -OutputDirectory $(PKGDIR)
insdir:
[ -d $(INST) ] || mkdir $(INST)
[ -d $(INST_INC) ] || mkdir $(INST_INC)
[ -d $(INST_BIN) ] || mkdir $(INST_BIN)
[ -d $(INST_LIB) ] || mkdir $(INST_LIB)
##################################################################
## We place the expat headers in their own subdirectory.
## The custom is to reference <expat.h>, so compile with:
## -I$(INST_INC)/expat
EXPAT_VER=2.1.0.11
EXPAT_ROOT=$(PKGDIR)/expat.$(EXPAT_VER)/build/native
EXPAT_INC=$(EXPAT_ROOT)/include
EXPAT_LIB=$(EXPAT_ROOT)/lib/v110/x64/Release/dynamic/utf8
expat: insdir
[ -d $(INST_INC)/expat ] || mkdir $(INST_INC)/expat
cp -r $(EXPAT_INC)/* $(INST_INC)/expat/
cp -r $(EXPAT_LIB)/* $(INST_LIB)/
##################################################################
LIBICONV_VER=1.14.0.11
LIBICONV_ROOT=$(PKGDIR)/libiconv.$(LIBICONV_VER)/build/native
LIBICONV_INC=$(LIBICONV_ROOT)/include
LIBICONV_LIB=$(LIBICONV_ROOT)/lib/v110/x64/Release/dynamic/cdecl
libiconv: insdir
cp -r $(LIBICONV_INC)/* $(INST_INC)/
cp -r $(LIBICONV_LIB)/libiconv.lib $(INST_LIB)/iconv.lib
LIBICONV_REDIST_ROOT=$(PKGDIR)/libiconv.redist.$(LIBICONV_VER)/build/native
LIBICONV_REDIST_BIN=$(LIBICONV_REDIST_ROOT)/bin/v110/x64/Release/dynamic/cdecl
libiconv_redist: insdir
cp -r $(LIBICONV_REDIST_BIN)/* $(INST_BIN)/
##################################################################
LIBSSH_VER=1.4.3.3
LIBSSH_ROOT=$(PKGDIR)/libssh2.$(LIBSSH_VER)/build/native
LIBSSH_INC=$(LIBSSH_ROOT)/include
LIBSSH_LIB=$(LIBSSH_ROOT)/lib/v110/x64/Release/dynamic/cdecl
libssh: insdir
[ -d $(INST_INC)/libssh2 ] || mkdir $(INST_INC)/libssh2
cp -r $(LIBSSH_INC)/* $(INST_INC)/libssh2
cp -r $(LIBSSH_LIB)/* $(INST_LIB)/
LIBSSH_REDIST_ROOT=$(PKGDIR)/libssh2.redist.$(LIBSSH_VER)/build/native
LIBSSH_REDIST_BIN=$(LIBSSH_REDIST_ROOT)/bin/v110/x64/Release/dynamic/cdecl
libssh_redist: insdir
cp -r $(LIBSSH_REDIST_BIN)/* $(INST_BIN)/
##################################################################
## We place the curl headers in their own subdirectory.
## The custom is to reference <curl/curl.h>, so compile with:
## -I$(INST_INC)
CURL_VER=7.30.0.2
CURL_ROOT=$(PKGDIR)/curl.$(CURL_VER)/build/native
CURL_INC=$(CURL_ROOT)/include/curl
CURL_LIB=$(CURL_ROOT)/lib/v110/x64/Release/dynamic
curl: insdir
[ -d $(INST_INC)/curl ] || mkdir $(INST_INC)/curl
cp -r $(CURL_INC)/* $(INST_INC)/curl
cp -r $(CURL_LIB)/* $(INST_LIB)/
CURL_REDIST_ROOT=$(PKGDIR)/curl.redist.$(CURL_VER)/build/native
CURL_REDIST_BIN=$(CURL_REDIST_ROOT)/bin/v110/x64/Release/dynamic
curl_redist: insdir
cp -r $(CURL_REDIST_BIN)/* $(INST_BIN)/
##################################################################
## We place the openssl headers in their own subdirectory.
## The custom is to reference <openssl/sha.h>, so compile with:
## -I$(INST_INC)
OPENSSL_VER=1.0.2.1
OPENSSL_ROOT=$(PKGDIR)/openssl.v140.windesktop.msvcstl.dyn.rt-dyn.x64.$(OPENSSL_VER)
OPENSSL_INC=$(OPENSSL_ROOT)/build/native/include/openssl
OPENSSL_LIB=$(OPENSSL_ROOT)/lib/native/v140/windesktop/msvcstl/dyn/rt-dyn/x64/release
openssl: insdir
[ -d $(INST_INC)/openssl ] || mkdir $(INST_INC)/openssl
cp -r $(OPENSSL_INC)/* $(INST_INC)/openssl
cp -r $(OPENSSL_LIB)/*.lib $(INST_LIB)/
cp -r $(OPENSSL_LIB)/*.dll $(INST_BIN)/
cp -r $(OPENSSL_LIB)/*.pdb $(INST_BIN)/
##################################################################
## We place the zlib headers in their own subdirectory.
## The custom is to reference <zlib.h>, so compile with:
## -I$(INST_INC)/zlib
ZLIB_VER=1.2.8.8
ZLIB_ROOT=$(PKGDIR)/zlib.v140.windesktop.msvcstl.dyn.rt-dyn.$(ZLIB_VER)
ZLIB_INC=$(ZLIB_ROOT)/build/native/include
ZLIB_LIB=$(ZLIB_ROOT)/lib/native/v140/windesktop/msvcstl/dyn/rt-dyn/x64/RelWithDebInfo
zlib: insdir
[ -d $(INST_INC)/zlib ] || mkdir $(INST_INC)/zlib
cp -r $(ZLIB_INC)/* $(INST_INC)/zlib
cp -r $(ZLIB_LIB)/*.lib $(INST_LIB)/
cp -r $(ZLIB_LIB)/*.dll $(INST_BIN)/
cp -r $(ZLIB_LIB)/*.pdb $(INST_BIN)/
##################################################################
clean:
rm -rf $(INST)
clobber: clean
rm -rf $(PKGDIR)

View File

@@ -0,0 +1,54 @@
Instructions for building Git for Windows using VS2015.
================================================================
Installing third-party dependencies:
====================================
[1] Install nuget.exe somewhere on your system and add it to your PATH.
https://docs.nuget.org/consume/command-line-reference
https://dist.nuget.org/index.html
[2] Download required nuget packages for third-party libraries.
Using a terminal window, type:
make -C compat/vcbuild
This will download the packages, unpack them into GEN.PKGS,
and populate the {include, lib, bin} directories in GEN.DEPS.
Building Git for Windows using VS2015:
======================================
[3] Build 64-bit version of Git for Windows.
Using a terminal window:
make MSVC=1 DEBUG=1
[4] Add compat/vcbuild/GEN.DEPS/bin to your PATH.
[5] You should then be able to run the test suite and any interactive
commands.
[6] To debug/profile in VS, open the git.exe in VS and run/debug
it. (Be sure to add GEN.DEPS/bin to the PATH in the debug
dialog.)
TODO List:
==========
[A] config.mak.uname currently contains hard-coded paths
to the various MSVC and SDK libraries for the 64-bit
version of the compilers and libaries.
See: SANE_TOOL_PATH, MSVC_DEPS, MSVC_SDK*, MSVC_VCDIR.
Long term, we need to figure out how to properly import
values for %VCINSTALLDIR%, %LIB%, %LIBPATH%, and the
other values normally set by "vsvars32.bat" when a
developer command prompt is started. This would also
allow us to switch between 32- and 64-bit tool chains.
[B] We need to build SLN or VCPROJ files.

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<!--
Used to specify the default location to expand packages.
See: NuGet.exe help install
See: NuGet.exe help update
-->
<add key="repositoryPath" value="Nupkg" />
</config>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
<packageRestore>
<!-- Allow NuGet to download missing packages -->
<add key="enabled" value="True" />
<!-- Automatically check for missing packages during build in Visual Studio -->
<add key="automatic" value="False" />
</packageRestore>
<bindingRedirects>
<add key="skip" value="False" />
</bindingRedirects>
<activePackageSource>
<!-- this tells only one given source is active -->
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</activePackageSource>
</configuration>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="curl" version="7.30.0.2" />
<package id="curl.redist" version="7.30.0.2" />
<package id="expat" version="2.1.0.11" />
<package id="libiconv" version="1.14.0.11" />
<package id="libiconv.redist" version="1.14.0.11" />
<package id="libssh2" version="1.4.3.3" />
<package id="libssh2.redist" version="1.4.3.3" />
<package id="openssl" version="1.0.2.1" />
<package id="openssl.v120.windesktop.msvcstl.dyn.rt-dyn" version="1.0.2.1" />
<package id="openssl.v120.windesktop.msvcstl.dyn.rt-dyn.x64" version="1.0.2.0" />
<package id="openssl.v120.windesktop.msvcstl.dyn.rt-dyn.x86" version="1.0.2.1" />
<package id="openssl.v140.windesktop.msvcstl.dyn.rt-dyn" version="1.0.2.1" />
<package id="openssl.v140.windesktop.msvcstl.dyn.rt-dyn.x64" version="1.0.2.1" />
<package id="openssl.v140.windesktop.msvcstl.dyn.rt-dyn.x86" version="1.0.2.1" />
<package id="zlib" version="1.2.8.8" />
<package id="zlib.v120.windesktop.msvcstl.dyn.rt-dyn" version="1.2.8.8" />
<package id="zlib.v140.windesktop.msvcstl.dyn.rt-dyn" version="1.2.8.8" />
</packages>

View File

@@ -12,18 +12,22 @@
use strict;
my @args = ();
my @cflags = ();
my @lflags = ();
my $is_linking = 0;
while (@ARGV) {
my $arg = shift @ARGV;
if ("$arg" =~ /^-[DIMGO]/) {
if ("$arg" =~ /^-[DIMGOZ]/) {
push(@cflags, $arg);
} elsif ("$arg" eq "-o") {
my $file_out = shift @ARGV;
if ("$file_out" =~ /exe$/) {
$is_linking = 1;
# Create foo.exe and foo.pdb
push(@args, "-OUT:$file_out");
} else {
# Create foo.o and foo.o.pdb
push(@args, "-Fo$file_out");
push(@args, "-Fd$file_out.pdb");
}
} elsif ("$arg" eq "-lz") {
push(@args, "zlib.lib");
@@ -35,9 +39,11 @@ while (@ARGV) {
push(@args, "ssleay32.lib");
} elsif ("$arg" eq "-lcurl") {
push(@args, "libcurl.lib");
} elsif ("$arg" eq "-lexpat") {
push(@args, "libexpat.lib");
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
$arg =~ s/^-L/-LIBPATH:/;
push(@args, $arg);
push(@lflags, $arg);
} elsif ("$arg" =~ /^-R/) {
# eat
} else {
@@ -45,10 +51,11 @@ while (@ARGV) {
}
}
if ($is_linking) {
push(@args, @lflags);
unshift(@args, "link.exe");
} else {
unshift(@args, "cl.exe");
push(@args, @cflags);
}
#printf("**** @args\n");
printf(STDERR "**** @args\n\n\n") if (!defined($ENV{'QUIET_GEN'}));
exit (system(@args) != 0);

View File

@@ -528,7 +528,20 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
#ifdef DETECT_MSYS_TTY
#include <winternl.h>
#if defined(_MSC_VER)
typedef struct _OBJECT_NAME_INFORMATION
{
UNICODE_STRING Name;
WCHAR NameBuffer[0];
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
#define ObjectNameInformation 1
#else
#include <ntstatus.h>
#endif
static void detect_msys_tty(int fd)
{

View File

@@ -349,6 +349,13 @@ endif
ifeq ($(uname_S),Windows)
GIT_VERSION := $(GIT_VERSION).MSVC
pathsep = ;
# Prepend MSVC 64-bit tool-chain to PATH.
#
# A regular Git Bash *does not* have cl.exe in its $PATH. As there is a
# link.exe next to, and required by, cl.exe, we have to prepend this
# onto the existing $PATH.
#
SANE_TOOL_PATH ?= /c/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64
HAVE_ALLOCA_H = YesPlease
NO_PREAD = YesPlease
NEEDS_CRYPTO_WITH_SSL = YesPlease
@@ -361,11 +368,16 @@ ifeq ($(uname_S),Windows)
NO_STRCASESTR = YesPlease
NO_STRLCPY = YesPlease
NO_MEMMEM = YesPlease
# NEEDS_LIBICONV = YesPlease
NO_ICONV = YesPlease
NEEDS_LIBICONV = YesPlease
NO_STRTOUMAX = YesPlease
NO_MKDTEMP = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
# VS2015 with UCRT claims that snprintf and friends are C99 compliant,
# so we don't need this.
#
# TODO If we want to support older compilers, we need to make this
# TODO conditional on the compiler version.
#
# SNPRINTF_RETURNS_BOGUS = YesPlease
NO_SVN_TESTS = YesPlease
RUNTIME_PREFIX = YesPlease
HAVE_WPGMPTR = YesWeDo
@@ -378,7 +390,6 @@ ifeq ($(uname_S),Windows)
NO_REGEX = YesPlease
NO_GETTEXT = YesPlease
NO_PYTHON = YesPlease
BLK_SHA1 = YesPlease
ETAGS_TARGET = ETAGS
NO_INET_PTON = YesPlease
NO_INET_NTOP = YesPlease
@@ -389,24 +400,54 @@ ifeq ($(uname_S),Windows)
CC = compat/vcbuild/scripts/clink.pl
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
COMPAT_OBJS = compat/msvc.o compat/winansi.o \
compat/win32/pthread.o compat/win32/syslog.o \
compat/win32/dirent.o compat/win32/fscache.o
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE
EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj
EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib
PTHREAD_LIBS =
lib =
# Path to the unpacked third-party libraries
MSVC_DEPS = compat/vcbuild/GEN.DEPS
# Compensate for lack of %VCINSTALLDIR%, %LIB%, %LIBPATH%, and etc.
# since vcvars*.bat did not get a chance to setup the environment of
# the user's shell window.
#
# TODO If we ask the user to launch a "x64 Native" command prompt
# TODO and then have it start a git-bash window, these could be
# TODO inherited. So we wouldn't need to add these lines here.
#
MSVC_SDK81 = "c:/Program Files (x86)/Windows Kits/8.1"
MSVC_SDK10 = "c:/Program Files (x86)/Windows Kits/10"
MSVC_VCDIR = "c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC"
BASIC_CFLAGS += \
-I$(MSVC_DEPS)/include -I$(MSVC_DEPS)/include/expat -I$(MSVC_DEPS)/include/zlib \
-L$(MSVC_DEPS)/lib \
-I$(MSVC_SDK81)/Include/um -I$(MSVC_SDK81)/Include/shared \
-L$(MSVC_SDK81)/lib/winv6.3/um/x64 \
-I$(MSVC_SDK10)/Include/10.0.10240.0/ucrt \
-L$(MSVC_SDK10)/lib/10.0.10240.0/ucrt/x64 \
-I$(MSVC_VCDIR)/INCLUDE \
-L$(MSVC_VCDIR)/lib/amd64
# Optionally enable memory leak reporting.
# BASIC_CLFAGS += -DUSE_MSVC_CRTDBG
BASIC_CFLAGS += -DPROTECT_NTFS_DEFAULT=1
# Always give "-Zi" to the compiler and "-debug" to linker (even in
# release mode) to force a PDB to be generated (like RelWithDebInfo).
BASIC_CFLAGS += -Zi
BASIC_LDFLAGS += -debug
ifndef DEBUG
BASIC_CFLAGS += -GL -Os -MD
BASIC_LDFLAGS += -LTCG
BASIC_CFLAGS += -GL -Gy -O2 -Oy- -MD -DNDEBUG
BASIC_LDFLAGS += -release -LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /DEBUGTYPE:CV,FIXUP
AR += -LTCG
else
BASIC_CFLAGS += -Zi -MDd
BASIC_CFLAGS += -MDd -DDEBUG -D_DEBUG
endif
X = .exe
compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
NO_INITGROUPS = YesPlease

View File

@@ -1,6 +1,15 @@
#ifndef GIT_COMPAT_UTIL_H
#define GIT_COMPAT_UTIL_H
#ifdef USE_MSVC_CRTDBG
/*
* For these to work they must appear very early in each
* file -- before most of the standard header files.
*/
#include <stdlib.h>
#include <crtdbg.h>
#endif
#define _FILE_OFFSET_BITS 64
@@ -272,6 +281,33 @@ extern char *gitdirname(char *);
#ifndef NO_ICONV
#include <iconv.h>
#ifdef _MSC_VER
/*
* At least version 1.14.0.11 of the libiconv NuPkg at
* https://www.nuget.org/packages/libiconv/ does not set errno at all.
*
* Let's simulate it by testing whether we might have possibly run out of
* space.
*/
static inline size_t msvc_iconv(iconv_t conv,
const char **inpos, size_t *insize,
char **outpos, size_t *outsize)
{
int saved_errno = errno;
size_t res;
errno = ENOENT;
res = iconv(conv, inpos, insize, outpos, outsize);
if (!res)
errno = saved_errno;
else if (errno == ENOENT)
errno = *outsize < 16 ? E2BIG : 0;
return res;
}
#undef iconv
#define iconv msvc_iconv
#endif
#endif
#ifndef NO_OPENSSL

View File

@@ -332,7 +332,7 @@ test_expect_success 'difftool --extcmd cat arg1' '
test_expect_success 'difftool --extcmd cat arg2' '
echo branch >expect &&
git difftool --no-prompt \
--extcmd sh\ -c\ \"cat\ \$2\" branch >actual &&
--extcmd sh\ -c\ \"cat\ \\\"\$2\\\"\" branch >actual &&
test_cmp expect actual
'