mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-11-28 09:25:17 +00:00
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:
parent
4f8be4bb28
commit
fb7a7adc8a
19 changed files with 912 additions and 799 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -34,6 +34,12 @@ make
|
||||||
*.pdb
|
*.pdb
|
||||||
*.sbr
|
*.sbr
|
||||||
|
|
||||||
|
# Windows build artifacts
|
||||||
|
/WinDebug/
|
||||||
|
/WinRel/
|
||||||
|
/GccDebug/
|
||||||
|
/GccRel/
|
||||||
|
|
||||||
# Distribution artifacts
|
# Distribution artifacts
|
||||||
.dep_segment
|
.dep_segment
|
||||||
.check-git-HEAD
|
.check-git-HEAD
|
||||||
|
|
|
@ -41,14 +41,14 @@ endif
|
||||||
|
|
||||||
make_SOURCES = ar.c arscan.c commands.c default.c dir.c expand.c file.c \
|
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 \
|
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 \
|
loadapi.c main.c misc.c output.c posixos.c read.c remake.c \
|
||||||
signame.c strcache.c variable.c version.c vpath.c hash.c \
|
rule.c signame.c strcache.c variable.c version.c vpath.c \
|
||||||
$(remote)
|
hash.c $(remote)
|
||||||
|
|
||||||
EXTRA_make_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
|
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 \
|
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@ \
|
make_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ \
|
||||||
$(GUILE_LIBS)
|
$(GUILE_LIBS)
|
||||||
|
|
|
@ -107,6 +107,7 @@ OBJS = \
|
||||||
$(OUTDIR)/dirent.obj \
|
$(OUTDIR)/dirent.obj \
|
||||||
$(OUTDIR)/pathstuff.obj \
|
$(OUTDIR)/pathstuff.obj \
|
||||||
$(OUTDIR)/posixfcn.obj \
|
$(OUTDIR)/posixfcn.obj \
|
||||||
|
$(OUTDIR)/w32os.obj \
|
||||||
$(guile)
|
$(guile)
|
||||||
|
|
||||||
$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)
|
$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)
|
||||||
|
@ -127,3 +128,5 @@ $(OUTDIR)/posixfcn.obj : w32/compat/posixfcn.c
|
||||||
$(CC) $(CFLAGS) /c $?
|
$(CC) $(CFLAGS) /c $?
|
||||||
$(OUTDIR)/pathstuff.obj : w32/pathstuff.c
|
$(OUTDIR)/pathstuff.obj : w32/pathstuff.c
|
||||||
$(CC) $(CFLAGS) /c $?
|
$(CC) $(CFLAGS) /c $?
|
||||||
|
$(OUTDIR)/w32os.obj : w32/w32os.c
|
||||||
|
$(CC) $(CFLAGS) /c $?
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
This version of GNU make has been tested on
|
This version of GNU make has been tested on:
|
||||||
Microsoft Windows 2000/XP/2003/Vista/7/2008.
|
Microsoft Windows 2000/XP/2003/Vista/7/8/10
|
||||||
It has also been used on Windows 95/98/NT, and on OS/2.
|
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
|
It also builds with MSVC 2.x, 4.x, 5.x, 6.x, 2003, and 14 (2015) as
|
||||||
with .NET 7.x and .NET 2003.
|
well as with .NET 7.x and .NET 2003.
|
||||||
|
|
||||||
As of version 4.0, a build with Guile is supported (tested with Guile
|
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
|
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
|
them. A precompiled 32-bit Windows build of Guile is available from
|
||||||
the ezwinports site mentioned above.
|
the ezwinports site mentioned above.
|
||||||
|
|
||||||
The Windows 32-bit port of GNU make is maintained jointly by various
|
The Windows port of GNU make is maintained jointly by various people.
|
||||||
people. It was originally made by Rob Tulloh.
|
It was originally made by Rob Tulloh.
|
||||||
|
It is currently maintained by Eli Zaretskii.
|
||||||
|
|
||||||
|
|
||||||
Do this first, regardless of the build method you choose:
|
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
|
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
|
The batch file will probe for Guile installation, and will build
|
||||||
gnumake.exe with Guile if it finds it. If you have Guile
|
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
|
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 ...
|
... OR ...
|
||||||
|
|
||||||
|
|
484
build_w32.bat
Normal file → Executable file
484
build_w32.bat
Normal file → Executable file
|
@ -15,283 +15,217 @@ rem
|
||||||
rem You should have received a copy of the GNU General Public License along
|
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/>.
|
rem with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
if "%1" == "-h" GoTo Usage
|
call :Reset
|
||||||
if "%1" == "--help" GoTo Usage
|
|
||||||
if not exist config.h.W32.template GoTo NotSCM
|
if "%1" == "-h" goto Usage
|
||||||
sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > config.h.W32.sed
|
if "%1" == "--help" goto Usage
|
||||||
echo s,%%PACKAGE%%,make,g >> config.h.W32.sed
|
|
||||||
sed -f config.h.W32.sed config.h.W32.template > config.h.W32
|
set MAKE=gnumake
|
||||||
echo static const char *const GUILE_module_defn = ^" \> gmk-default.h
|
set GUILE=Y
|
||||||
sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\/" gmk-default.scm >> gmk-default.h
|
set COMPILER=msvc
|
||||||
echo ^";>> gmk-default.h
|
|
||||||
:NotSCM
|
|
||||||
copy config.h.W32 config.h
|
|
||||||
|
|
||||||
rem Guile configuration
|
|
||||||
set GUILECFLAGS=
|
|
||||||
set GUILELIBS=
|
|
||||||
set NOGUILE=
|
|
||||||
set OPT=-O2
|
|
||||||
set COMPILER=
|
|
||||||
set PKGMSC=
|
|
||||||
:ParseSW
|
:ParseSW
|
||||||
if "%1" == "--debug" GoTo SetOpt
|
if "%1" == "--debug" goto SetDebug
|
||||||
if "%1" == "--without-guile" GoTo NoGuile
|
if "%1" == "--without-guile" goto NoGuile
|
||||||
if "%1" == "gcc" GoTo SetCC
|
if "%1" == "gcc" goto SetCC
|
||||||
if "%1" == "" GoTo ChkGuile
|
if "%1" == "" goto DoneSW
|
||||||
:SetOpt
|
|
||||||
set OPT=-O0
|
:SetDebug
|
||||||
|
set DEBUG=Y
|
||||||
shift
|
shift
|
||||||
GoTo ParseSW
|
goto ParseSW
|
||||||
|
|
||||||
:NoGuile
|
:NoGuile
|
||||||
set NOGUILE=Y
|
set GUILE=N
|
||||||
echo "Building without Guile"
|
echo Building without Guile
|
||||||
shift
|
shift
|
||||||
GoTo ParseSW
|
goto ParseSW
|
||||||
|
|
||||||
:SetCC
|
:SetCC
|
||||||
set COMPILER=gcc
|
set COMPILER=gcc
|
||||||
echo "Building with GCC"
|
echo Building with GCC
|
||||||
shift
|
shift
|
||||||
GoTo ParseSW
|
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 ..\..
|
|
||||||
|
|
||||||
if exist link.dbg del link.dbg
|
rem Build with Guile is supported only on NT and later versions
|
||||||
if exist link.rel del link.rel
|
:DoneSW
|
||||||
echo.
|
echo.
|
||||||
echo "Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8"
|
echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8
|
||||||
if "%COMPILER%" == "gcc" GoTo GCCBuild
|
if "%DEBUG%" == "Y" echo Building without compiler optimizations
|
||||||
set make=gnumake
|
|
||||||
|
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
|
echo on
|
||||||
if not exist .\WinDebug\nul mkdir .\WinDebug
|
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
|
||||||
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
|
|
||||||
@echo off
|
@echo off
|
||||||
Rem The version NN of libgnumake-NN.dll.a should be bumped whenever
|
echo %OUTDIR%\%1.obj >>%OUTDIR%\link.sc
|
||||||
Rem the API changes in binary-incompatible manner.
|
goto :EOF
|
||||||
@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
|
:GccCompile
|
||||||
@GoTo BuildEnd
|
:: 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
|
:Usage
|
||||||
echo Usage: %0 [options] [gcc]
|
echo Usage: %0 [options] [gcc]
|
||||||
echo Options:
|
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. (MSVC build always makes both debug and release)
|
||||||
echo. --without-guile Do not compile Guile support even if found
|
echo. --without-guile Do not compile Guile support even if found
|
||||||
echo. --help Display these instructions and exit
|
echo. --help Display these instructions and exit
|
||||||
:BuildEnd
|
goto :EOF
|
||||||
@echo off
|
|
||||||
set GUILELIBS=
|
:Reset
|
||||||
set GUILECFLAGS=
|
|
||||||
set PKGMSC=
|
|
||||||
set OPT=
|
|
||||||
set COMPILER=
|
set COMPILER=
|
||||||
|
set DEBUG=
|
||||||
|
set GUILE=
|
||||||
|
set GUILECFLAGS=
|
||||||
|
set GUILELIBS=
|
||||||
|
set LINKOPTS=
|
||||||
|
set MAKE=
|
||||||
set NOGUILE=
|
set NOGUILE=
|
||||||
echo on
|
set OPTS=
|
||||||
|
set OUTDIR=
|
||||||
|
set PKGMSC=
|
||||||
|
goto :EOF
|
||||||
|
|
196
job.c
196
job.c
|
@ -23,6 +23,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
#include "filedef.h"
|
#include "filedef.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
|
#include "os.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -541,11 +542,7 @@ child_handler (int sig UNUSED)
|
||||||
{
|
{
|
||||||
++dead_children;
|
++dead_children;
|
||||||
|
|
||||||
if (job_rfd >= 0)
|
jobserver_signal ();
|
||||||
{
|
|
||||||
close (job_rfd);
|
|
||||||
job_rfd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __EMX__
|
#ifdef __EMX__
|
||||||
/* The signal handler must called only once! */
|
/* 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
|
/* If we're using the jobserver and this child is not the only outstanding
|
||||||
job, put a token back into the pipe for it. */
|
job, put a token back into the pipe for it. */
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
if (jobserver_enabled () && jobserver_tokens > 1)
|
||||||
if (has_jobserver_semaphore () && jobserver_tokens > 1)
|
|
||||||
{
|
{
|
||||||
if (! release_jobserver_semaphore ())
|
jobserver_release (1);
|
||||||
{
|
|
||||||
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"));
|
|
||||||
|
|
||||||
DB (DB_JOBS, (_("Released token for child %p (%s).\n"),
|
DB (DB_JOBS, (_("Released token for child %p (%s).\n"),
|
||||||
child, child->file->name));
|
child, child->file->name));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
--jobserver_tokens;
|
--jobserver_tokens;
|
||||||
|
|
||||||
|
@ -1092,60 +1066,6 @@ unblock_sigs (void)
|
||||||
}
|
}
|
||||||
#endif
|
#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.
|
/* Start a job to run the commands specified in CHILD.
|
||||||
CHILD is updated to reflect the commands and ID of the child process.
|
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__
|
# ifdef __EMX__
|
||||||
/* If we aren't running a recursive command and we have a jobserver
|
/* If we aren't running a recursive command and we have a jobserver
|
||||||
pipe, close it before exec'ing. */
|
pipe, close it before exec'ing. */
|
||||||
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
|
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
|
||||||
{
|
jobserver_pre_child ();
|
||||||
CLOSE_ON_EXEC (job_fds[0]);
|
|
||||||
CLOSE_ON_EXEC (job_fds[1]);
|
|
||||||
}
|
|
||||||
if (job_rfd >= 0)
|
|
||||||
CLOSE_ON_EXEC (job_rfd);
|
|
||||||
|
|
||||||
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
|
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
|
||||||
child->pid = child_execute_job (child->good_stdin ? FD_STDIN : bad_stdin,
|
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 */
|
/* undo CLOSE_ON_EXEC() after the child process has been started */
|
||||||
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
|
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
|
||||||
{
|
jobserver_post_child ();
|
||||||
fcntl (job_fds[0], F_SETFD, 0);
|
|
||||||
fcntl (job_fds[1], F_SETFD, 0);
|
|
||||||
}
|
|
||||||
if (job_rfd >= 0)
|
|
||||||
fcntl (job_rfd, F_SETFD, 0);
|
|
||||||
|
|
||||||
#else /* !__EMX__ */
|
#else /* !__EMX__ */
|
||||||
|
|
||||||
|
@ -1554,15 +1464,10 @@ start_job_command (struct child *child)
|
||||||
/* We are the child side. */
|
/* We are the child side. */
|
||||||
unblock_sigs ();
|
unblock_sigs ();
|
||||||
|
|
||||||
/* If we aren't running a recursive command and we have a jobserver
|
/* If we AREN'T running a recursive command and we have a jobserver,
|
||||||
pipe, close it before exec'ing. */
|
clear it before exec'ing. */
|
||||||
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
|
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
|
||||||
{
|
jobserver_clear ();
|
||||||
close (job_fds[0]);
|
|
||||||
close (job_fds[1]);
|
|
||||||
}
|
|
||||||
if (job_rfd >= 0)
|
|
||||||
close (job_rfd);
|
|
||||||
|
|
||||||
#ifdef SET_STACK_SIZE
|
#ifdef SET_STACK_SIZE
|
||||||
/* Reset limits, if necessary. */
|
/* 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;
|
just once). Also more thought needs to go into the entire algorithm;
|
||||||
this is where the old parallel job code waits, so... */
|
this is where the old parallel job code waits, so... */
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
else if (jobserver_enabled ())
|
||||||
else if (has_jobserver_semaphore ())
|
|
||||||
#else
|
|
||||||
else if (job_fds[0] >= 0)
|
|
||||||
#endif
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int got_token;
|
int got_token;
|
||||||
#ifndef WINDOWS32
|
|
||||||
char token;
|
|
||||||
int saved_errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DB (DB_JOBS, ("Need a job token; we %shave children\n",
|
DB (DB_JOBS, ("Need a job token; we %shave children\n",
|
||||||
children ? "" : "don't "));
|
children ? "" : "don't "));
|
||||||
|
@ -1972,36 +1869,8 @@ new_job (struct file *file)
|
||||||
if (!jobserver_tokens)
|
if (!jobserver_tokens)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
/* Prepare for jobserver token acquisition. */
|
||||||
/* Read a token. As long as there's no token available we'll block.
|
jobserver_pre_acquire ();
|
||||||
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
|
|
||||||
|
|
||||||
/* Reap anything that's currently waiting. */
|
/* Reap anything that's currently waiting. */
|
||||||
reap_children (0, 0);
|
reap_children (0, 0);
|
||||||
|
@ -2010,8 +1879,7 @@ new_job (struct file *file)
|
||||||
can run now (i.e., waiting for load). */
|
can run now (i.e., waiting for load). */
|
||||||
start_waiting_jobs ();
|
start_waiting_jobs ();
|
||||||
|
|
||||||
/* If our "free" slot has become available, use it; we don't need an
|
/* If our "free" slot is available, use it; we don't need a token. */
|
||||||
actual token. */
|
|
||||||
if (!jobserver_tokens)
|
if (!jobserver_tokens)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2020,26 +1888,8 @@ new_job (struct file *file)
|
||||||
if (!children)
|
if (!children)
|
||||||
O (fatal, NILF, "INTERNAL: no children as we go to sleep on read\n");
|
O (fatal, NILF, "INTERNAL: no children as we go to sleep on read\n");
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
/* Get a token. */
|
||||||
/* On Windows we simply wait for the jobserver semaphore to become
|
got_token = jobserver_acquire (waiting_jobs != NULL);
|
||||||
* 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
|
|
||||||
|
|
||||||
/* If we got one, we're done here. */
|
/* If we got one, we're done here. */
|
||||||
if (got_token == 1)
|
if (got_token == 1)
|
||||||
|
@ -2048,16 +1898,6 @@ new_job (struct file *file)
|
||||||
c, c->file->name));
|
c, c->file->name));
|
||||||
break;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
2
job.h
2
job.h
|
@ -115,6 +115,8 @@ struct child
|
||||||
|
|
||||||
extern struct child *children;
|
extern struct child *children;
|
||||||
|
|
||||||
|
/* A signal handler for SIGCHLD, if needed. */
|
||||||
|
RETSIGTYPE child_handler (int sig);
|
||||||
int is_bourne_compatible_shell(const char *path);
|
int is_bourne_compatible_shell(const char *path);
|
||||||
void new_job (struct file *file);
|
void new_job (struct file *file);
|
||||||
void reap_children (int block, int err);
|
void reap_children (int block, int err);
|
||||||
|
|
217
main.c
217
main.c
|
@ -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/>. */
|
this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include "makeint.h"
|
#include "makeint.h"
|
||||||
|
#include "os.h"
|
||||||
#include "filedef.h"
|
#include "filedef.h"
|
||||||
#include "dep.h"
|
#include "dep.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
|
@ -270,15 +271,12 @@ static unsigned int inf_jobs = 0;
|
||||||
|
|
||||||
/* File descriptors for the jobs pipe. */
|
/* File descriptors for the jobs pipe. */
|
||||||
|
|
||||||
char *jobserver_fds = 0;
|
char *jobserver_fds = NULL;
|
||||||
|
|
||||||
int job_fds[2] = { -1, -1 };
|
|
||||||
int job_rfd = -1;
|
|
||||||
|
|
||||||
/* Handle for the mutex used on Windows to synchronize output of our
|
/* Handle for the mutex used on Windows to synchronize output of our
|
||||||
children under -O. */
|
children under -O. */
|
||||||
|
|
||||||
char *sync_mutex = 0;
|
char *sync_mutex = NULL;
|
||||||
|
|
||||||
/* Maximum load average at which multiple jobs will be run.
|
/* Maximum load average at which multiple jobs will be run.
|
||||||
Negative values mean unlimited, while zero means limit to
|
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. */
|
/* Mask of signals that are being caught with fatal_error_signal. */
|
||||||
|
|
||||||
#ifdef POSIX
|
#ifdef POSIX
|
||||||
sigset_t fatal_signal_set;
|
sigset_t fatal_signal_set;
|
||||||
#else
|
#else
|
||||||
# ifdef HAVE_SIGSETMASK
|
# ifdef HAVE_SIGSETMASK
|
||||||
|
@ -1597,85 +1595,33 @@ main (int argc, char **argv, char **envp)
|
||||||
starting_directory = current_directory;
|
starting_directory = current_directory;
|
||||||
|
|
||||||
#ifdef MAKE_JOBSERVER
|
#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
|
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
|
FDs are valid before any other aspect of make has a chance to start
|
||||||
using them for something else. */
|
using them for something else. */
|
||||||
|
|
||||||
if (jobserver_fds)
|
if (jobserver_fds)
|
||||||
{
|
{
|
||||||
/* Make sure the jobserver option has the proper format. */
|
/* The combination of jobserver_fds and !job_slots means we're using the
|
||||||
const char *cp = jobserver_fds;
|
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
|
||||||
#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
|
|
||||||
user set -j explicitly. This is broken; in this case obey the user
|
user set -j explicitly. This is broken; in this case obey the user
|
||||||
(ignore the jobserver pipe for this make) but print a message.
|
(ignore the jobserver for this make) but print a message. If we've
|
||||||
If we've restarted, we already printed this the first time. */
|
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 (job_slots > 0)
|
||||||
{
|
{
|
||||||
if (! restarts)
|
/* If job_slots is set now then we're not using jobserver */
|
||||||
O (error, NILF,
|
jobserver_clear ();
|
||||||
_("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;
|
|
||||||
|
|
||||||
free (jobserver_fds);
|
free (jobserver_fds);
|
||||||
jobserver_fds = 0;
|
jobserver_fds = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1902,7 +1848,7 @@ main (int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
|
#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
|
/* Set up to handle children dying. This must be done before
|
||||||
reading in the makefiles so that 'shell' function calls will work.
|
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
|
functionality here and rely on the signal handler and counting
|
||||||
children.
|
children.
|
||||||
|
|
||||||
If we're using the jobs pipe we need a signal handler so that
|
If we're using the jobs pipe we need a signal handler so that SIGCHLD is
|
||||||
SIGCHLD is not ignored; we need it to interrupt the read(2) of the
|
not ignored; we need it to interrupt the read(2) of the jobserver pipe if
|
||||||
jobserver pipe in job.c if we're waiting for a token.
|
we're waiting for a token.
|
||||||
|
|
||||||
If none of these are true, we don't need a signal handler at all. */
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef MAKE_JOBSERVER
|
#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)
|
if (job_slots > 1)
|
||||||
{
|
{
|
||||||
#ifdef WINDOWS32
|
/* If we have >1 slot at this point, then we're a top-level make.
|
||||||
/* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects
|
Set up the jobserver.
|
||||||
* and one of them is the job-server semaphore object. Limit the
|
|
||||||
* number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */
|
|
||||||
|
|
||||||
if (job_slots >= MAXIMUM_WAIT_OBJECTS)
|
Every make assumes that it always has one job it can run. For the
|
||||||
{
|
|
||||||
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
|
|
||||||
submakes it's the token they were given by their parent. 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
|
top make, we just subtract one from the number the user wants. */
|
||||||
want job_slots to be 0 to indicate we're using the jobserver. */
|
|
||||||
|
|
||||||
|
jobserver_setup (job_slots - 1);
|
||||||
|
|
||||||
|
/* We're using the jobserver so set job_slots to 0. */
|
||||||
master_job_slots = job_slots;
|
master_job_slots = job_slots;
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
|
||||||
/* We're using the jobserver so set job_slots to 0. */
|
|
||||||
job_slots = 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. */
|
/* Fill in the jobserver_fds for our children. */
|
||||||
|
jobserver_fds = jobserver_get_arg ();
|
||||||
#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
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2489,10 +2392,6 @@ main (int argc, char **argv, char **envp)
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
fflush (stderr);
|
fflush (stderr);
|
||||||
|
|
||||||
/* Close the dup'd jobserver pipe if we opened one. */
|
|
||||||
if (job_rfd >= 0)
|
|
||||||
close (job_rfd);
|
|
||||||
|
|
||||||
#ifdef _AMIGA
|
#ifdef _AMIGA
|
||||||
exec_command (nargv);
|
exec_command (nargv);
|
||||||
exit (0);
|
exit (0);
|
||||||
|
@ -3444,13 +3343,7 @@ clean_jobserver (int status)
|
||||||
have written all our tokens so do that now. If tokens are left
|
have written all our tokens so do that now. If tokens are left
|
||||||
after any other error code, that's bad. */
|
after any other error code, that's bad. */
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
if (jobserver_enabled() && jobserver_tokens)
|
||||||
if (has_jobserver_semaphore () && jobserver_tokens)
|
|
||||||
#else
|
|
||||||
char token = '+';
|
|
||||||
|
|
||||||
if (job_fds[0] != -1 && jobserver_tokens)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (status != 2)
|
if (status != 2)
|
||||||
ON (error, NILF,
|
ON (error, NILF,
|
||||||
|
@ -3459,18 +3352,7 @@ clean_jobserver (int status)
|
||||||
else
|
else
|
||||||
/* Don't write back the "free" token */
|
/* Don't write back the "free" token */
|
||||||
while (--jobserver_tokens)
|
while (--jobserver_tokens)
|
||||||
{
|
jobserver_release (0);
|
||||||
#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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3479,42 +3361,21 @@ clean_jobserver (int status)
|
||||||
if (master_job_slots)
|
if (master_job_slots)
|
||||||
{
|
{
|
||||||
/* We didn't write one for ourself, so start at 1. */
|
/* We didn't write one for ourself, so start at 1. */
|
||||||
unsigned int tcnt = 1;
|
unsigned int tokens = 1 + jobserver_acquire_all ();
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
if (tokens != master_job_slots)
|
||||||
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)
|
|
||||||
ONN (error, NILF,
|
ONN (error, NILF,
|
||||||
"INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
|
"INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
|
||||||
tcnt, master_job_slots);
|
tokens, master_job_slots);
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
jobserver_clear ();
|
||||||
free_jobserver_semaphore ();
|
|
||||||
#else
|
|
||||||
close (job_fds[0]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Clean out jobserver_fds so we don't pass this information to any
|
/* 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
|
sub-makes. Also reset job_slots since it will be put on the command
|
||||||
line, not in MAKEFLAGS. */
|
line, not in MAKEFLAGS. */
|
||||||
job_slots = default_job_slots;
|
job_slots = default_job_slots;
|
||||||
free (jobserver_fds);
|
free (jobserver_fds);
|
||||||
jobserver_fds = 0;
|
jobserver_fds = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ changelog-check:
|
||||||
po-check:
|
po-check:
|
||||||
if test -f po/POTFILES.in; then \
|
if test -f po/POTFILES.in; then \
|
||||||
grep '^[^#]' po/POTFILES.in | sort > $@-1; \
|
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; \
|
diff -u $@-1 $@-2 || exit 1; \
|
||||||
rm -f $@-1 $@-2; \
|
rm -f $@-1 $@-2; \
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -234,6 +234,9 @@
|
||||||
<File
|
<File
|
||||||
RelativePath=".\w32\pathstuff.c">
|
RelativePath=".\w32\pathstuff.c">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\w32\w32os.c">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\w32\subproc\sub_proc.c">
|
RelativePath=".\w32\subproc\sub_proc.c">
|
||||||
</File>
|
</File>
|
||||||
|
|
|
@ -623,8 +623,6 @@ extern int batch_mode_shell;
|
||||||
extern char cmd_prefix;
|
extern char cmd_prefix;
|
||||||
|
|
||||||
extern unsigned int job_slots;
|
extern unsigned int job_slots;
|
||||||
extern int job_fds[2];
|
|
||||||
extern int job_rfd;
|
|
||||||
#ifndef NO_FLOAT
|
#ifndef NO_FLOAT
|
||||||
extern double max_load_average;
|
extern double max_load_average;
|
||||||
#else
|
#else
|
||||||
|
|
77
os.h
Normal file
77
os.h
Normal 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
|
|
@ -32,6 +32,7 @@ load.c
|
||||||
main.c
|
main.c
|
||||||
misc.c
|
misc.c
|
||||||
output.c
|
output.c
|
||||||
|
posixos.c
|
||||||
read.c
|
read.c
|
||||||
remake.c
|
remake.c
|
||||||
remote-cstms.c
|
remote-cstms.c
|
||||||
|
@ -43,3 +44,4 @@ variable.h
|
||||||
vmsfunctions.c
|
vmsfunctions.c
|
||||||
vmsjobs.c
|
vmsjobs.c
|
||||||
vpath.c
|
vpath.c
|
||||||
|
w32/w32os.c
|
||||||
|
|
320
posixos.c
Normal file
320
posixos.c
Normal 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 */
|
|
@ -118,7 +118,7 @@ closedir (DIR *dir)
|
||||||
struct FAB *dfab = &dir->fab;
|
struct FAB *dfab = &dir->fab;
|
||||||
struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
|
struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
|
||||||
if (dnam != NULL)
|
if (dnam != NULL)
|
||||||
free (dnam->nam$l_esa);
|
free (dnam->nam$l_esa);
|
||||||
free (dnam);
|
free (dnam);
|
||||||
free (dir);
|
free (dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, (VOID_DECL));
|
||||||
EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,
|
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,
|
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,
|
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(long process_file_io, (HANDLE proc));
|
||||||
EXTERN_DECL(void process_cleanup, (HANDLE proc));
|
EXTERN_DECL(void process_cleanup, (HANDLE proc));
|
||||||
EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus));
|
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));
|
int outfd, int errfd));
|
||||||
EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
|
EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
|
||||||
EXTERN_DECL(int process_used_slots, (VOID_DECL));
|
EXTERN_DECL(int process_used_slots, (VOID_DECL));
|
||||||
|
EXTERN_DECL(DWORD process_set_handles, (HANDLE *handles));
|
||||||
|
|
||||||
/* support routines */
|
/* support routines */
|
||||||
EXTERN_DECL(long process_errno, (HANDLE proc));
|
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_pipes, (HANDLE proc, int pipes[3]));
|
||||||
EXTERN_DECL(void process_noinherit, (int fildes));
|
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
|
#endif
|
||||||
|
|
|
@ -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/>.
|
|
|
@ -61,124 +61,26 @@ static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
|
||||||
static int proc_index = 0;
|
static int proc_index = 0;
|
||||||
static int fake_exits_pending = 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)
|
* Fill a HANDLE list with handles to wait for.
|
||||||
{
|
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
int wait_for_semaphore_or_child_process()
|
DWORD
|
||||||
|
process_set_handles(HANDLE *handles)
|
||||||
{
|
{
|
||||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
DWORD count = 0;
|
||||||
DWORD dwHandleCount = 1;
|
|
||||||
DWORD dwEvent;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Add jobserver semaphore to first slot. */
|
|
||||||
handles[0] = jobserver_semaphore;
|
|
||||||
|
|
||||||
/* Build array of handles to wait for */
|
/* 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 */
|
/* Don't wait on child processes that have already finished */
|
||||||
if (fake_exits_pending && proc_array[i]->exit_code)
|
if (fake_exits_pending && proc_array[i]->exit_code)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
handles[dwHandleCount++] = (HANDLE) proc_array[i]->pid;
|
handles[count++] = (HANDLE) proc_array[i]->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwEvent = WaitForMultipleObjects(
|
return count;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -756,7 +658,7 @@ process_begin(
|
||||||
pproc->lerrno = E_NO_MEM;
|
pproc->lerrno = E_NO_MEM;
|
||||||
free( command_line );
|
free( command_line );
|
||||||
if ((pproc->last_err == ERROR_INVALID_PARAMETER
|
if ((pproc->last_err == ERROR_INVALID_PARAMETER
|
||||||
|| pproc->last_err == ERROR_MORE_DATA)
|
|| pproc->last_err == ERROR_MORE_DATA)
|
||||||
&& envsize_needed > 32*1024) {
|
&& envsize_needed > 32*1024) {
|
||||||
fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n",
|
fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n",
|
||||||
envsize_needed);
|
envsize_needed);
|
||||||
|
|
196
w32/w32os.c
Normal file
196
w32/w32os.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue