[v5,6/8] cmake: support for building git on windows with mingw
diff mbox series

Message ID 10acdbf5e4d4c49f69889ab1129d3d6b5a7fd754.1593187898.git.gitgitgadget@gmail.com
State New
Headers show
Series
  • CMake build system for git
Related show

Commit Message

Junio C Hamano via GitGitGadget June 26, 2020, 4:11 p.m. UTC
From: Sibi Siddharthan <sibisiddharthan.github@gmail.com>

This patch facilitates building git on Windows with CMake using MinGW

NOTE: The funtions unsetenv and hstrerror are not checked in Windows
builds.
Reasons
NO_UNSETENV is not compatible with Windows builds.
lines 262-264 compat/mingw.h

compat/mingw.h(line 25) provides a definition of hstrerror which
conflicts with the definition provided in
git-compat-util.h(lines 733-736).

To use CMake on Windows with MinGW do this:
cmake `relative-path-to-srcdir` -G "MinGW Makefiles"

Signed-off-by: Sibi Siddharthan <sibisiddharthan.github@gmail.com>
---
 contrib/buildsystems/CMakeLists.txt | 117 ++++++++++++++++++++++------
 1 file changed, 94 insertions(+), 23 deletions(-)

Comments

David Aguilar June 30, 2020, 7:25 a.m. UTC | #1
On Fri, Jun 26, 2020 at 04:11:36PM +0000, Sibi Siddharthan via GitGitGadget wrote:
> From: Sibi Siddharthan <sibisiddharthan.github@gmail.com>
> 
> This patch facilitates building git on Windows with CMake using MinGW
> 
> NOTE: The funtions unsetenv and hstrerror are not checked in Windows
> builds.
> Reasons
> NO_UNSETENV is not compatible with Windows builds.
> lines 262-264 compat/mingw.h
> 
> compat/mingw.h(line 25) provides a definition of hstrerror which
> conflicts with the definition provided in
> git-compat-util.h(lines 733-736).
> 
> To use CMake on Windows with MinGW do this:
> cmake `relative-path-to-srcdir` -G "MinGW Makefiles"
> 
> Signed-off-by: Sibi Siddharthan <sibisiddharthan.github@gmail.com>
> ---
>  contrib/buildsystems/CMakeLists.txt | 117 ++++++++++++++++++++++------
>  1 file changed, 94 insertions(+), 23 deletions(-)
> 
> diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
> index 2768ee5b71..2d7c0ed88e 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}/../..)
>  
>  find_program(SH_EXE sh)
> +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/")
> +endif()
>  
>  #Create GIT-VERSION-FILE using GIT-VERSION-GEN
>  if(NOT EXISTS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE)
> @@ -65,7 +69,9 @@ project(git
>  	VERSION ${git_version}
>  	LANGUAGES C)
>  
> +
>  #TODO gitk git-gui gitweb
> +#TODO Enable NLS on windows natively
>  #TODO Add pcre support
>  
>  #macros for parsing the Makefile for sources and scripts
> @@ -104,6 +110,7 @@ find_package(EXPAT)
>  find_package(Iconv)
>  find_package(Intl)
>  
> +
>  if(NOT Intl_FOUND)
>  	add_compile_definitions(NO_GETTEXT)
>  	if(NOT Iconv_FOUND)
> @@ -125,6 +132,14 @@ if(Intl_FOUND)
>  	include_directories(SYSTEM ${Intl_INCLUDE_DIRS})
>  endif()
>  
> +
> +if(WIN32)
> +	find_program(WINDRES_EXE windres)
> +	if(NOT WINDRES_EXE)
> +		message(FATAL_ERROR "Install windres on Windows for resource files")
> +	endif()
> +endif()
> +
>  find_program(MSGFMT_EXE msgfmt)
>  if(NOT MSGFMT_EXE)
>  	message(WARNING "Text Translations won't be build")
> @@ -156,11 +171,35 @@ add_compile_definitions(PAGER_ENV="LESS=FRX LV=-c"
>  			BINDIR="bin"
>  			GIT_BUILT_FROM_COMMIT="")
>  
> -set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
> -add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
> +if(WIN32)
> +	set(FALLBACK_RUNTIME_PREFIX /mingw64)
> +	add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
> +else()
> +	set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
> +	add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
> +endif()
> +
> +
> +#Platform Specific
> +if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
> +	include_directories(${CMAKE_SOURCE_DIR}/compat/win32)
> +	add_compile_definitions(HAVE_ALLOCA_H NO_POSIX_GOODIES NATIVE_CRLF NO_UNIX_SOCKETS WIN32
> +				_CONSOLE DETECT_MSYS_TTY STRIP_EXTENSION=".exe"  NO_SYMLINK_HEAD UNRELIABLE_FSTAT
> +				NOGDI OBJECT_CREATION_MODE=1 __USE_MINGW_ANSI_STDIO=0
> +				USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
> +				UNICODE _UNICODE HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET)
> +	list(APPEND compat_SOURCES compat/mingw.c compat/winansi.c compat/win32/path-utils.c
> +		compat/win32/pthread.c compat/win32mmap.c compat/win32/syslog.c
> +		compat/win32/trace2_win32_process_info.c compat/win32/dirent.c
> +		compat/nedmalloc/nedmalloc.c compat/strdup.c)
> +	set(NO_UNIX_SOCKETS 1)
> +
> +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
> +	add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
> +	list(APPEND compat_SOURCES unix-socket.c)
> +endif()
>  
> -add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
> -list(APPEND compat_SOURCES unix-socket.c)
> +set(EXE_EXTENSION ${CMAKE_EXECUTABLE_SUFFIX})
>  
>  #header checks
>  check_include_file(libgen.h HAVE_LIBGEN_H)
> @@ -223,7 +262,12 @@ endif()
>  #function checks
>  set(function_checks
>  	strcasestr memmem strlcpy strtoimax strtoumax strtoull
> -	setenv mkdtemp poll pread memmem unsetenv hstrerror)
> +	setenv mkdtemp poll pread memmem)
> +
> +#unsetenv,hstrerror are incompatible with windows build
> +if(NOT WIN32)
> +	list(APPEND function_checks unsetenv hstrerror)
> +endif()
>  
>  foreach(f ${function_checks})
>  	string(TOUPPER ${f} uf)
> @@ -444,7 +488,13 @@ unset(CMAKE_REQUIRED_INCLUDES)
>  #programs
>  set(PROGRAMS_BUILT
>  	git git-bugreport git-credential-store git-daemon git-fast-import git-http-backend git-sh-i18n--envsubst
> -	git-shell git-remote-testsvn git-credential-cache git-credential-cache--daemon)
> +	git-shell git-remote-testsvn)
> +
> +if(NO_UNIX_SOCKETS)
> +	list(APPEND excluded_progs git-credential-cache git-credential-cache--daemon)
> +else()
> +	list(APPEND PROGRAMS_BUILT git-credential-cache git-credential-cache--daemon)
> +endif()
>  
>  if(NOT CURL_FOUND)
>  	list(APPEND excluded_progs git-http-fetch git-http-push)
> @@ -516,15 +566,34 @@ parse_makefile_for_sources(libvcs-svn_SOURCES "VCSSVN_OBJS")
>  list(TRANSFORM libvcs-svn_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
>  add_library(vcs-svn STATIC ${libvcs-svn_SOURCES})
>  
> +#add git.rc for gcc
> +if(WIN32)
> +	add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/git.res
> +			COMMAND ${WINDRES_EXE} -O coff -DMAJOR=${PROJECT_VERSION_MAJOR} -DMINOR=${PROJECT_VERSION_MINOR}
> +				-DMICRO=${PROJECT_VERSION_PATCH} -DPATCHLEVEL=0 -DGIT_VERSION="\\\"${PROJECT_VERSION}.GIT\\\""
> +				-i ${CMAKE_SOURCE_DIR}/git.rc -o ${CMAKE_BINARY_DIR}/git.res
> +			WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
> +			VERBATIM)
> +	add_custom_target(git-rc DEPENDS ${CMAKE_BINARY_DIR}/git.res)
> +endif()
> +
>  #link all required libraries to common-main
>  add_library(common-main OBJECT ${CMAKE_SOURCE_DIR}/common-main.c)
> -target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES} pthread rt)
> +
> +target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES})
>  if(Intl_FOUND)
>  	target_link_libraries(common-main ${Intl_LIBRARIES})
>  endif()
>  if(Iconv_FOUND)
>  	target_link_libraries(common-main ${Iconv_LIBRARIES})
>  endif()
> +if(WIN32)
> +	target_link_libraries(common-main ws2_32 ntdll ${CMAKE_BINARY_DIR}/git.res)
> +	add_dependencies(common-main git-rc)
> +	target_link_options(common-main PUBLIC -municode -Wl,--nxcompat -Wl,--dynamicbase -Wl,--pic-executable,-e,mainCRTStartup)
> +elseif(UNIX)
> +	target_link_libraries(common-main pthread rt)
> +endif()


Small note about pthread.  In CMake land, the typical convention is to
use the FindThreads module. [1]

To use it, add this to the top-level:

	set(THREADS_PREFER_PTHREAD_FLAG TRUE)
	find_package(Threads REQUIRED)

and then use the Threads::Threads target with target_link_libraries()
instead of hard-coding "pthread" here.

That way it'll only use the "-pthread" flag and library links as needed.

I'm not sure if mingw makes this advice moot, but I figured it was worth
mentioning.

[1] https://cmake.org/cmake/help/latest/module/FindThreads.html
Sibi Siddharthan July 1, 2020, 5:45 p.m. UTC | #2
This module should not be used here as Git is built with pthreads in mind.
All of the Linux systems have the pthread library at install. For
Windows, there is a pthread layer implemented using Win32 calls in
compat/win32/pthread.c,h .

It would be nice if the library checks for pthreads on Windows
(libwinpthread and similar implementations), but it does not.

Thank You,
Sibi Siddharthan

On Tue, Jun 30, 2020 at 12:55 PM David Aguilar <davvid@gmail.com> wrote:
>
> On Fri, Jun 26, 2020 at 04:11:36PM +0000, Sibi Siddharthan via GitGitGadget wrote:
> > From: Sibi Siddharthan <sibisiddharthan.github@gmail.com>
> >
> > This patch facilitates building git on Windows with CMake using MinGW
> >
> > NOTE: The funtions unsetenv and hstrerror are not checked in Windows
> > builds.
> > Reasons
> > NO_UNSETENV is not compatible with Windows builds.
> > lines 262-264 compat/mingw.h
> >
> > compat/mingw.h(line 25) provides a definition of hstrerror which
> > conflicts with the definition provided in
> > git-compat-util.h(lines 733-736).
> >
> > To use CMake on Windows with MinGW do this:
> > cmake `relative-path-to-srcdir` -G "MinGW Makefiles"
> >
> > Signed-off-by: Sibi Siddharthan <sibisiddharthan.github@gmail.com>
> > ---
> >  contrib/buildsystems/CMakeLists.txt | 117 ++++++++++++++++++++++------
> >  1 file changed, 94 insertions(+), 23 deletions(-)
> >
> > diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
> > index 2768ee5b71..2d7c0ed88e 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}/../..)
> >
> >  find_program(SH_EXE sh)
> > +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/")
> > +endif()
> >
> >  #Create GIT-VERSION-FILE using GIT-VERSION-GEN
> >  if(NOT EXISTS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE)
> > @@ -65,7 +69,9 @@ project(git
> >       VERSION ${git_version}
> >       LANGUAGES C)
> >
> > +
> >  #TODO gitk git-gui gitweb
> > +#TODO Enable NLS on windows natively
> >  #TODO Add pcre support
> >
> >  #macros for parsing the Makefile for sources and scripts
> > @@ -104,6 +110,7 @@ find_package(EXPAT)
> >  find_package(Iconv)
> >  find_package(Intl)
> >
> > +
> >  if(NOT Intl_FOUND)
> >       add_compile_definitions(NO_GETTEXT)
> >       if(NOT Iconv_FOUND)
> > @@ -125,6 +132,14 @@ if(Intl_FOUND)
> >       include_directories(SYSTEM ${Intl_INCLUDE_DIRS})
> >  endif()
> >
> > +
> > +if(WIN32)
> > +     find_program(WINDRES_EXE windres)
> > +     if(NOT WINDRES_EXE)
> > +             message(FATAL_ERROR "Install windres on Windows for resource files")
> > +     endif()
> > +endif()
> > +
> >  find_program(MSGFMT_EXE msgfmt)
> >  if(NOT MSGFMT_EXE)
> >       message(WARNING "Text Translations won't be build")
> > @@ -156,11 +171,35 @@ add_compile_definitions(PAGER_ENV="LESS=FRX LV=-c"
> >                       BINDIR="bin"
> >                       GIT_BUILT_FROM_COMMIT="")
> >
> > -set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
> > -add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
> > +if(WIN32)
> > +     set(FALLBACK_RUNTIME_PREFIX /mingw64)
> > +     add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
> > +else()
> > +     set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
> > +     add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
> > +endif()
> > +
> > +
> > +#Platform Specific
> > +if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
> > +     include_directories(${CMAKE_SOURCE_DIR}/compat/win32)
> > +     add_compile_definitions(HAVE_ALLOCA_H NO_POSIX_GOODIES NATIVE_CRLF NO_UNIX_SOCKETS WIN32
> > +                             _CONSOLE DETECT_MSYS_TTY STRIP_EXTENSION=".exe"  NO_SYMLINK_HEAD UNRELIABLE_FSTAT
> > +                             NOGDI OBJECT_CREATION_MODE=1 __USE_MINGW_ANSI_STDIO=0
> > +                             USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
> > +                             UNICODE _UNICODE HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET)
> > +     list(APPEND compat_SOURCES compat/mingw.c compat/winansi.c compat/win32/path-utils.c
> > +             compat/win32/pthread.c compat/win32mmap.c compat/win32/syslog.c
> > +             compat/win32/trace2_win32_process_info.c compat/win32/dirent.c
> > +             compat/nedmalloc/nedmalloc.c compat/strdup.c)
> > +     set(NO_UNIX_SOCKETS 1)
> > +
> > +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
> > +     add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
> > +     list(APPEND compat_SOURCES unix-socket.c)
> > +endif()
> >
> > -add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
> > -list(APPEND compat_SOURCES unix-socket.c)
> > +set(EXE_EXTENSION ${CMAKE_EXECUTABLE_SUFFIX})
> >
> >  #header checks
> >  check_include_file(libgen.h HAVE_LIBGEN_H)
> > @@ -223,7 +262,12 @@ endif()
> >  #function checks
> >  set(function_checks
> >       strcasestr memmem strlcpy strtoimax strtoumax strtoull
> > -     setenv mkdtemp poll pread memmem unsetenv hstrerror)
> > +     setenv mkdtemp poll pread memmem)
> > +
> > +#unsetenv,hstrerror are incompatible with windows build
> > +if(NOT WIN32)
> > +     list(APPEND function_checks unsetenv hstrerror)
> > +endif()
> >
> >  foreach(f ${function_checks})
> >       string(TOUPPER ${f} uf)
> > @@ -444,7 +488,13 @@ unset(CMAKE_REQUIRED_INCLUDES)
> >  #programs
> >  set(PROGRAMS_BUILT
> >       git git-bugreport git-credential-store git-daemon git-fast-import git-http-backend git-sh-i18n--envsubst
> > -     git-shell git-remote-testsvn git-credential-cache git-credential-cache--daemon)
> > +     git-shell git-remote-testsvn)
> > +
> > +if(NO_UNIX_SOCKETS)
> > +     list(APPEND excluded_progs git-credential-cache git-credential-cache--daemon)
> > +else()
> > +     list(APPEND PROGRAMS_BUILT git-credential-cache git-credential-cache--daemon)
> > +endif()
> >
> >  if(NOT CURL_FOUND)
> >       list(APPEND excluded_progs git-http-fetch git-http-push)
> > @@ -516,15 +566,34 @@ parse_makefile_for_sources(libvcs-svn_SOURCES "VCSSVN_OBJS")
> >  list(TRANSFORM libvcs-svn_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
> >  add_library(vcs-svn STATIC ${libvcs-svn_SOURCES})
> >
> > +#add git.rc for gcc
> > +if(WIN32)
> > +     add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/git.res
> > +                     COMMAND ${WINDRES_EXE} -O coff -DMAJOR=${PROJECT_VERSION_MAJOR} -DMINOR=${PROJECT_VERSION_MINOR}
> > +                             -DMICRO=${PROJECT_VERSION_PATCH} -DPATCHLEVEL=0 -DGIT_VERSION="\\\"${PROJECT_VERSION}.GIT\\\""
> > +                             -i ${CMAKE_SOURCE_DIR}/git.rc -o ${CMAKE_BINARY_DIR}/git.res
> > +                     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
> > +                     VERBATIM)
> > +     add_custom_target(git-rc DEPENDS ${CMAKE_BINARY_DIR}/git.res)
> > +endif()
> > +
> >  #link all required libraries to common-main
> >  add_library(common-main OBJECT ${CMAKE_SOURCE_DIR}/common-main.c)
> > -target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES} pthread rt)
> > +
> > +target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES})
> >  if(Intl_FOUND)
> >       target_link_libraries(common-main ${Intl_LIBRARIES})
> >  endif()
> >  if(Iconv_FOUND)
> >       target_link_libraries(common-main ${Iconv_LIBRARIES})
> >  endif()
> > +if(WIN32)
> > +     target_link_libraries(common-main ws2_32 ntdll ${CMAKE_BINARY_DIR}/git.res)
> > +     add_dependencies(common-main git-rc)
> > +     target_link_options(common-main PUBLIC -municode -Wl,--nxcompat -Wl,--dynamicbase -Wl,--pic-executable,-e,mainCRTStartup)
> > +elseif(UNIX)
> > +     target_link_libraries(common-main pthread rt)
> > +endif()
>
>
> Small note about pthread.  In CMake land, the typical convention is to
> use the FindThreads module. [1]
>
> To use it, add this to the top-level:
>
>         set(THREADS_PREFER_PTHREAD_FLAG TRUE)
>         find_package(Threads REQUIRED)
>
> and then use the Threads::Threads target with target_link_libraries()
> instead of hard-coding "pthread" here.
>
> That way it'll only use the "-pthread" flag and library links as needed.
>
> I'm not sure if mingw makes this advice moot, but I figured it was worth
> mentioning.
>
> [1] https://cmake.org/cmake/help/latest/module/FindThreads.html
> --
> David
Sibi Siddharthan July 1, 2020, 5:49 p.m. UTC | #3
Sorry for top posting, I realized it only after clicking send :)

Patch
diff mbox series

diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 2768ee5b71..2d7c0ed88e 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}/../..)
 
 find_program(SH_EXE sh)
+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/")
+endif()
 
 #Create GIT-VERSION-FILE using GIT-VERSION-GEN
 if(NOT EXISTS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE)
@@ -65,7 +69,9 @@  project(git
 	VERSION ${git_version}
 	LANGUAGES C)
 
+
 #TODO gitk git-gui gitweb
+#TODO Enable NLS on windows natively
 #TODO Add pcre support
 
 #macros for parsing the Makefile for sources and scripts
@@ -104,6 +110,7 @@  find_package(EXPAT)
 find_package(Iconv)
 find_package(Intl)
 
+
 if(NOT Intl_FOUND)
 	add_compile_definitions(NO_GETTEXT)
 	if(NOT Iconv_FOUND)
@@ -125,6 +132,14 @@  if(Intl_FOUND)
 	include_directories(SYSTEM ${Intl_INCLUDE_DIRS})
 endif()
 
+
+if(WIN32)
+	find_program(WINDRES_EXE windres)
+	if(NOT WINDRES_EXE)
+		message(FATAL_ERROR "Install windres on Windows for resource files")
+	endif()
+endif()
+
 find_program(MSGFMT_EXE msgfmt)
 if(NOT MSGFMT_EXE)
 	message(WARNING "Text Translations won't be build")
@@ -156,11 +171,35 @@  add_compile_definitions(PAGER_ENV="LESS=FRX LV=-c"
 			BINDIR="bin"
 			GIT_BUILT_FROM_COMMIT="")
 
-set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
-add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
+if(WIN32)
+	set(FALLBACK_RUNTIME_PREFIX /mingw64)
+	add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
+else()
+	set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
+	add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
+endif()
+
+
+#Platform Specific
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+	include_directories(${CMAKE_SOURCE_DIR}/compat/win32)
+	add_compile_definitions(HAVE_ALLOCA_H NO_POSIX_GOODIES NATIVE_CRLF NO_UNIX_SOCKETS WIN32
+				_CONSOLE DETECT_MSYS_TTY STRIP_EXTENSION=".exe"  NO_SYMLINK_HEAD UNRELIABLE_FSTAT
+				NOGDI OBJECT_CREATION_MODE=1 __USE_MINGW_ANSI_STDIO=0
+				USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
+				UNICODE _UNICODE HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET)
+	list(APPEND compat_SOURCES compat/mingw.c compat/winansi.c compat/win32/path-utils.c
+		compat/win32/pthread.c compat/win32mmap.c compat/win32/syslog.c
+		compat/win32/trace2_win32_process_info.c compat/win32/dirent.c
+		compat/nedmalloc/nedmalloc.c compat/strdup.c)
+	set(NO_UNIX_SOCKETS 1)
+
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+	add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
+	list(APPEND compat_SOURCES unix-socket.c)
+endif()
 
-add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
-list(APPEND compat_SOURCES unix-socket.c)
+set(EXE_EXTENSION ${CMAKE_EXECUTABLE_SUFFIX})
 
 #header checks
 check_include_file(libgen.h HAVE_LIBGEN_H)
@@ -223,7 +262,12 @@  endif()
 #function checks
 set(function_checks
 	strcasestr memmem strlcpy strtoimax strtoumax strtoull
-	setenv mkdtemp poll pread memmem unsetenv hstrerror)
+	setenv mkdtemp poll pread memmem)
+
+#unsetenv,hstrerror are incompatible with windows build
+if(NOT WIN32)
+	list(APPEND function_checks unsetenv hstrerror)
+endif()
 
 foreach(f ${function_checks})
 	string(TOUPPER ${f} uf)
@@ -444,7 +488,13 @@  unset(CMAKE_REQUIRED_INCLUDES)
 #programs
 set(PROGRAMS_BUILT
 	git git-bugreport git-credential-store git-daemon git-fast-import git-http-backend git-sh-i18n--envsubst
-	git-shell git-remote-testsvn git-credential-cache git-credential-cache--daemon)
+	git-shell git-remote-testsvn)
+
+if(NO_UNIX_SOCKETS)
+	list(APPEND excluded_progs git-credential-cache git-credential-cache--daemon)
+else()
+	list(APPEND PROGRAMS_BUILT git-credential-cache git-credential-cache--daemon)
+endif()
 
 if(NOT CURL_FOUND)
 	list(APPEND excluded_progs git-http-fetch git-http-push)
@@ -516,15 +566,34 @@  parse_makefile_for_sources(libvcs-svn_SOURCES "VCSSVN_OBJS")
 list(TRANSFORM libvcs-svn_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
 add_library(vcs-svn STATIC ${libvcs-svn_SOURCES})
 
+#add git.rc for gcc
+if(WIN32)
+	add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/git.res
+			COMMAND ${WINDRES_EXE} -O coff -DMAJOR=${PROJECT_VERSION_MAJOR} -DMINOR=${PROJECT_VERSION_MINOR}
+				-DMICRO=${PROJECT_VERSION_PATCH} -DPATCHLEVEL=0 -DGIT_VERSION="\\\"${PROJECT_VERSION}.GIT\\\""
+				-i ${CMAKE_SOURCE_DIR}/git.rc -o ${CMAKE_BINARY_DIR}/git.res
+			WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+			VERBATIM)
+	add_custom_target(git-rc DEPENDS ${CMAKE_BINARY_DIR}/git.res)
+endif()
+
 #link all required libraries to common-main
 add_library(common-main OBJECT ${CMAKE_SOURCE_DIR}/common-main.c)
-target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES} pthread rt)
+
+target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES})
 if(Intl_FOUND)
 	target_link_libraries(common-main ${Intl_LIBRARIES})
 endif()
 if(Iconv_FOUND)
 	target_link_libraries(common-main ${Iconv_LIBRARIES})
 endif()
+if(WIN32)
+	target_link_libraries(common-main ws2_32 ntdll ${CMAKE_BINARY_DIR}/git.res)
+	add_dependencies(common-main git-rc)
+	target_link_options(common-main PUBLIC -municode -Wl,--nxcompat -Wl,--dynamicbase -Wl,--pic-executable,-e,mainCRTStartup)
+elseif(UNIX)
+	target_link_libraries(common-main pthread rt)
+endif()
 
 #git
 parse_makefile_for_sources(git_SOURCES "BUILTIN_OBJS")
@@ -575,11 +644,13 @@  endif()
 add_executable(git-remote-testsvn ${CMAKE_SOURCE_DIR}/remote-testsvn.c)
 target_link_libraries(git-remote-testsvn common-main vcs-svn)
 
-add_executable(git-credential-cache ${CMAKE_SOURCE_DIR}/credential-cache.c)
-target_link_libraries(git-credential-cache common-main)
+if(NOT NO_UNIX_SOCKETS)
+	add_executable(git-credential-cache ${CMAKE_SOURCE_DIR}/credential-cache.c)
+	target_link_libraries(git-credential-cache common-main)
 
-add_executable(git-credential-cache--daemon ${CMAKE_SOURCE_DIR}/credential-cache--daemon.c)
-target_link_libraries(git-credential-cache--daemon common-main)
+	add_executable(git-credential-cache--daemon ${CMAKE_SOURCE_DIR}/credential-cache--daemon.c)
+	target_link_libraries(git-credential-cache--daemon common-main)
+endif()
 
 
 set(git_builtin_extra
@@ -591,16 +662,16 @@  set(git_builtin_extra
 foreach(s ${git_SOURCES} ${git_builtin_extra})
 	string(REPLACE "${CMAKE_SOURCE_DIR}/builtin/" "" s ${s})
 	string(REPLACE ".c" "" s ${s})
-	file(APPEND ${CMAKE_BINARY_DIR}/CreateLinks.cmake "file(CREATE_LINK git git-${s})\n")
-	list(APPEND git_links ${CMAKE_BINARY_DIR}/git-${s})
+	file(APPEND ${CMAKE_BINARY_DIR}/CreateLinks.cmake "file(CREATE_LINK git${EXE_EXTENSION} git-${s}${EXE_EXTENSION})\n")
+	list(APPEND git_links ${CMAKE_BINARY_DIR}/git-${s}${EXE_EXTENSION})
 endforeach()
 
 if(CURL_FOUND)
 	set(remote_exes
 		git-remote-https git-remote-ftp git-remote-ftps)
 	foreach(s ${remote_exes})
-		file(APPEND ${CMAKE_BINARY_DIR}/CreateLinks.cmake "file(CREATE_LINK git-remote-http ${s})\n")
-		list(APPEND git_http_links ${CMAKE_BINARY_DIR}/${s})
+		file(APPEND ${CMAKE_BINARY_DIR}/CreateLinks.cmake "file(CREATE_LINK git-remote-http${EXE_EXTENSION} ${s}${EXE_EXTENSION})\n")
+		list(APPEND git_http_links ${CMAKE_BINARY_DIR}/${s}${EXE_EXTENSION})
 	endforeach()
 endif()
 
@@ -722,20 +793,20 @@  set(bin_links
 	git-receive-pack git-upload-archive git-upload-pack)
 
 foreach(b ${bin_links})
-install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git ${CMAKE_INSTALL_PREFIX}/bin/${b})")
+install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/bin/${b}${EXE_EXTENSION})")
 endforeach()
 
-install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git)")
-install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git-shell ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git-shell)")
+install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git${EXE_EXTENSION})")
+install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git-shell${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git-shell${EXE_EXTENSION})")
 
 foreach(b ${git_links})
 	string(REPLACE "${CMAKE_BINARY_DIR}" "" b ${b})
-	install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git ${CMAKE_INSTALL_PREFIX}/libexec/git-core/${b})")
+	install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/${b}${EXE_EXTENSION})")
 endforeach()
 
 foreach(b ${git_http_links})
 	string(REPLACE "${CMAKE_BINARY_DIR}" "" b ${b})
-	install(CODE "file(CREATE_LINK  ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git-remote-http ${CMAKE_INSTALL_PREFIX}/libexec/git-core/${b})")
+	install(CODE "file(CREATE_LINK  ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git-remote-http${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/${b}${EXE_EXTENSION})")
 endforeach()
 
 install(PROGRAMS ${git_shell_scripts} ${git_perl_scripts} ${CMAKE_BINARY_DIR}/git-p4
@@ -784,14 +855,14 @@  set(wrapper_test_scripts
 foreach(script ${wrapper_scripts})
 	file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
 	string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
-	string(REPLACE "@@PROG@@" "${script}" content "${content}")
+	string(REPLACE "@@PROG@@" "${script}${EXE_EXTENSION}" content "${content}")
 	file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/${script} ${content})
 endforeach()
 
 foreach(script ${wrapper_test_scripts})
 	file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
 	string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
-	string(REPLACE "@@PROG@@" "t/helper/${script}" content "${content}")
+	string(REPLACE "@@PROG@@" "t/helper/${script}${EXE_EXTENSION}" content "${content}")
 	file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/${script} ${content})
 endforeach()
 
@@ -857,7 +928,7 @@  file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PTHREADS='${NO_PTHREADS}'\
 file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_UNIX_SOCKETS='${NO_UNIX_SOCKETS}'\n")
 file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PAGER_ENV='${PAGER_ENV}'\n")
 file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "DC_SHA1='${DC_SHA1}'\n")
-file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "X=''\n")
+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")