Extract jobserver implementation into OS-specific files.

* os.h, posixos.c, w32/w32os.c: New files implementing jobserver.
* job.c, job.h, main.c, makeint.h: Move content to new files.
* w32/include/sub_proc.h, w32/subproc/sub_proc.c: Ditto.
* Makefile.am: Build and package OS-specific files.
* build_w32.bat, make_msvc_net2003.vcproj, README.W32.template:
Update for new files, and clean up the build.
* POTFILES.in, maintMakefile, NMakefile.template: Ditto.
* w32/subproc/build.bat: Delete as unused.
This commit is contained in:
Paul Smith 2016-03-06 13:29:43 -05:00
parent 4f8be4bb28
commit fb7a7adc8a
19 changed files with 912 additions and 799 deletions

6
.gitignore vendored
View file

@ -34,6 +34,12 @@ make
*.pdb
*.sbr
# Windows build artifacts
/WinDebug/
/WinRel/
/GccDebug/
/GccRel/
# Distribution artifacts
.dep_segment
.check-git-HEAD

View file

@ -41,14 +41,14 @@ endif
make_SOURCES = ar.c arscan.c commands.c default.c dir.c expand.c file.c \
function.c getopt.c getopt1.c guile.c implicit.c job.c load.c \
loadapi.c main.c misc.c output.c read.c remake.c rule.c \
signame.c strcache.c variable.c version.c vpath.c hash.c \
$(remote)
loadapi.c main.c misc.c output.c posixos.c read.c remake.c \
rule.c signame.c strcache.c variable.c version.c vpath.c \
hash.c $(remote)
EXTRA_make_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
noinst_HEADERS = commands.h dep.h filedef.h job.h makeint.h rule.h variable.h \
debug.h getopt.h gettext.h hash.h output.h
debug.h getopt.h gettext.h hash.h output.h os.h
make_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ \
$(GUILE_LIBS)

View file

@ -107,6 +107,7 @@ OBJS = \
$(OUTDIR)/dirent.obj \
$(OUTDIR)/pathstuff.obj \
$(OUTDIR)/posixfcn.obj \
$(OUTDIR)/w32os.obj \
$(guile)
$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)
@ -127,3 +128,5 @@ $(OUTDIR)/posixfcn.obj : w32/compat/posixfcn.c
$(CC) $(CFLAGS) /c $?
$(OUTDIR)/pathstuff.obj : w32/pathstuff.c
$(CC) $(CFLAGS) /c $?
$(OUTDIR)/w32os.obj : w32/w32os.c
$(CC) $(CFLAGS) /c $?

View file

@ -1,11 +1,12 @@
This version of GNU make has been tested on
Microsoft Windows 2000/XP/2003/Vista/7/2008.
This version of GNU make has been tested on:
Microsoft Windows 2000/XP/2003/Vista/7/8/10
It has also been used on Windows 95/98/NT, and on OS/2.
It builds with the MinGW port of GCC (tested with GCC 3.4.2 and 4.8.1).
It builds with the MinGW port of GCC (tested with GCC 3.4.2, 4.8.1,
and 4.9.3).
It also builds with MSVC 2.x, 4.x, 5.x, 6.x, and 2003 as well as
with .NET 7.x and .NET 2003.
It also builds with MSVC 2.x, 4.x, 5.x, 6.x, 2003, and 14 (2015) as
well as with .NET 7.x and .NET 2003.
As of version 4.0, a build with Guile is supported (tested with Guile
2.0.3). To build with Guile, you will need, in addition to Guile
@ -25,8 +26,9 @@ also provide you with these dependencies or a URL where to download
them. A precompiled 32-bit Windows build of Guile is available from
the ezwinports site mentioned above.
The Windows 32-bit port of GNU make is maintained jointly by various
people. It was originally made by Rob Tulloh.
The Windows port of GNU make is maintained jointly by various people.
It was originally made by Rob Tulloh.
It is currently maintained by Eli Zaretskii.
Do this first, regardless of the build method you choose:
@ -56,7 +58,9 @@ Building with (MinGW-)GCC using build_w32.bat
build_w32.bat gcc
This produces gnumake.exe in the current directory.
This produces gnumake.exe in the GccRel directory.
If you want a version of GNU make built with debugging enabled,
add the --debug option.
The batch file will probe for Guile installation, and will build
gnumake.exe with Guile if it finds it. If you have Guile
@ -76,7 +80,9 @@ Building with (MSVC++-)cl using build_w32.bat or NMakefile
build_w32.bat
(this produces WinDebug/gnumake.exe and WinRel/gnumake.exe)
This produces gnumake.exe in the WinRel directory.
If you want a version of GNU make built with debugging enabled,
add the --debug option.
... OR ...

484
build_w32.bat Normal file → Executable file
View file

@ -15,283 +15,217 @@ rem
rem You should have received a copy of the GNU General Public License along
rem with this program. If not, see <http://www.gnu.org/licenses/>.
if "%1" == "-h" GoTo Usage
if "%1" == "--help" GoTo Usage
if not exist config.h.W32.template GoTo NotSCM
sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > config.h.W32.sed
echo s,%%PACKAGE%%,make,g >> config.h.W32.sed
sed -f config.h.W32.sed config.h.W32.template > config.h.W32
echo static const char *const GUILE_module_defn = ^" \> gmk-default.h
sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\/" gmk-default.scm >> gmk-default.h
echo ^";>> gmk-default.h
:NotSCM
copy config.h.W32 config.h
call :Reset
if "%1" == "-h" goto Usage
if "%1" == "--help" goto Usage
set MAKE=gnumake
set GUILE=Y
set COMPILER=msvc
rem Guile configuration
set GUILECFLAGS=
set GUILELIBS=
set NOGUILE=
set OPT=-O2
set COMPILER=
set PKGMSC=
:ParseSW
if "%1" == "--debug" GoTo SetOpt
if "%1" == "--without-guile" GoTo NoGuile
if "%1" == "gcc" GoTo SetCC
if "%1" == "" GoTo ChkGuile
:SetOpt
set OPT=-O0
if "%1" == "--debug" goto SetDebug
if "%1" == "--without-guile" goto NoGuile
if "%1" == "gcc" goto SetCC
if "%1" == "" goto DoneSW
:SetDebug
set DEBUG=Y
shift
GoTo ParseSW
goto ParseSW
:NoGuile
set NOGUILE=Y
echo "Building without Guile"
set GUILE=N
echo Building without Guile
shift
GoTo ParseSW
goto ParseSW
:SetCC
set COMPILER=gcc
echo "Building with GCC"
echo Building with GCC
shift
GoTo ParseSW
rem Build with Guile is supported only on NT and later versions
:ChkGuile
if "%NOGUILE%" == "Y" GoTo GuileDone
if not "%OS%" == "Windows_NT" GoTo NoGuile
pkg-config --help > guile.tmp 2> NUL
if ERRORLEVEL 1 GoTo NoPkgCfg
echo "Checking for Guile 2.0"
if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax
pkg-config --cflags --short-errors "guile-2.0" > guile.tmp
if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp
pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > guile.tmp
if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp
if not "%GUILECFLAGS%" == "" GoTo GuileDone
echo "Checking for Guile 1.8"
pkg-config --cflags --short-errors "guile-1.8" > guile.tmp
if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp
pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > guile.tmp
if not ERRORLEVEL 1 set /P GUILELIBS= < guile.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 not "%GUILECFLAGS%" == "" echo "Guile found, building with Guile"
if not "%GUILECFLAGS%" == "" set GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE
if "%COMPILER%" == "gcc" if "%OPT%" == "-O0" echo "Building without compiler optimizations"
cd w32\subproc
echo.
echo "Creating the subproc library"
%ComSpec% /c build.bat
cd ..\..
goto ParseSW
if exist link.dbg del link.dbg
if exist link.rel del link.rel
rem Build with Guile is supported only on NT and later versions
:DoneSW
echo.
echo "Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8"
if "%COMPILER%" == "gcc" GoTo GCCBuild
set make=gnumake
echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8
if "%DEBUG%" == "Y" echo Building without compiler optimizations
if "%COMPILER%" == "gcc" goto GccBuild
set OUTDIR=.\WinRel
set "OPTS=/O2 /D NDEBUG"
set LINKOPTS=
if "%DEBUG%" == "Y" set OUTDIR=.\WinDebug
if "%DEBUG%" == "Y" set "OPTS=/Zi /Od /D _DEBUG"
if "%DEBUG%" == "Y" set LINKOPTS=/DEBUG
call :Build
goto Done
:GccBuild
set OUTDIR=.\GccRel
set OPTS=-O2
if "%DEBUG%" == "Y" set OPTS=-O0
if "%DEBUG%" == "Y" set OUTDIR=.\GccDebug
call :Build
goto Done
:Done
call :Reset
goto :EOF
:Build
:: Clean the directory if it exists
if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR%
:: Recreate it
mkdir %OUTDIR%
mkdir %OUTDIR%\glob
mkdir %OUTDIR%\w32
mkdir %OUTDIR%\w32\compat
mkdir %OUTDIR%\w32\subproc
if "%GUILE%" == "Y" call :ChkGuile
echo.
echo Compiling %OUTDIR% version
if exist config.h.W32.template call :ConfigSCM
copy config.h.W32 %OUTDIR%\config.h
call :Compile ar
call :Compile arscan
call :Compile commands
call :Compile default
call :Compile dir
call :Compile expand
call :Compile file
call :Compile function
call :Compile getloadavg
call :Compile getopt
call :Compile getopt1
call :Compile glob\fnmatch
call :Compile glob\glob
call :Compile guile GUILE
call :Compile hash
call :Compile implicit
call :Compile job
call :Compile load
call :Compile loadapi
call :Compile main GUILE
call :Compile misc
call :Compile output
call :Compile read
call :Compile remake
call :Compile remote-stub
call :Compile rule
call :Compile signame
call :Compile strcache
call :Compile variable
call :Compile version
call :Compile vpath
call :Compile w32\compat\posixfcn
call :Compile w32\pathstuff
call :Compile w32\subproc\misc
call :Compile w32\subproc\sub_proc
call :Compile w32\subproc\w32err
call :Compile w32\w32os
if not "%COMPILER%" == "gcc" call :Compile w32\compat\dirent
call :Link
echo.
if not exist %OUTDIR%\%MAKE%.exe echo %OUTDIR% build FAILED!
if exist %OUTDIR%\%MAKE%.exe echo %OUTDIR% build succeeded.
goto :EOF
:Compile
set EXTRAS=
if "%2" == "GUILE" set "EXTRAS=%GUILECFLAGS%"
if "%COMPILER%" == "gcc" goto GccCompile
:: MSVC Compile
echo on
if not exist .\WinDebug\nul mkdir .\WinDebug
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c
echo WinDebug\variable.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c rule.c
echo WinDebug\rule.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remote-stub.c
echo WinDebug\remote-stub.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c commands.c
echo WinDebug\commands.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c file.c
echo WinDebug\file.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getloadavg.c
echo WinDebug\getloadavg.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c default.c
echo WinDebug\default.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c signame.c
echo WinDebug\signame.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c expand.c
echo WinDebug\expand.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c dir.c
echo WinDebug\dir.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od %GUILECFLAGS% /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c main.c
echo WinDebug\main.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt1.c
echo WinDebug\getopt1.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c job.c
echo WinDebug\job.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c output.c
echo WinDebug\output.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c read.c
echo WinDebug\read.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c version.c
echo WinDebug\version.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt.c
echo WinDebug\getopt.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c arscan.c
echo WinDebug\arscan.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c hash.c
echo WinDebug\hash.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c strcache.c
echo WinDebug\strcache.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remake.c
echo WinDebug\remake.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c misc.c
echo WinDebug\misc.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c ar.c
echo WinDebug\ar.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c function.c
echo WinDebug\function.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c vpath.c
echo WinDebug\vpath.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c implicit.c
echo WinDebug\implicit.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c loadapi.c
echo WinDebug\loadapi.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c load.c
echo WinDebug\load.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\dirent.c
echo WinDebug\dirent.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\posixfcn.c
echo WinDebug\posixfcn.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\glob.c
echo WinDebug\glob.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\fnmatch.c
echo WinDebug\fnmatch.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\pathstuff.c
echo WinDebug\pathstuff.obj >>link.dbg
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od %GUILECFLAGS% /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c guile.c
echo WinDebug\guile.obj >>link.dbg
:LinkDbg
echo off
echo "Linking WinDebug/%make%.exe"
rem link.exe %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 w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj .\WinDebug/rule.obj .\WinDebug/remote-stub.obj .\WinDebug/commands.obj .\WinDebug/file.obj .\WinDebug/getloadavg.obj .\WinDebug/default.obj .\WinDebug/signame.obj .\WinDebug/expand.obj .\WinDebug/dir.obj .\WinDebug/main.obj .\WinDebug/getopt1.obj .\WinDebug/job.obj .\WinDebug/output.obj .\WinDebug/read.obj .\WinDebug/version.obj .\WinDebug/getopt.obj .\WinDebug/arscan.obj .\WinDebug/remake.obj .\WinDebug/hash.obj .\WinDebug/strcache.obj .\WinDebug/misc.obj .\WinDebug/ar.obj .\WinDebug/function.obj .\WinDebug/vpath.obj .\WinDebug/implicit.obj .\WinDebug/dirent.obj .\WinDebug/glob.obj .\WinDebug/fnmatch.obj .\WinDebug/pathstuff.obj
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 w32\subproc\windebug\subproc.lib >>link.dbg
link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe @link.dbg
if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
if not exist .\WinRel\nul mkdir .\WinRel
echo on
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /D TIVOLI /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c variable.c
echo WinRel\variable.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c rule.c
echo WinRel\rule.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remote-stub.c
echo WinRel\remote-stub.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c commands.c
echo WinRel\commands.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c file.c
echo WinRel\file.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getloadavg.c
echo WinRel\getloadavg.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c default.c
echo WinRel\default.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c signame.c
echo WinRel\signame.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c expand.c
echo WinRel\expand.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c dir.c
echo WinRel\dir.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 %GUILECFLAGS% /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c main.c
echo WinRel\main.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt1.c
echo WinRel\getopt1.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c job.c
echo WinRel\job.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c output.c
echo WinRel\output.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c read.c
echo WinRel\read.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c version.c
echo WinRel\version.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt.c
echo WinRel\getopt.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c arscan.c
echo WinRel\arscan.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remake.c
echo WinRel\remake.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c hash.c
echo WinRel\hash.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c strcache.c
echo WinRel\strcache.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c misc.c
echo WinRel\misc.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c ar.c
echo WinRel\ar.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c function.c
echo WinRel\function.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c vpath.c
echo WinRel\vpath.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c implicit.c
echo WinRel\implicit.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c loadapi.c
echo WinRel\loadapi.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c load.c
echo WinRel\load.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\dirent.c
echo WinRel\dirent.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\posixfcn.c
echo WinRel\posixfcn.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\glob.c
echo WinRel\glob.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\fnmatch.c
echo WinRel\fnmatch.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\pathstuff.c
echo WinRel\pathstuff.obj >>link.rel
cl.exe /nologo /MT /W4 /GX /YX /O2 %GUILECFLAGS% /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c guile.c
echo WinRel\guile.obj >>link.rel
:LinkRel
echo off
echo "Linking WinRel/%make%.exe"
rem link.exe %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 w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj .\WinRel/rule.obj .\WinRel/remote-stub.obj .\WinRel/commands.obj .\WinRel/file.obj .\WinRel/getloadavg.obj .\WinRel/default.obj .\WinRel/signame.obj .\WinRel/expand.obj .\WinRel/dir.obj .\WinRel/main.obj .\WinRel/getopt1.obj .\WinRel/job.obj .\WinRel/output.obj .\WinRel/read.obj .\WinRel/version.obj .\WinRel/getopt.obj .\WinRel/arscan.obj .\WinRel/remake.obj .\WinRel/misc.obj .\WinRel/hash.obj .\WinRel/strcache.obj .\WinRel/ar.obj .\WinRel/function.obj .\WinRel/vpath.obj .\WinRel/implicit.obj .\WinRel/dirent.obj .\WinRel/glob.obj .\WinRel/fnmatch.obj .\WinRel/pathstuff.obj
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 w32\subproc\winrel\subproc.lib >>link.rel
link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe @link.rel
if not exist .\WinRel/%make%.exe echo "WinRel build failed"
if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
set make=
GoTo BuildEnd
:GCCBuild
echo on
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H %GUILECFLAGS% -c main.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c output.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c strcache.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c loadapi.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c load.c
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/compat/posixfcn.c -o posixfcn.o
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% %GUILECFLAGS% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c guile.c
:LinkGCC
cl.exe /nologo /MT /W4 /GX /YX %OPTS% /I %OUTDIR% /I . /I glob /I w32/include /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR%OUTDIR% /Fp%OUTDIR%\%MAKE%.pch /Fo%OUTDIR%\%1.obj /Fd%OUTDIR%\%MAKE%.pdb %EXTRAS% /c %1.c
@echo off
Rem The version NN of libgnumake-NN.dll.a should be bumped whenever
Rem the API changes in binary-incompatible manner.
@echo on
gcc -mthreads -gdwarf-2 -g3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o guile.o job.o output.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o loadapi.o load.o glob.o fnmatch.o pathstuff.o posixfcn.o w32_misc.o sub_proc.o w32err.o %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -Wl,--out-implib=libgnumake-1.dll.a
@GoTo BuildEnd
echo %OUTDIR%\%1.obj >>%OUTDIR%\link.sc
goto :EOF
:GccCompile
:: GCC Compile
echo on
gcc -mthreads -Wall -gdwarf-2 -g3 %OPTS% -I%OUTDIR% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%\%1.o -c %1.c
@echo off
goto :EOF
:Link
echo Linking %OUTDIR%/%MAKE%.exe
if "%COMPILER%" == "gcc" goto GccLink
:: 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
echo on
link.exe /NOLOGO /SUBSYSTEM:console /PDB:%OUTDIR%\%MAKE%.pdb %LINKOPTS% /OUT:%OUTDIR%\%MAKE%.exe @%OUTDIR%\link.sc
@echo off
goto :EOF
:GccLink
:: GCC Link
echo on
gcc -mthreads -gdwarf-2 -g3 -o %OUTDIR%\%MAKE%.exe %OUTDIR%\variable.o %OUTDIR%\rule.o %OUTDIR%\remote-stub.o %OUTDIR%\commands.o %OUTDIR%\file.o %OUTDIR%\getloadavg.o %OUTDIR%\default.o %OUTDIR%\signame.o %OUTDIR%\expand.o %OUTDIR%\dir.o %OUTDIR%\main.o %OUTDIR%\getopt1.o %OUTDIR%\guile.o %OUTDIR%\job.o %OUTDIR%\output.o %OUTDIR%\read.o %OUTDIR%\version.o %OUTDIR%\getopt.o %OUTDIR%\arscan.o %OUTDIR%\remake.o %OUTDIR%\misc.o %OUTDIR%\hash.o %OUTDIR%\strcache.o %OUTDIR%\ar.o %OUTDIR%\function.o %OUTDIR%\vpath.o %OUTDIR%\implicit.o %OUTDIR%\loadapi.o %OUTDIR%\load.o %OUTDIR%\glob\glob.o %OUTDIR%\glob\fnmatch.o %OUTDIR%\w32\pathstuff.o %OUTDIR%\w32\compat\posixfcn.o %OUTDIR%\w32\w32os.o %OUTDIR%\w32\subproc\misc.o %OUTDIR%\w32\subproc\sub_proc.o %OUTDIR%\w32\subproc\w32err.o %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -Wl,--out-implib=%OUTDIR%\libgnumake-1.dll.a
@echo off
goto :EOF
:ConfigSCM
echo Generating config from SCM templates
sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > %OUTDIR%\config.h.W32.sed
echo s,%%PACKAGE%%,make,g >> %OUTDIR%\config.h.W32.sed
sed -f %OUTDIR%\config.h.W32.sed config.h.W32.template > config.h.W32
echo static const char *const GUILE_module_defn = ^" \> gmk-default.h
sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\\/" gmk-default.scm >> gmk-default.h
echo ^";>> gmk-default.h
goto :EOF
:ChkGuile
if not "%OS%" == "Windows_NT" goto NoGuile
pkg-config --help > %OUTDIR%\guile.tmp 2> NUL
if ERRORLEVEL 1 goto NoPkgCfg
echo Checking for Guile 2.0
if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax
pkg-config --cflags --short-errors "guile-2.0" > %OUTDIR%\guile.tmp
if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\guile.tmp
pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > %OUTDIR%\guile.tmp
if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\guile.tmp
if not "%GUILECFLAGS%" == "" goto GuileDone
echo Checking for Guile 1.8
pkg-config --cflags --short-errors "guile-1.8" > %OUTDIR%\guile.tmp
if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\guile.tmp
pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > %OUTDIR%\guile.tmp
if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\guile.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
:Usage
echo Usage: %0 [options] [gcc]
echo Options:
@ -299,12 +233,18 @@ echo. --debug For GCC only, make a debug build
echo. (MSVC build always makes both debug and release)
echo. --without-guile Do not compile Guile support even if found
echo. --help Display these instructions and exit
:BuildEnd
@echo off
set GUILELIBS=
set GUILECFLAGS=
set PKGMSC=
set OPT=
goto :EOF
:Reset
set COMPILER=
set DEBUG=
set GUILE=
set GUILECFLAGS=
set GUILELIBS=
set LINKOPTS=
set MAKE=
set NOGUILE=
echo on
set OPTS=
set OUTDIR=
set PKGMSC=
goto :EOF

196
job.c
View file

@ -23,6 +23,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include "filedef.h"
#include "commands.h"
#include "variable.h"
#include "os.h"
#include "debug.h"
#include <string.h>
@ -541,11 +542,7 @@ child_handler (int sig UNUSED)
{
++dead_children;
if (job_rfd >= 0)
{
close (job_rfd);
job_rfd = -1;
}
jobserver_signal ();
#ifdef __EMX__
/* The signal handler must called only once! */
@ -1012,35 +1009,12 @@ free_child (struct child *child)
/* If we're using the jobserver and this child is not the only outstanding
job, put a token back into the pipe for it. */
#ifdef WINDOWS32
if (has_jobserver_semaphore () && jobserver_tokens > 1)
if (jobserver_enabled () && jobserver_tokens > 1)
{
if (! release_jobserver_semaphore ())
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
ONS (fatal, NILF,
_("release jobserver semaphore: (Error %ld: %s)"), err, estr);
}
DB (DB_JOBS, (_("Released token for child %p (%s).\n"), child, child->file->name));
}
#else
if (job_fds[1] >= 0 && jobserver_tokens > 1)
{
char token = '+';
int r;
/* Write a job token back to the pipe. */
EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1)
pfatal_with_name (_("write jobserver"));
jobserver_release (1);
DB (DB_JOBS, (_("Released token for child %p (%s).\n"),
child, child->file->name));
}
#endif
--jobserver_tokens;
@ -1092,60 +1066,6 @@ unblock_sigs (void)
}
#endif
#if defined(MAKE_JOBSERVER) && !defined(WINDOWS32)
RETSIGTYPE
job_noop (int sig UNUSED)
{
}
/* Set the child handler action flags to FLAGS. */
static void
set_child_handler_action_flags (int set_handler, int set_alarm)
{
struct sigaction sa;
#ifdef __EMX__
/* The child handler must be turned off here. */
signal (SIGCHLD, SIG_DFL);
#endif
memset (&sa, '\0', sizeof sa);
sa.sa_handler = child_handler;
sa.sa_flags = set_handler ? 0 : SA_RESTART;
#if defined SIGCHLD
if (sigaction (SIGCHLD, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGCHLD");
#endif
#if defined SIGCLD && SIGCLD != SIGCHLD
if (sigaction (SIGCLD, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGCLD");
#endif
#if defined SIGALRM
if (set_alarm)
{
/* If we're about to enter the read(), set an alarm to wake up in a
second so we can check if the load has dropped and we can start more
work. On the way out, turn off the alarm and set SIG_DFL. */
if (set_handler)
{
sa.sa_handler = job_noop;
sa.sa_flags = 0;
if (sigaction (SIGALRM, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGALRM");
alarm (1);
}
else
{
alarm (0);
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
if (sigaction (SIGALRM, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGALRM");
}
}
#endif
}
#endif
/* Start a job to run the commands specified in CHILD.
CHILD is updated to reflect the commands and ID of the child process.
@ -1516,13 +1436,8 @@ start_job_command (struct child *child)
# ifdef __EMX__
/* If we aren't running a recursive command and we have a jobserver
pipe, close it before exec'ing. */
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
{
CLOSE_ON_EXEC (job_fds[0]);
CLOSE_ON_EXEC (job_fds[1]);
}
if (job_rfd >= 0)
CLOSE_ON_EXEC (job_rfd);
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
jobserver_pre_child ();
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
child->pid = child_execute_job (child->good_stdin ? FD_STDIN : bad_stdin,
@ -1537,13 +1452,8 @@ start_job_command (struct child *child)
}
/* undo CLOSE_ON_EXEC() after the child process has been started */
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
{
fcntl (job_fds[0], F_SETFD, 0);
fcntl (job_fds[1], F_SETFD, 0);
}
if (job_rfd >= 0)
fcntl (job_rfd, F_SETFD, 0);
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
jobserver_post_child ();
#else /* !__EMX__ */
@ -1554,15 +1464,10 @@ start_job_command (struct child *child)
/* We are the child side. */
unblock_sigs ();
/* If we aren't running a recursive command and we have a jobserver
pipe, close it before exec'ing. */
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
{
close (job_fds[0]);
close (job_fds[1]);
}
if (job_rfd >= 0)
close (job_rfd);
/* If we AREN'T running a recursive command and we have a jobserver,
clear it before exec'ing. */
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
jobserver_clear ();
#ifdef SET_STACK_SIZE
/* Reset limits, if necessary. */
@ -1952,18 +1857,10 @@ new_job (struct file *file)
just once). Also more thought needs to go into the entire algorithm;
this is where the old parallel job code waits, so... */
#ifdef WINDOWS32
else if (has_jobserver_semaphore ())
#else
else if (job_fds[0] >= 0)
#endif
else if (jobserver_enabled ())
while (1)
{
int got_token;
#ifndef WINDOWS32
char token;
int saved_errno;
#endif
DB (DB_JOBS, ("Need a job token; we %shave children\n",
children ? "" : "don't "));
@ -1972,36 +1869,8 @@ new_job (struct file *file)
if (!jobserver_tokens)
break;
#ifndef WINDOWS32
/* Read a token. As long as there's no token available we'll block.
We enable interruptible system calls before the read(2) so that if
we get a SIGCHLD while we're waiting, we'll return with EINTR and
we can process the death(s) and return tokens to the free pool.
Once we return from the read, we immediately reinstate restartable
system calls. This allows us to not worry about checking for
EINTR on all the other system calls in the program.
There is one other twist: there is a span between the time
reap_children() does its last check for dead children and the time
the read(2) call is entered, below, where if a child dies we won't
notice. This is extremely serious as it could cause us to
deadlock, given the right set of events.
To avoid this, we do the following: before we reap_children(), we
dup(2) the read FD on the jobserver pipe. The read(2) call below
uses that new FD. In the signal handler, we close that FD. That
way, if a child dies during the section mentioned above, the
read(2) will be invoked with an invalid FD and will return
immediately with EBADF. */
/* Make sure we have a dup'd FD. */
if (job_rfd < 0)
{
DB (DB_JOBS, ("Duplicate the job FD\n"));
EINTRLOOP (job_rfd, dup (job_fds[0]));
}
#endif
/* Prepare for jobserver token acquisition. */
jobserver_pre_acquire ();
/* Reap anything that's currently waiting. */
reap_children (0, 0);
@ -2010,8 +1879,7 @@ new_job (struct file *file)
can run now (i.e., waiting for load). */
start_waiting_jobs ();
/* If our "free" slot has become available, use it; we don't need an
actual token. */
/* If our "free" slot is available, use it; we don't need a token. */
if (!jobserver_tokens)
break;
@ -2020,26 +1888,8 @@ new_job (struct file *file)
if (!children)
O (fatal, NILF, "INTERNAL: no children as we go to sleep on read\n");
#ifdef WINDOWS32
/* On Windows we simply wait for the jobserver semaphore to become
* signalled or one of our child processes to terminate.
*/
got_token = wait_for_semaphore_or_child_process ();
if (got_token < 0)
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
ONS (fatal, NILF,
_("semaphore or child process wait: (Error %ld: %s)"),
err, estr);
}
#else
/* Set interruptible system calls, and read() for a job token. */
set_child_handler_action_flags (1, waiting_jobs != NULL);
EINTRLOOP (got_token, read (job_rfd, &token, 1));
saved_errno = errno;
set_child_handler_action_flags (0, waiting_jobs != NULL);
#endif
/* Get a token. */
got_token = jobserver_acquire (waiting_jobs != NULL);
/* If we got one, we're done here. */
if (got_token == 1)
@ -2048,16 +1898,6 @@ new_job (struct file *file)
c, c->file->name));
break;
}
#ifndef WINDOWS32
/* If the error _wasn't_ expected (EINTR or EBADF), punt. Otherwise,
go back and reap_children(), and try again. */
errno = saved_errno;
if (errno != EINTR && errno != EBADF)
pfatal_with_name (_("read jobs pipe"));
if (errno == EBADF)
DB (DB_JOBS, ("Read returned EBADF.\n"));
#endif
}
#endif

2
job.h
View file

@ -115,6 +115,8 @@ struct child
extern struct child *children;
/* A signal handler for SIGCHLD, if needed. */
RETSIGTYPE child_handler (int sig);
int is_bourne_compatible_shell(const char *path);
void new_job (struct file *file);
void reap_children (int block, int err);

217
main.c
View file

@ -15,6 +15,7 @@ You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
#include "makeint.h"
#include "os.h"
#include "filedef.h"
#include "dep.h"
#include "variable.h"
@ -270,15 +271,12 @@ static unsigned int inf_jobs = 0;
/* File descriptors for the jobs pipe. */
char *jobserver_fds = 0;
int job_fds[2] = { -1, -1 };
int job_rfd = -1;
char *jobserver_fds = NULL;
/* Handle for the mutex used on Windows to synchronize output of our
children under -O. */
char *sync_mutex = 0;
char *sync_mutex = NULL;
/* Maximum load average at which multiple jobs will be run.
Negative values mean unlimited, while zero means limit to
@ -600,7 +598,7 @@ struct output make_sync;
/* Mask of signals that are being caught with fatal_error_signal. */
#ifdef POSIX
#ifdef POSIX
sigset_t fatal_signal_set;
#else
# ifdef HAVE_SIGSETMASK
@ -1597,85 +1595,33 @@ main (int argc, char **argv, char **envp)
starting_directory = current_directory;
#ifdef MAKE_JOBSERVER
/* If the jobserver-fds option is seen, make sure that -j is reasonable.
/* If the jobserver_fds option is seen, make sure that -j is reasonable.
This can't be usefully set in the makefile, and we want to verify the
FDs are valid before any other aspect of make has a chance to start
using them for something else. */
if (jobserver_fds)
{
/* Make sure the jobserver option has the proper format. */
const char *cp = jobserver_fds;
#ifdef WINDOWS32
if (! open_jobserver_semaphore (cp))
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
fatal (NILF, strlen (cp) + INTSTR_LENGTH + strlen (estr),
_("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
cp, err, estr);
}
DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), cp));
#else
if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
OS (fatal, NILF,
_("internal error: invalid --jobserver-fds string '%s'"), cp);
DB (DB_JOBS,
(_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
#endif
/* The combination of a pipe + !job_slots means we're using the
jobserver. If !job_slots and we don't have a pipe, we can start
infinite jobs. If we see both a pipe and job_slots >0 that means the
/* The combination of jobserver_fds and !job_slots means we're using the
jobserver. If !job_slots and no jobserver_fds, we can start infinite
jobs. If we see both jobserver_fds and job_slots >0 that means the
user set -j explicitly. This is broken; in this case obey the user
(ignore the jobserver pipe for this make) but print a message.
If we've restarted, we already printed this the first time. */
(ignore the jobserver for this make) but print a message. If we've
restarted, we already printed this the first time. */
if (!job_slots)
jobserver_parse_arg (jobserver_fds);
else if (! restarts)
O (error, NILF,
_("warning: -jN forced in submake: disabling jobserver mode."));
if (job_slots > 0)
{
if (! restarts)
O (error, NILF,
_("warning: -jN forced in submake: disabling jobserver mode."));
}
#ifndef WINDOWS32
#ifdef HAVE_FCNTL
# define FD_OK(_f) ((fcntl ((_f), F_GETFD) != -1) || (errno != EBADF))
#else
# define FD_OK(_f) 1
#endif
/* Create a duplicate pipe, that will be closed in the SIGCHLD
handler. If this fails with EBADF, the parent has closed the pipe
on us because it didn't think we were a submake. If so, print a
warning then default to -j1. */
else if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1])
|| (job_rfd = dup (job_fds[0])) < 0)
{
if (errno != EBADF)
pfatal_with_name (_("dup jobserver"));
O (error, NILF,
_("warning: jobserver unavailable: using -j1. Add '+' to parent make rule."));
job_slots = 1;
job_fds[0] = job_fds[1] = -1;
}
#endif
if (job_slots > 0)
{
#ifdef WINDOWS32
free_jobserver_semaphore ();
#else
if (job_fds[0] >= 0)
close (job_fds[0]);
if (job_fds[1] >= 0)
close (job_fds[1]);
#endif
job_fds[0] = job_fds[1] = -1;
/* If job_slots is set now then we're not using jobserver */
jobserver_clear ();
free (jobserver_fds);
jobserver_fds = 0;
jobserver_fds = NULL;
}
}
#endif
@ -1902,7 +1848,7 @@ main (int argc, char **argv, char **envp)
}
#ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
#if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG)
#if !defined(HAVE_WAIT_NOHANG) || defined(MAKE_JOBSERVER)
/* Set up to handle children dying. This must be done before
reading in the makefiles so that 'shell' function calls will work.
@ -1910,9 +1856,9 @@ main (int argc, char **argv, char **envp)
functionality here and rely on the signal handler and counting
children.
If we're using the jobs pipe we need a signal handler so that
SIGCHLD is not ignored; we need it to interrupt the read(2) of the
jobserver pipe in job.c if we're waiting for a token.
If we're using the jobs pipe we need a signal handler so that SIGCHLD is
not ignored; we need it to interrupt the read(2) of the jobserver pipe if
we're waiting for a token.
If none of these are true, we don't need a signal handler at all. */
{
@ -2074,66 +2020,23 @@ main (int argc, char **argv, char **envp)
#endif
#ifdef MAKE_JOBSERVER
/* If we have >1 slot but no jobserver-fds, then we're a top-level make.
Set up the pipe and install the fds option for our children. */
if (job_slots > 1)
{
#ifdef WINDOWS32
/* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects
* and one of them is the job-server semaphore object. Limit the
* number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */
/* If we have >1 slot at this point, then we're a top-level make.
Set up the jobserver.
if (job_slots >= MAXIMUM_WAIT_OBJECTS)
{
job_slots = MAXIMUM_WAIT_OBJECTS - 1;
DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), job_slots));
}
if (! create_jobserver_semaphore (job_slots - 1))
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
ONS (fatal, NILF,
_("creating jobserver semaphore: (Error %ld: %s)"), err, estr);
}
#else
char c = '+';
if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
pfatal_with_name (_("creating jobs pipe"));
#endif
/* Every make assumes that it always has one job it can run. For the
Every make assumes that it always has one job it can run. For the
submakes it's the token they were given by their parent. For the
top make, we just subtract one from the number the user wants. We
want job_slots to be 0 to indicate we're using the jobserver. */
top make, we just subtract one from the number the user wants. */
jobserver_setup (job_slots - 1);
/* We're using the jobserver so set job_slots to 0. */
master_job_slots = job_slots;
#ifdef WINDOWS32
/* We're using the jobserver so set job_slots to 0. */
job_slots = 0;
#else
while (--job_slots)
{
int r;
EINTRLOOP (r, write (job_fds[1], &c, 1));
if (r != 1)
pfatal_with_name (_("init jobserver pipe"));
}
#endif
/* Fill in the jobserver_fds for our children. */
#ifdef WINDOWS32
jobserver_fds = xmalloc (MAX_PATH + 1);
strcpy (jobserver_fds, get_jobserver_semaphore_name ());
#else
jobserver_fds = xmalloc ((INTSTR_LENGTH * 2) + 2);
sprintf (jobserver_fds, "%d,%d", job_fds[0], job_fds[1]);
#endif
jobserver_fds = jobserver_get_arg ();
}
#endif
@ -2489,10 +2392,6 @@ main (int argc, char **argv, char **envp)
fflush (stdout);
fflush (stderr);
/* Close the dup'd jobserver pipe if we opened one. */
if (job_rfd >= 0)
close (job_rfd);
#ifdef _AMIGA
exec_command (nargv);
exit (0);
@ -3444,13 +3343,7 @@ clean_jobserver (int status)
have written all our tokens so do that now. If tokens are left
after any other error code, that's bad. */
#ifdef WINDOWS32
if (has_jobserver_semaphore () && jobserver_tokens)
#else
char token = '+';
if (job_fds[0] != -1 && jobserver_tokens)
#endif
if (jobserver_enabled() && jobserver_tokens)
{
if (status != 2)
ON (error, NILF,
@ -3459,18 +3352,7 @@ clean_jobserver (int status)
else
/* Don't write back the "free" token */
while (--jobserver_tokens)
{
#ifdef WINDOWS32
if (! release_jobserver_semaphore ())
perror_with_name ("release_jobserver_semaphore", "");
#else
int r;
EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1)
perror_with_name ("write", "");
#endif
}
jobserver_release (0);
}
@ -3479,42 +3361,21 @@ clean_jobserver (int status)
if (master_job_slots)
{
/* We didn't write one for ourself, so start at 1. */
unsigned int tcnt = 1;
unsigned int tokens = 1 + jobserver_acquire_all ();
#ifdef WINDOWS32
while (acquire_jobserver_semaphore ())
++tcnt;
#else
/* Close the write side, so the read() won't hang. */
close (job_fds[1]);
while (1)
{
int r;
EINTRLOOP (r, read (job_fds[0], &token, 1));
if (r != 1)
break;
++tcnt;
}
#endif
if (tcnt != master_job_slots)
if (tokens != master_job_slots)
ONN (error, NILF,
"INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
tcnt, master_job_slots);
tokens, master_job_slots);
#ifdef WINDOWS32
free_jobserver_semaphore ();
#else
close (job_fds[0]);
#endif
jobserver_clear ();
/* Clean out jobserver_fds so we don't pass this information to any
sub-makes. Also reset job_slots since it will be put on the command
line, not in MAKEFLAGS. */
job_slots = default_job_slots;
free (jobserver_fds);
jobserver_fds = 0;
jobserver_fds = NULL;
}
}

View file

@ -276,7 +276,7 @@ changelog-check:
po-check:
if test -f po/POTFILES.in; then \
grep '^[^#]' po/POTFILES.in | sort > $@-1; \
$(PERL) -wn -e 'if (/\b_\(/) { $$ARGV eq "makeint.h" || print "$$ARGV\n" and close ARGV }' *.c *.h | sort > $@-2; \
$(PERL) -wn -e 'if (/\b_\(/) { $$ARGV eq "./makeint.h" || print "$$ARGV\n" and close ARGV }' `find . -name '*.[ch]'` | sed 's,^\./,,' | sort > $@-2; \
diff -u $@-1 $@-2 || exit 1; \
rm -f $@-1 $@-2; \
fi

View file

@ -234,6 +234,9 @@
<File
RelativePath=".\w32\pathstuff.c">
</File>
<File
RelativePath=".\w32\w32os.c">
</File>
<File
RelativePath=".\w32\subproc\sub_proc.c">
</File>

View file

@ -623,8 +623,6 @@ extern int batch_mode_shell;
extern char cmd_prefix;
extern unsigned int job_slots;
extern int job_fds[2];
extern int job_rfd;
#ifndef NO_FLOAT
extern double max_load_average;
#else

77
os.h Normal file
View file

@ -0,0 +1,77 @@
/* Declarations for operating system interfaces for GNU Make.
Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. */
/* This section provides OS-specific functions to support the jobserver. */
#ifdef MAKE_JOBSERVER
/* Returns 1 if the jobserver is enabled, else 0. */
unsigned int jobserver_enabled ();
/* Called in the master instance to set up the jobserver initially. */
void jobserver_setup (int job_slots);
/* Called in a child instance to connect to the jobserver. */
void jobserver_parse_arg (const char* arg);
/* Returns an allocated buffer used to pass to child instances. */
char *jobserver_get_arg ();
/* Clear this instance's jobserver configuration. */
void jobserver_clear ();
/* Recover all the jobserver tokens and return the number we got. */
unsigned int jobserver_acquire_all ();
/* Release a jobserver token. If it fails and is_fatal is 1, fatal. */
void jobserver_release (int is_fatal);
/* Notify the jobserver that a child exited. */
void jobserver_signal ();
/* Get ready to start a non-recursive child. */
void jobserver_pre_child ();
/* Complete starting a non-recursive child. */
void jobserver_post_child ();
/* Set up to acquire a new token. */
void jobserver_pre_acquire ();
/* Wait until we can acquire a jobserver token.
TIMEOUT is 1 if we have other jobs waiting for the load to go down;
in this case we won't wait forever, so we can check the load.
Returns 1 if we got a token, or 0 if we stopped waiting due to a child
exiting or a timeout. */
int jobserver_acquire (int timeout);
#else
#define jobserver_enabled() (0)
#define jobserver_setup(_slots) (void)(0)
#define jobserver_parse_arg(_arg) (void)(0)
#define jobserver_get_arg() (NULL)
#define jobserver_clear() (void)(0)
#define jobserver_release(_fatal) (void)(0)
#define jobserver_acquire_all() (0)
#define jobserver_signal() (void)(0)
#define jobserver_pre_child() (void)(0)
#define jobserver_post_child() (void)(0)
#define jobserver_pre_acquire() (void)(0)
#define jobserver_acquire(_tmout) (0)
#endif

View file

@ -32,6 +32,7 @@ load.c
main.c
misc.c
output.c
posixos.c
read.c
remake.c
remote-cstms.c
@ -43,3 +44,4 @@ variable.h
vmsfunctions.c
vmsjobs.c
vpath.c
w32/w32os.c

320
posixos.c Normal file
View file

@ -0,0 +1,320 @@
/* POSIX-based operating system interface for GNU Make.
Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. */
#include "makeint.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include "debug.h"
#include "job.h"
#include "os.h"
#ifdef MAKE_JOBSERVER
/* This section provides OS-specific functions to support the jobserver. */
/* These track the state of the jobserver pipe. Passed to child instances. */
static int job_fds[2] = { -1, -1 };
/* Used to signal read() that a SIGCHLD happened. Always CLOEXEC. */
static int job_rfd = -1;
/* Token written to the pipe (could be any character...) */
static char token = '+';
static int
make_job_rfd ()
{
EINTRLOOP (job_rfd, dup (job_fds[0]));
if (job_rfd >= 0)
CLOSE_ON_EXEC (job_rfd);
return job_rfd;
}
void
jobserver_setup (int slots)
{
int r;
EINTRLOOP (r, pipe (job_fds));
if (r < 0)
pfatal_with_name (_("creating jobs pipe"));
if (make_job_rfd () < 0)
pfatal_with_name (_("duping jobs pipe"));
while (slots--)
{
EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1)
pfatal_with_name (_("init jobserver pipe"));
}
}
void
jobserver_parse_arg (const char* arg)
{
/* Given the command-line parameter, parse it. */
if (sscanf (arg, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
OS (fatal, NILF,
_("internal error: invalid --jobserver-fds string '%s'"), arg);
DB (DB_JOBS,
(_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
#ifdef HAVE_FCNTL
# define FD_OK(_f) ((fcntl ((_f), F_GETFD) != -1) || (errno != EBADF))
#else
# define FD_OK(_f) 1
#endif
/* Create a duplicate pipe, that will be closed in the SIGCHLD handler. If
this fails with EBADF, the parent has closed the pipe on us because it
didn't think we were a submake. If so, warn then default to -j1. */
if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1]) || make_job_rfd () < 0)
{
if (errno != EBADF)
pfatal_with_name (_("dup jobserver"));
O (error, NILF,
_("warning: jobserver unavailable: using -j1. Add '+' to parent make rule."));
job_slots = 1;
job_fds[0] = job_fds[1] = -1;
}
}
char *
jobserver_get_arg ()
{
char *fds = xmalloc ((INTSTR_LENGTH * 2) + 2);
sprintf (fds, "%d,%d", job_fds[0], job_fds[1]);
return fds;
}
unsigned int
jobserver_enabled ()
{
return job_fds[0] >= 0;
}
void
jobserver_clear ()
{
if (job_fds[0] >= 0)
close (job_fds[0]);
if (job_fds[1] >= 0)
close (job_fds[1]);
if (job_rfd >= 0)
close (job_rfd);
job_fds[0] = job_fds[1] = job_rfd = -1;
}
void
jobserver_release (int is_fatal)
{
int r;
EINTRLOOP (r, write (job_fds[1], &token, 1));
if (r != 1)
{
if (is_fatal)
pfatal_with_name (_("write jobserver"));
perror_with_name ("write", "");
}
}
unsigned int
jobserver_acquire_all ()
{
unsigned int tokens = 0;
/* Close the write side, so the read() won't hang. */
close (job_fds[1]);
job_fds[1] = -1;
while (1)
{
char intake;
int r;
EINTRLOOP (r, read (job_fds[0], &intake, 1));
if (r != 1)
return tokens;
++tokens;
}
}
/* This is really only invoked on OS/2.
On POSIX we just call jobserver_clear() in the child process. */
void jobserver_pre_child ()
{
CLOSE_ON_EXEC (job_fds[0]);
CLOSE_ON_EXEC (job_fds[1]);
}
void jobserver_post_child ()
{
#if defined(F_GETFD) && defined(F_SETFD)
for (int i = 0; i < 2; ++i)
{
int flags;
EINTRLOOP (flags, fcntl (job_fds[i], F_GETFD));
if (flags >= 0)
{
int r;
EINTRLOOP (r, fcntl (job_fds[i], F_SETFD, flags & ~FD_CLOEXEC));
}
}
#endif
}
/* The acquire algorithm goes like this (from job.c):
Read a token. As long as there's no token available we'll block. We
enable interruptible system calls before the read(2) so that if we get a
SIGCHLD while we're waiting, we'll return with EINTR and we can process the
death(s) and return tokens to the free pool.
Once we return from the read, we immediately reinstate restartable system
calls. This allows us to not worry about checking for EINTR on all the
other system calls in the program.
There is one other twist: there is a span between the time reap_children()
does its last check for dead children and the time the read(2) call is
entered, below, where if a child dies we won't notice. This is extremely
serious as it could cause us to deadlock, given the right set of events.
To avoid this, we do the following: before we reap_children(), we dup(2)
the read FD on the jobserver pipe. The read(2) call below uses that new
FD. In the signal handler, we close that FD. That way, if a child dies
during the section mentioned above, the read(2) will be invoked with an
invalid FD and will return immediately with EBADF. */
static RETSIGTYPE
job_noop (int sig UNUSED)
{
}
/* Set the child handler action flags to FLAGS. */
static void
set_child_handler_action_flags (int set_handler, int set_alarm)
{
struct sigaction sa;
#ifdef __EMX__
/* The child handler must be turned off here. */
signal (SIGCHLD, SIG_DFL);
#endif
memset (&sa, '\0', sizeof sa);
sa.sa_handler = child_handler;
sa.sa_flags = set_handler ? 0 : SA_RESTART;
#if defined SIGCHLD
if (sigaction (SIGCHLD, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGCHLD");
#endif
#if defined SIGCLD && SIGCLD != SIGCHLD
if (sigaction (SIGCLD, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGCLD");
#endif
#if defined SIGALRM
if (set_alarm)
{
/* If we're about to enter the read(), set an alarm to wake up in a
second so we can check if the load has dropped and we can start more
work. On the way out, turn off the alarm and set SIG_DFL. */
if (set_handler)
{
sa.sa_handler = job_noop;
sa.sa_flags = 0;
if (sigaction (SIGALRM, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGALRM");
alarm (1);
}
else
{
alarm (0);
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
if (sigaction (SIGALRM, &sa, NULL) < 0)
pfatal_with_name ("sigaction: SIGALRM");
}
}
#endif
}
void
jobserver_signal ()
{
if (job_rfd >= 0)
{
close (job_rfd);
job_rfd = -1;
}
}
void
jobserver_pre_acquire ()
{
/* Make sure we have a dup'd FD. */
if (job_rfd < 0 && job_fds[0] >= 0)
{
DB (DB_JOBS, ("Duplicate the job FD\n"));
if (make_job_rfd () < 0)
pfatal_with_name (_("duping jobs pipe"));
}
}
int
jobserver_acquire (int timeout)
{
char intake;
int got_token;
int saved_errno;
/* Set interruptible system calls, and read() for a job token. */
set_child_handler_action_flags (1, timeout);
EINTRLOOP (got_token, read (job_rfd, &intake, 1));
saved_errno = errno;
set_child_handler_action_flags (0, timeout);
if (got_token == 1)
return 1;
/* If the error _wasn't_ expected (EINTR or EBADF), fatal. Otherwise,
go back and reap_children(), and try again. */
errno = saved_errno;
if (errno != EINTR && errno != EBADF)
pfatal_with_name (_("read jobs pipe"));
if (errno == EBADF)
DB (DB_JOBS, ("Read returned EBADF.\n"));
return 0;
}
#endif /* MAKE_JOBSERVER */

View file

@ -118,7 +118,7 @@ closedir (DIR *dir)
struct FAB *dfab = &dir->fab;
struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
if (dnam != NULL)
free (dnam->nam$l_esa);
free (dnam->nam$l_esa);
free (dnam);
free (dir);
}

View file

@ -32,11 +32,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
EXTERN_DECL(HANDLE process_init, (VOID_DECL));
EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,
HANDLE stderrh));
HANDLE stderrh));
EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,
char *exec_path, char *as_user));
char *exec_path, char *as_user));
EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data,
int stdin_data_len));
int stdin_data_len));
EXTERN_DECL(long process_file_io, (HANDLE proc));
EXTERN_DECL(void process_cleanup, (HANDLE proc));
EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus));
@ -45,6 +45,7 @@ EXTERN_DECL(HANDLE process_easy, (char** argv, char** env,
int outfd, int errfd));
EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
EXTERN_DECL(int process_used_slots, (VOID_DECL));
EXTERN_DECL(DWORD process_set_handles, (HANDLE *handles));
/* support routines */
EXTERN_DECL(long process_errno, (HANDLE proc));
@ -58,14 +59,4 @@ EXTERN_DECL(int process_errcnt, (HANDLE proc));
EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));
EXTERN_DECL(void process_noinherit, (int fildes));
/* jobserver routines */
EXTERN_DECL(int open_jobserver_semaphore, (const char* name));
EXTERN_DECL(int create_jobserver_semaphore, (int tokens));
EXTERN_DECL(void free_jobserver_semaphore, (VOID_DECL));
EXTERN_DECL(int acquire_jobserver_semaphore, (VOID_DECL));
EXTERN_DECL(int release_jobserver_semaphore, (VOID_DECL));
EXTERN_DECL(int has_jobserver_semaphore, (VOID_DECL));
EXTERN_DECL(char* get_jobserver_semaphore_name, (VOID_DECL));
EXTERN_DECL(int wait_for_semaphore_or_child_process, (VOID_DECL));
#endif

View file

@ -1,34 +0,0 @@
@if "%COMPILER%" == "gcc" GoTo GCCBuild
if not exist .\WinDebug\nul mkdir .\WinDebug
cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c
cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c
cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c
lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib .\WinDebug/misc.obj .\WinDebug/sub_proc.obj .\WinDebug/w32err.obj
if not exist .\WinRel\nul mkdir .\WinRel
cl.exe /nologo /MT /W4 /GX /YX /O2 /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c
cl.exe /nologo /MT /W4 /GX /YX /O2 /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c
cl.exe /nologo /MT /W4 /GX /YX /O2 /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c
lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib .\WinRel/misc.obj .\WinRel/sub_proc.obj .\WinRel/w32err.obj
GoTo BuildEnd
:GCCBuild
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I.. -I. -I../include -I../.. -DWINDOWS32 -c misc.c -o ../../w32_misc.o
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I.. -I. -I../include -I../.. -DWINDOWS32 -c sub_proc.c -o ../../sub_proc.o
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I.. -I. -I../include -I../.. -DWINDOWS32 -c w32err.c -o ../../w32err.o
:BuildEnd
@echo off
rem Copyright (C) 1996-2016 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
rem the terms of the GNU General Public License as published by the Free
rem Software Foundation; either version 3 of the License, or (at your option)
rem any later version.
rem
rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for.
rem more details.
rem
rem You should have received a copy of the GNU General Public License along
rem with this program. If not, see <http://www.gnu.org/licenses/>.

View file

@ -61,124 +61,26 @@ static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
static int proc_index = 0;
static int fake_exits_pending = 0;
/* Windows jobserver implementation variables */
static char jobserver_semaphore_name[MAX_PATH + 1];
static HANDLE jobserver_semaphore = NULL;
/* Open existing jobserver semaphore */
int open_jobserver_semaphore(const char* name)
{
jobserver_semaphore = OpenSemaphore(
SEMAPHORE_ALL_ACCESS, // Semaphore access setting
FALSE, // Child processes DON'T inherit
name); // Semaphore name
if (jobserver_semaphore == NULL)
return 0;
return 1;
}
/* Create new jobserver semaphore */
int create_jobserver_semaphore(int tokens)
{
sprintf(jobserver_semaphore_name, "gmake_semaphore_%d", _getpid());
jobserver_semaphore = CreateSemaphore(
NULL, // Use default security descriptor
tokens, // Initial count
tokens, // Maximum count
jobserver_semaphore_name); // Semaphore name
if (jobserver_semaphore == NULL)
return 0;
return 1;
}
/* Close jobserver semaphore */
void free_jobserver_semaphore()
{
if (jobserver_semaphore != NULL)
{
CloseHandle(jobserver_semaphore);
jobserver_semaphore = NULL;
}
}
/* Decrement semaphore count */
int acquire_jobserver_semaphore()
{
DWORD dwEvent = WaitForSingleObject(
jobserver_semaphore, // Handle to semaphore
0); // DON'T wait on semaphore
return (dwEvent == WAIT_OBJECT_0);
}
/* Increment semaphore count */
int release_jobserver_semaphore()
{
BOOL bResult = ReleaseSemaphore(
jobserver_semaphore, // handle to semaphore
1, // increase count by one
NULL); // not interested in previous count
return (bResult);
}
int has_jobserver_semaphore()
{
return (jobserver_semaphore != NULL);
}
char* get_jobserver_semaphore_name()
{
return (jobserver_semaphore_name);
}
/* Wait for either the jobserver semaphore to become signalled or one of our
* child processes to terminate.
/*
* Fill a HANDLE list with handles to wait for.
*/
int wait_for_semaphore_or_child_process()
DWORD
process_set_handles(HANDLE *handles)
{
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
DWORD dwHandleCount = 1;
DWORD dwEvent;
DWORD count = 0;
int i;
/* Add jobserver semaphore to first slot. */
handles[0] = jobserver_semaphore;
/* Build array of handles to wait for */
for (i = 0; i < proc_index; i++)
{
for (i = 0; i < proc_index; i++) {
/* Don't wait on child processes that have already finished */
if (fake_exits_pending && proc_array[i]->exit_code)
continue;
handles[dwHandleCount++] = (HANDLE) proc_array[i]->pid;
handles[count++] = (HANDLE) proc_array[i]->pid;
}
dwEvent = WaitForMultipleObjects(
dwHandleCount, // number of objects in array
handles, // array of objects
FALSE, // wait for any object
INFINITE); // wait until object is signalled
switch(dwEvent)
{
case WAIT_FAILED:
return -1;
case WAIT_OBJECT_0:
/* Indicate that the semaphore was signalled */
return 1;
default:
/* Assume that one or more of the child processes terminated. */
return 0;
}
return count;
}
/*
@ -756,7 +658,7 @@ process_begin(
pproc->lerrno = E_NO_MEM;
free( command_line );
if ((pproc->last_err == ERROR_INVALID_PARAMETER
|| pproc->last_err == ERROR_MORE_DATA)
|| pproc->last_err == ERROR_MORE_DATA)
&& envsize_needed > 32*1024) {
fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n",
envsize_needed);

196
w32/w32os.c Normal file
View file

@ -0,0 +1,196 @@
/* Windows32-based operating system interface for GNU Make.
Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. */
#include "makeint.h"
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <process.h>
#include <io.h>
#include "pathstuff.h"
#include "sub_proc.h"
#include "w32err.h"
#include "os.h"
#include "debug.h"
/* This section provides OS-specific functions to support the jobserver. */
static char jobserver_semaphore_name[MAX_PATH + 1];
static HANDLE jobserver_semaphore = NULL;
void
jobserver_setup (int slots)
{
/* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects
* and one of them is the job-server semaphore object. Limit the
* number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */
if (slots >= MAXIMUM_WAIT_OBJECTS)
{
slots = MAXIMUM_WAIT_OBJECTS - 1;
DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), slots));
}
sprintf (jobserver_semaphore_name, "gmake_semaphore_%d", _getpid ());
jobserver_semaphore = CreateSemaphore (
NULL, /* Use default security descriptor */
slots, /* Initial count */
slots, /* Maximum count */
jobserver_semaphore_name); /* Semaphore name */
if (jobserver_semaphore == NULL)
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
ONS (fatal, NILF,
_("creating jobserver semaphore: (Error %ld: %s)"), err, estr);
}
}
void
jobserver_parse_arg (const char* arg)
{
jobserver_semaphore = OpenSemaphore (
SEMAPHORE_ALL_ACCESS, /* Semaphore access setting */
FALSE, /* Child processes DON'T inherit */
arg); /* Semaphore name */
if (jobserver_semaphore == NULL)
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
fatal (NILF, strlen (arg) + INTSTR_LENGTH + strlen (estr),
_("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
arg, err, estr);
}
DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), arg));
}
char *
jobserver_get_arg ()
{
char *fds = xmalloc (MAX_PATH + 1);
strcpy (fds, jobserver_semaphore_name);
return fds;
}
unsigned int
jobserver_enabled ()
{
return jobserver_semaphore != NULL;
}
/* Close jobserver semaphore */
void
jobserver_clear ()
{
if (jobserver_semaphore != NULL)
{
CloseHandle (jobserver_semaphore);
jobserver_semaphore = NULL;
}
}
void
jobserver_release (int is_fatal)
{
if (! ReleaseSemaphore (
jobserver_semaphore, /* handle to semaphore */
1, /* increase count by one */
NULL)) /* not interested in previous count */
{
if (is_fatal)
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
ONS (fatal, NILF,
_("release jobserver semaphore: (Error %ld: %s)"), err, estr);
}
perror_with_name ("release_jobserver_semaphore", "");
}
}
unsigned int
jobserver_acquire_all ()
{
unsigned int tokens = 0;
while (1)
{
DWORD dwEvent = WaitForSingleObject (
jobserver_semaphore, /* Handle to semaphore */
0); /* DON'T wait on semaphore */
if (dwEvent != WAIT_OBJECT_0)
return tokens;
++tokens;
}
}
void
jobserver_signal ()
{
}
void jobserver_pre_child ()
{
}
void jobserver_post_child ()
{
}
void
jobserver_pre_acquire ()
{
}
/* Returns 1 if we got a token, or 0 if a child has completed.
The Windows implementation doesn't support load detection. */
int
jobserver_acquire (int timeout)
{
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
DWORD dwHandleCount;
DWORD dwEvent;
/* Add jobserver semaphore to first slot. */
handles[0] = jobserver_semaphore;
/* Build array of handles to wait for. */
dwHandleCount = 1 + process_set_handles (&handles[1]);
dwEvent = WaitForMultipleObjects (
dwHandleCount, /* number of objects in array */
handles, /* array of objects */
FALSE, /* wait for any object */
INFINITE); /* wait until object is signalled */
if (dwEvent == WAIT_FAILED)
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
ONS (fatal, NILF,
_("semaphore or child process wait: (Error %ld: %s)"),
err, estr);
}
/* WAIT_OBJECT_0 indicates that the semaphore was signalled. */
return dwEvent == WAIT_OBJECT_0;
}