| @echo off | |
| :: Copyright (C) 1996-2024 Free Software Foundation, Inc. | |
| :: This file is part of GNU Make. | |
| :: | |
| :: GNU Make is free software; you can redistribute it and/or modify it under | |
| :: the terms of the GNU General Public License as published by the Free | |
| :: Software Foundation; either version 3 of the License, or (at your option) | |
| :: any later version. | |
| :: | |
| :: GNU Make is distributed in the hope that it will be useful, but WITHOUT | |
| :: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| :: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. | |
| :: more details. | |
| :: | |
| :: You should have received a copy of the GNU General Public License along | |
| :: with this program. If not, see <https://www.gnu.org/licenses/>. | |
| setlocal | |
| if not "%RECURSEME%"=="%~0" ( | |
| set "RECURSEME=%~0" | |
| %ComSpec% /s /c ""%~0" %*" | |
| goto :EOF | |
| ) | |
| call :Reset | |
| if "%1" == "-h" goto Usage | |
| if "%1" == "--help" goto Usage | |
| echo. | |
| echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8/10/11 | |
| echo. | |
| set MAKE=gnumake | |
| set GUILE=Y | |
| set COMPILER=cl.exe | |
| set RC=rc.exe | |
| set O=obj | |
| set ARCH=x64 | |
| set DEBUG=N | |
| set DIRENT=Y | |
| set VERBOSE=N | |
| if exist maintMakefile ( | |
| set MAINT=Y | |
| ) else ( | |
| set MAINT=N | |
| ) | |
| :ParseSW | |
| if "%1" == "--verbose" goto SetVerbose | |
| if "%1" == "--debug" goto SetDebug | |
| if "%1" == "--without-guile" goto NoGuile | |
| if "%1" == "--x86" goto Set32Bit | |
| if "%1" == "gcc" goto SetCC | |
| if "%1" == "tcc" goto SetTCC | |
| if "%1" == "" goto DoneSW | |
| goto Usage | |
| :SetVerbose | |
| set VERBOSE=Y | |
| shift | |
| goto ParseSW | |
| :SetDebug | |
| set DEBUG=Y | |
| echo - Building without compiler optimizations | |
| shift | |
| goto ParseSW | |
| :NoGuile | |
| set GUILE=N | |
| echo - Building without Guile | |
| shift | |
| goto ParseSW | |
| :Set32Bit | |
| set ARCH=x86 | |
| echo - Building 32bit GNU Make | |
| shift | |
| goto ParseSW | |
| :SetCC | |
| set COMPILER=gcc | |
| set RC=windres | |
| set O=o | |
| echo - Building with GCC | |
| shift | |
| goto ParseSW | |
| :SetTCC | |
| set COMPILER=tcc | |
| set RC=windres | |
| set O=o | |
| echo - Building with TinyC | |
| shift | |
| goto ParseSW | |
| :DoneSW | |
| if "%MAINT%" == "Y" echo - Enabling maintainer mode | |
| if "%COMPILER%" == "gcc" goto FindGcc | |
| if "%COMPILER%" == "tcc" goto FindTcc | |
| :: Find a compiler. Visual Studio requires a lot of effort to locate :-/. | |
| call %COMPILER% >nul 2>&1 | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| :: Visual Studio 15 2017 and above provides the "vswhere" tool | |
| call :FindVswhere | |
| if ERRORLEVEL 1 goto LegacyVS | |
| for /f "tokens=* usebackq" %%i in (`"%VSWHERE%" -latest -property installationPath`) do ( | |
| set InstallPath=%%i | |
| ) | |
| set "VSVARS=%InstallPath%\VC\Auxiliary\Build\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| :: No "vswhere" or it can't find a compiler. Go old-school. | |
| :LegacyVS | |
| set "VSVARS=%VS150COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS110COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS100COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS80COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS71COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%VS70COMNTOOLS%\..\..\VC\vcvarsall.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%V6TOOLS%\VC98\Bin\vcvars32.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%V6TOOLS%\VC97\Bin\vcvars32.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| set "VSVARS=%V5TOOLS%\VC\Bin\vcvars32.bat" | |
| call :CheckMSVC | |
| if not ERRORLEVEL 1 goto FoundMSVC | |
| :: We did not find anything--fail | |
| echo No MSVC compiler available. | |
| echo Please run vcvarsall.bat and/or configure your Path. | |
| exit 1 | |
| :FoundMSVC | |
| set OUTDIR=.\WinRel | |
| set LNKOUT=./WinRel | |
| set "OPTS=/O2 /D NDEBUG" | |
| set LINKOPTS= | |
| if "%DEBUG%" == "Y" set OUTDIR=.\WinDebug | |
| if "%DEBUG%" == "Y" set LNKOUT=./WinDebug | |
| if "%DEBUG%" == "Y" set "OPTS=/Zi /Od /D _DEBUG" | |
| if "%DEBUG%" == "Y" set LINKOPTS=/DEBUG | |
| if "%MAINT%" == "Y" set "OPTS=%OPTS% /D MAKE_MAINTAINER_MODE" | |
| :: Show the compiler version that we found | |
| :: Unfortunately this also shows a "usage" note; I can't find anything better. | |
| echo. | |
| call %COMPILER% | |
| goto FindRC | |
| :FindGcc | |
| set OUTDIR=.\GccRel | |
| set LNKOUT=./GccRel | |
| set OPTS=-O2 | |
| set DIRENT=N | |
| if "%DEBUG%" == "Y" set OPTS=-O0 | |
| if "%DEBUG%" == "Y" set OUTDIR=.\GccDebug | |
| if "%DEBUG%" == "Y" set LNKOUT=./GccDebug | |
| if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE" | |
| :: Show the compiler version that we found | |
| echo. | |
| call %COMPILER% --version | |
| if not ERRORLEVEL 1 goto FindRC | |
| echo No %COMPILER% found. | |
| exit 1 | |
| :FindTcc | |
| set OUTDIR=.\TccRel | |
| set LNKOUT=./TccRel | |
| set OPTS=-O2 | |
| if "%DEBUG%" == "Y" set OPTS=-O0 | |
| if "%DEBUG%" == "Y" set OUTDIR=.\TccDebug | |
| if "%DEBUG%" == "Y" set LNKOUT=./TccDebug | |
| if "%MAINT%" == "Y" set "OPTS=%OPTS% -DMAKE_MAINTAINER_MODE" | |
| :: Show the compiler version that we found | |
| echo. | |
| call %COMPILER% -v | |
| if not ERRORLEVEL 1 goto FindRC | |
| echo No %COMPILER% found. | |
| exit 1 | |
| :FindRC | |
| set HAVE_RC=Y | |
| call where %RC% >nul 2>&1 | |
| if not ERRORLEVEL 1 goto Build | |
| echo. | |
| echo %RC% was not found. Building without UTF-8 resource. | |
| set HAVE_RC=N | |
| :Build | |
| echo. | |
| :: Clean the directory if it exists | |
| if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR% | |
| :: Recreate it | |
| mkdir %OUTDIR% | |
| mkdir %OUTDIR%\src | |
| mkdir %OUTDIR%\src\w32 | |
| mkdir %OUTDIR%\src\w32\compat | |
| mkdir %OUTDIR%\src\w32\subproc | |
| mkdir %OUTDIR%\lib | |
| if "%GUILE%" == "Y" call :ChkGuile | |
| if not exist src\config.h.W32 goto NotConfig | |
| echo. | |
| echo Compiling %OUTDIR% version | |
| copy src\config.h.W32 %OUTDIR%\src\config.h | |
| copy lib\glob.in.h %OUTDIR%\lib\glob.h | |
| copy lib\fnmatch.in.h %OUTDIR%\lib\fnmatch.h | |
| if exist %OUTDIR%\link.sc del %OUTDIR%\link.sc | |
| call :Compile src/ar | |
| call :Compile src/arscan | |
| call :Compile src/commands | |
| call :Compile src/default | |
| call :Compile src/dir | |
| call :Compile src/expand | |
| call :Compile src/file | |
| call :Compile src/function | |
| call :Compile src/getopt | |
| call :Compile src/getopt1 | |
| call :Compile src/guile GUILE | |
| call :Compile src/hash | |
| call :Compile src/implicit | |
| call :Compile src/job | |
| call :Compile src/load | |
| call :Compile src/loadapi | |
| call :Compile src/main GUILE | |
| call :Compile src/misc | |
| call :Compile src/output | |
| call :Compile src/read | |
| call :Compile src/remake | |
| call :Compile src/remote-stub | |
| call :Compile src/rule | |
| call :Compile src/shuffle | |
| call :Compile src/signame | |
| call :Compile src/strcache | |
| call :Compile src/variable | |
| call :Compile src/version | |
| call :Compile src/vpath | |
| call :Compile src/warning | |
| call :Compile src/w32/pathstuff | |
| call :Compile src/w32/w32os | |
| call :Compile src/w32/compat/posixfcn | |
| call :Compile src/w32/subproc/misc | |
| call :Compile src/w32/subproc/sub_proc | |
| call :Compile src/w32/subproc/w32err | |
| call :Compile lib/fnmatch | |
| call :Compile lib/glob | |
| call :Compile lib/getloadavg | |
| :: Compile dirent unless it is supported by compiler library (like with gcc). | |
| if "%DIRENT%" == "Y" call :Compile src\w32\compat\dirent | |
| :: Compile UTF-8 resource if a resource compiler is available. | |
| if "%HAVE_RC%" == "Y" call :ResourceCompile src/w32/utf8 | |
| call :Link | |
| echo. | |
| if exist %OUTDIR%\%MAKE%.exe goto Success | |
| echo %OUTDIR% build FAILED! | |
| exit 1 | |
| :Success | |
| echo %OUTDIR% build succeeded. | |
| if exist Basic.mk copy /Y Basic.mk Makefile | |
| if not exist tests\config-flags.pm copy /Y tests\config-flags.pm.W32 tests\config-flags.pm | |
| call :Reset | |
| goto :EOF | |
| :: | |
| :: Subroutines | |
| :: | |
| :Compile | |
| if "%VERBOSE%" == "N" echo - Compiling %1.c | |
| echo %LNKOUT%/%1.%O% >>%OUTDIR%\link.sc | |
| set EXTRAS= | |
| if "%2" == "GUILE" set "EXTRAS=%GUILECFLAGS%" | |
| if exist "%OUTDIR%\%1.%O%" del "%OUTDIR%\%1.%O%" | |
| if "%COMPILER%" == "gcc" goto GccCompile | |
| if "%COMPILER%" == "tcc" goto TccCompile | |
| :: MSVC Compile | |
| if "%VERBOSE%" == "Y" echo on | |
| call %COMPILER% /nologo /MT /W4 /EHsc %OPTS% /I %OUTDIR%/src /I src /I %OUTDIR%/lib /I lib /I src/w32/include /D _CONSOLE /D HAVE_CONFIG_H /FR%OUTDIR% /Fp%OUTDIR%\%MAKE%.pch /Fo%OUTDIR%\%1.%O% /Fd%OUTDIR%\%MAKE%.pdb %EXTRAS% /c %1.c | |
| @echo off | |
| goto CompileDone | |
| :GccCompile | |
| :: GCC Compile | |
| if "%VERBOSE%" == "Y" echo on | |
| call %COMPILER% -mthreads -Wall -std=gnu99 -gdwarf-2 -g3 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR%/lib -I./lib -I./src/w32/include -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%/%1.%O% -c %1.c | |
| @echo off | |
| goto CompileDone | |
| :TccCompile | |
| :: TCC Compile | |
| if "%VERBOSE%" == "Y" echo on | |
| call %COMPILER% -mthreads -Wall -std=c11 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR%/lib -I./lib -I./src/w32/include -D_cdecl= -D_MSC_VER -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%/%1.%O% -c %1.c | |
| @echo off | |
| goto CompileDone | |
| :ResourceCompile | |
| if "%VERBOSE%" == "N" echo - Compiling %1.rc | |
| echo %LNKOUT%/%1.%O% >>%OUTDIR%\link.sc | |
| if exist "%OUTDIR%\%1.%O%" del "%OUTDIR%\%1.%O%" | |
| if "%COMPILER%" == "gcc" goto GccResourceCompile | |
| if "%COMPILER%" == "tcc" goto TccResourceCompile | |
| :: MSVC Resource Compile | |
| if "%VERBOSE%" == "Y" echo on | |
| call %RC% /fo %OUTDIR%\%1.%O% %1.rc | |
| @echo off | |
| goto CompileDone | |
| :GccResourceCompile | |
| :: GCC Resource Compile | |
| if "%VERBOSE%" == "Y" echo on | |
| call %RC% -o %OUTDIR%/%1.%O% -i %1.rc | |
| @echo off | |
| goto CompileDone | |
| :TccResourceCompile | |
| :: TCC Resource Compile | |
| goto GccResourceCompile | |
| :CompileDone | |
| if not exist "%OUTDIR%\%1.%O%" exit 1 | |
| goto :EOF | |
| :Link | |
| echo. | |
| echo - Linking %LNKOUT%/%MAKE%.exe | |
| if "%COMPILER%" == "gcc" goto GccLink | |
| if "%COMPILER%" == "tcc" goto TccLink | |
| :: MSVC Link | |
| echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib >>%OUTDIR%\link.sc | |
| if "%VERBOSE%" == "Y" echo on | |
| call link.exe /NOLOGO /SUBSYSTEM:console /PDB:%LNKOUT%\%MAKE%.pdb %LINKOPTS% /OUT:%LNKOUT%\%MAKE%.exe @%LNKOUT%\link.sc | |
| @echo off | |
| goto :EOF | |
| :GccLink | |
| :: GCC Link | |
| if "%VERBOSE%" == "Y" echo on | |
| echo %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 >>%OUTDIR%\link.sc | |
| call %COMPILER% -mthreads -gdwarf-2 -g3 %OPTS% -o %LNKOUT%/%MAKE%.exe @%LNKOUT%/link.sc -Wl,--out-implib=%LNKOUT%/libgnumake-1.dll.a | |
| @echo off | |
| goto :EOF | |
| :TccLink | |
| :: TCC Link | |
| if "%VERBOSE%" == "Y" echo on | |
| echo %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lodbc32 -lodbccp32 >>%OUTDIR%\link.sc | |
| call %COMPILER% -mthreads %OPTS% -o %LNKOUT%/%MAKE%.exe @%LNKOUT%/link.sc | |
| @echo off | |
| goto :EOF | |
| :ChkGuile | |
| :: Build with Guile is supported only on NT and later versions | |
| if not "%OS%" == "Windows_NT" goto NoGuile | |
| call pkg-config --help > %OUTDIR%\guile.tmp 2> NUL | |
| if ERRORLEVEL 1 goto NoPkgCfg | |
| set PKGMSC= | |
| if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax | |
| echo Checking for Guile 2.0 | |
| call pkg-config --cflags --short-errors "guile-2.0" > %OUTDIR%\gl-c2.tmp 2> NUL | |
| if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\gl-c2.tmp | |
| call pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > %OUTDIR%\gl-l2.tmp 2> NUL | |
| if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\gl-l2.tmp | |
| if not "%GUILECFLAGS%" == "" goto GuileDone | |
| echo Checking for Guile 1.8 | |
| call pkg-config --cflags --short-errors "guile-1.8" > %OUTDIR%\gl-c18.tmp 2> NUL | |
| if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\gl-c18.tmp | |
| call pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > %OUTDIR%\gl-l18.tmp 2> NUL | |
| if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\gl-l18.tmp | |
| if not "%GUILECFLAGS%" == "" goto GuileDone | |
| echo - No Guile found, building without Guile | |
| goto GuileDone | |
| :NoPkgCfg | |
| echo - pkg-config not found, building without Guile | |
| :GuileDone | |
| if "%GUILECFLAGS%" == "" goto :EOF | |
| echo - Guile found: building with Guile | |
| set "GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE" | |
| goto :EOF | |
| :FindVswhere | |
| set VSWHERE=vswhere | |
| call "%VSWHERE%" -help >nul 2>&1 | |
| if not ERRORLEVEL 1 exit /b 0 | |
| set "VSWHERE=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere" | |
| call "%VSWHERE%" -help >nul 2>&1 | |
| if ERRORLEVEL 1 exit /b 1 | |
| goto :EOF | |
| :CheckMSVC | |
| if not exist "%VSVARS%" exit /b 1 | |
| call "%VSVARS%" %ARCH% | |
| if ERRORLEVEL 1 exit /b 1 | |
| call %COMPILER% >nul 2>&1 | |
| if ERRORLEVEL 1 exit /b 1 | |
| goto :EOF | |
| :NotConfig | |
| echo. | |
| echo *** This workspace is not configured. | |
| echo Either retrieve the configured source in the release tarball | |
| echo or, if building from Git, run the .\bootstrap.bat script first. | |
| exit /b 1 | |
| :Usage | |
| echo Usage: %0 [options] [gcc] OR [tcc] | |
| echo Options: | |
| echo. --without-guile Do not compile Guile support even if found | |
| echo. --debug Make a Debug build--default is Release | |
| echo. --x86 Make a 32bit binary--default is 64bit | |
| echo. --help Display these instructions and exit | |
| echo. | |
| echo. "gcc" means compile with GCC, "tcc" means compile with Tiny C's TCC | |
| goto :EOF | |
| :Reset | |
| set ARCH= | |
| set COMPILER= | |
| set DEBUG= | |
| set GUILE= | |
| set GUILECFLAGS= | |
| set GUILELIBS= | |
| set LINKOPTS= | |
| set MAKE= | |
| set NOGUILE= | |
| set O= | |
| set OPTS= | |
| set OUTDIR= | |
| set LNKOUT= | |
| set PKGMSC= | |
| set VSVARS= | |
| goto :EOF |