mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-11-28 01:06:48 +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
|
||||
*.sbr
|
||||
|
||||
# Windows build artifacts
|
||||
/WinDebug/
|
||||
/WinRel/
|
||||
/GccDebug/
|
||||
/GccRel/
|
||||
|
||||
# Distribution artifacts
|
||||
.dep_segment
|
||||
.check-git-HEAD
|
||||
|
|
|
@ -41,14 +41,14 @@ endif
|
|||
|
||||
make_SOURCES = ar.c arscan.c commands.c default.c dir.c expand.c file.c \
|
||||
function.c getopt.c getopt1.c guile.c implicit.c job.c load.c \
|
||||
loadapi.c main.c misc.c output.c read.c remake.c rule.c \
|
||||
signame.c strcache.c variable.c version.c vpath.c hash.c \
|
||||
$(remote)
|
||||
loadapi.c main.c misc.c output.c posixos.c read.c remake.c \
|
||||
rule.c signame.c strcache.c variable.c version.c vpath.c \
|
||||
hash.c $(remote)
|
||||
|
||||
EXTRA_make_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
|
||||
|
||||
noinst_HEADERS = commands.h dep.h filedef.h job.h makeint.h rule.h variable.h \
|
||||
debug.h getopt.h gettext.h hash.h output.h
|
||||
debug.h getopt.h gettext.h hash.h output.h os.h
|
||||
|
||||
make_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ \
|
||||
$(GUILE_LIBS)
|
||||
|
|
|
@ -107,6 +107,7 @@ OBJS = \
|
|||
$(OUTDIR)/dirent.obj \
|
||||
$(OUTDIR)/pathstuff.obj \
|
||||
$(OUTDIR)/posixfcn.obj \
|
||||
$(OUTDIR)/w32os.obj \
|
||||
$(guile)
|
||||
|
||||
$(OUTDIR)/make.exe: $(OUTDIR) $(OBJS)
|
||||
|
@ -127,3 +128,5 @@ $(OUTDIR)/posixfcn.obj : w32/compat/posixfcn.c
|
|||
$(CC) $(CFLAGS) /c $?
|
||||
$(OUTDIR)/pathstuff.obj : w32/pathstuff.c
|
||||
$(CC) $(CFLAGS) /c $?
|
||||
$(OUTDIR)/w32os.obj : w32/w32os.c
|
||||
$(CC) $(CFLAGS) /c $?
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
This version of GNU make has been tested on
|
||||
Microsoft Windows 2000/XP/2003/Vista/7/2008.
|
||||
This version of GNU make has been tested on:
|
||||
Microsoft Windows 2000/XP/2003/Vista/7/8/10
|
||||
It has also been used on Windows 95/98/NT, and on OS/2.
|
||||
|
||||
It builds with the MinGW port of GCC (tested with GCC 3.4.2 and 4.8.1).
|
||||
It builds with the MinGW port of GCC (tested with GCC 3.4.2, 4.8.1,
|
||||
and 4.9.3).
|
||||
|
||||
It also builds with MSVC 2.x, 4.x, 5.x, 6.x, and 2003 as well as
|
||||
with .NET 7.x and .NET 2003.
|
||||
It also builds with MSVC 2.x, 4.x, 5.x, 6.x, 2003, and 14 (2015) as
|
||||
well as with .NET 7.x and .NET 2003.
|
||||
|
||||
As of version 4.0, a build with Guile is supported (tested with Guile
|
||||
2.0.3). To build with Guile, you will need, in addition to Guile
|
||||
|
@ -25,8 +26,9 @@ also provide you with these dependencies or a URL where to download
|
|||
them. A precompiled 32-bit Windows build of Guile is available from
|
||||
the ezwinports site mentioned above.
|
||||
|
||||
The Windows 32-bit port of GNU make is maintained jointly by various
|
||||
people. It was originally made by Rob Tulloh.
|
||||
The Windows port of GNU make is maintained jointly by various people.
|
||||
It was originally made by Rob Tulloh.
|
||||
It is currently maintained by Eli Zaretskii.
|
||||
|
||||
|
||||
Do this first, regardless of the build method you choose:
|
||||
|
@ -56,7 +58,9 @@ Building with (MinGW-)GCC using build_w32.bat
|
|||
|
||||
build_w32.bat gcc
|
||||
|
||||
This produces gnumake.exe in the current directory.
|
||||
This produces gnumake.exe in the GccRel directory.
|
||||
If you want a version of GNU make built with debugging enabled,
|
||||
add the --debug option.
|
||||
|
||||
The batch file will probe for Guile installation, and will build
|
||||
gnumake.exe with Guile if it finds it. If you have Guile
|
||||
|
@ -76,7 +80,9 @@ Building with (MSVC++-)cl using build_w32.bat or NMakefile
|
|||
|
||||
build_w32.bat
|
||||
|
||||
(this produces WinDebug/gnumake.exe and WinRel/gnumake.exe)
|
||||
This produces gnumake.exe in the WinRel directory.
|
||||
If you want a version of GNU make built with debugging enabled,
|
||||
add the --debug option.
|
||||
|
||||
... OR ...
|
||||
|
||||
|
|
484
build_w32.bat
Normal file → Executable file
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 with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if "%1" == "-h" GoTo Usage
|
||||
if "%1" == "--help" GoTo Usage
|
||||
if not exist config.h.W32.template GoTo NotSCM
|
||||
sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > config.h.W32.sed
|
||||
echo s,%%PACKAGE%%,make,g >> config.h.W32.sed
|
||||
sed -f config.h.W32.sed config.h.W32.template > config.h.W32
|
||||
echo static const char *const GUILE_module_defn = ^" \> gmk-default.h
|
||||
sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\/" gmk-default.scm >> gmk-default.h
|
||||
echo ^";>> gmk-default.h
|
||||
:NotSCM
|
||||
copy config.h.W32 config.h
|
||||
call :Reset
|
||||
|
||||
if "%1" == "-h" goto Usage
|
||||
if "%1" == "--help" goto Usage
|
||||
|
||||
set MAKE=gnumake
|
||||
set GUILE=Y
|
||||
set COMPILER=msvc
|
||||
|
||||
rem Guile configuration
|
||||
set GUILECFLAGS=
|
||||
set GUILELIBS=
|
||||
set NOGUILE=
|
||||
set OPT=-O2
|
||||
set COMPILER=
|
||||
set PKGMSC=
|
||||
:ParseSW
|
||||
if "%1" == "--debug" GoTo SetOpt
|
||||
if "%1" == "--without-guile" GoTo NoGuile
|
||||
if "%1" == "gcc" GoTo SetCC
|
||||
if "%1" == "" GoTo ChkGuile
|
||||
:SetOpt
|
||||
set OPT=-O0
|
||||
if "%1" == "--debug" goto SetDebug
|
||||
if "%1" == "--without-guile" goto NoGuile
|
||||
if "%1" == "gcc" goto SetCC
|
||||
if "%1" == "" goto DoneSW
|
||||
|
||||
:SetDebug
|
||||
set DEBUG=Y
|
||||
shift
|
||||
GoTo ParseSW
|
||||
goto ParseSW
|
||||
|
||||
:NoGuile
|
||||
set NOGUILE=Y
|
||||
echo "Building without Guile"
|
||||
set GUILE=N
|
||||
echo Building without Guile
|
||||
shift
|
||||
GoTo ParseSW
|
||||
goto ParseSW
|
||||
|
||||
:SetCC
|
||||
set COMPILER=gcc
|
||||
echo "Building with GCC"
|
||||
echo Building with GCC
|
||||
shift
|
||||
GoTo ParseSW
|
||||
rem Build with Guile is supported only on NT and later versions
|
||||
:ChkGuile
|
||||
if "%NOGUILE%" == "Y" GoTo GuileDone
|
||||
if not "%OS%" == "Windows_NT" GoTo NoGuile
|
||||
pkg-config --help > guile.tmp 2> NUL
|
||||
if ERRORLEVEL 1 GoTo NoPkgCfg
|
||||
echo "Checking for Guile 2.0"
|
||||
if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax
|
||||
pkg-config --cflags --short-errors "guile-2.0" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp
|
||||
pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp
|
||||
if not "%GUILECFLAGS%" == "" GoTo GuileDone
|
||||
echo "Checking for Guile 1.8"
|
||||
pkg-config --cflags --short-errors "guile-1.8" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp
|
||||
pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp
|
||||
if not "%GUILECFLAGS%" == "" GoTo GuileDone
|
||||
echo "No Guile found, building without Guile"
|
||||
GoTo GuileDone
|
||||
:NoPkgCfg
|
||||
echo "pkg-config not found, building without Guile"
|
||||
:GuileDone
|
||||
if not "%GUILECFLAGS%" == "" echo "Guile found, building with Guile"
|
||||
if not "%GUILECFLAGS%" == "" set GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE
|
||||
if "%COMPILER%" == "gcc" if "%OPT%" == "-O0" echo "Building without compiler optimizations"
|
||||
cd w32\subproc
|
||||
echo.
|
||||
echo "Creating the subproc library"
|
||||
%ComSpec% /c build.bat
|
||||
cd ..\..
|
||||
goto ParseSW
|
||||
|
||||
if exist link.dbg del link.dbg
|
||||
if exist link.rel del link.rel
|
||||
rem Build with Guile is supported only on NT and later versions
|
||||
:DoneSW
|
||||
echo.
|
||||
echo "Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8"
|
||||
if "%COMPILER%" == "gcc" GoTo GCCBuild
|
||||
set make=gnumake
|
||||
echo Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8
|
||||
if "%DEBUG%" == "Y" echo Building without compiler optimizations
|
||||
|
||||
if "%COMPILER%" == "gcc" goto GccBuild
|
||||
|
||||
set OUTDIR=.\WinRel
|
||||
set "OPTS=/O2 /D NDEBUG"
|
||||
set LINKOPTS=
|
||||
if "%DEBUG%" == "Y" set OUTDIR=.\WinDebug
|
||||
if "%DEBUG%" == "Y" set "OPTS=/Zi /Od /D _DEBUG"
|
||||
if "%DEBUG%" == "Y" set LINKOPTS=/DEBUG
|
||||
call :Build
|
||||
goto Done
|
||||
|
||||
:GccBuild
|
||||
set OUTDIR=.\GccRel
|
||||
set OPTS=-O2
|
||||
if "%DEBUG%" == "Y" set OPTS=-O0
|
||||
if "%DEBUG%" == "Y" set OUTDIR=.\GccDebug
|
||||
call :Build
|
||||
goto Done
|
||||
|
||||
:Done
|
||||
call :Reset
|
||||
goto :EOF
|
||||
|
||||
:Build
|
||||
:: Clean the directory if it exists
|
||||
if exist %OUTDIR%\nul rmdir /S /Q %OUTDIR%
|
||||
|
||||
:: Recreate it
|
||||
mkdir %OUTDIR%
|
||||
mkdir %OUTDIR%\glob
|
||||
mkdir %OUTDIR%\w32
|
||||
mkdir %OUTDIR%\w32\compat
|
||||
mkdir %OUTDIR%\w32\subproc
|
||||
|
||||
if "%GUILE%" == "Y" call :ChkGuile
|
||||
|
||||
echo.
|
||||
echo Compiling %OUTDIR% version
|
||||
|
||||
if exist config.h.W32.template call :ConfigSCM
|
||||
copy config.h.W32 %OUTDIR%\config.h
|
||||
|
||||
call :Compile ar
|
||||
call :Compile arscan
|
||||
call :Compile commands
|
||||
call :Compile default
|
||||
call :Compile dir
|
||||
call :Compile expand
|
||||
call :Compile file
|
||||
call :Compile function
|
||||
call :Compile getloadavg
|
||||
call :Compile getopt
|
||||
call :Compile getopt1
|
||||
call :Compile glob\fnmatch
|
||||
call :Compile glob\glob
|
||||
call :Compile guile GUILE
|
||||
call :Compile hash
|
||||
call :Compile implicit
|
||||
call :Compile job
|
||||
call :Compile load
|
||||
call :Compile loadapi
|
||||
call :Compile main GUILE
|
||||
call :Compile misc
|
||||
call :Compile output
|
||||
call :Compile read
|
||||
call :Compile remake
|
||||
call :Compile remote-stub
|
||||
call :Compile rule
|
||||
call :Compile signame
|
||||
call :Compile strcache
|
||||
call :Compile variable
|
||||
call :Compile version
|
||||
call :Compile vpath
|
||||
call :Compile w32\compat\posixfcn
|
||||
call :Compile w32\pathstuff
|
||||
call :Compile w32\subproc\misc
|
||||
call :Compile w32\subproc\sub_proc
|
||||
call :Compile w32\subproc\w32err
|
||||
call :Compile w32\w32os
|
||||
|
||||
if not "%COMPILER%" == "gcc" call :Compile w32\compat\dirent
|
||||
|
||||
call :Link
|
||||
|
||||
echo.
|
||||
if not exist %OUTDIR%\%MAKE%.exe echo %OUTDIR% build FAILED!
|
||||
if exist %OUTDIR%\%MAKE%.exe echo %OUTDIR% build succeeded.
|
||||
goto :EOF
|
||||
|
||||
:Compile
|
||||
set EXTRAS=
|
||||
if "%2" == "GUILE" set "EXTRAS=%GUILECFLAGS%"
|
||||
if "%COMPILER%" == "gcc" goto GccCompile
|
||||
|
||||
:: MSVC Compile
|
||||
echo on
|
||||
if not exist .\WinDebug\nul mkdir .\WinDebug
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c
|
||||
echo WinDebug\variable.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c rule.c
|
||||
echo WinDebug\rule.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remote-stub.c
|
||||
echo WinDebug\remote-stub.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c commands.c
|
||||
echo WinDebug\commands.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c file.c
|
||||
echo WinDebug\file.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getloadavg.c
|
||||
echo WinDebug\getloadavg.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c default.c
|
||||
echo WinDebug\default.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c signame.c
|
||||
echo WinDebug\signame.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c expand.c
|
||||
echo WinDebug\expand.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c dir.c
|
||||
echo WinDebug\dir.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od %GUILECFLAGS% /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c main.c
|
||||
echo WinDebug\main.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt1.c
|
||||
echo WinDebug\getopt1.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c job.c
|
||||
echo WinDebug\job.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c output.c
|
||||
echo WinDebug\output.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c read.c
|
||||
echo WinDebug\read.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c version.c
|
||||
echo WinDebug\version.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt.c
|
||||
echo WinDebug\getopt.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c arscan.c
|
||||
echo WinDebug\arscan.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c hash.c
|
||||
echo WinDebug\hash.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c strcache.c
|
||||
echo WinDebug\strcache.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remake.c
|
||||
echo WinDebug\remake.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c misc.c
|
||||
echo WinDebug\misc.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c ar.c
|
||||
echo WinDebug\ar.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c function.c
|
||||
echo WinDebug\function.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c vpath.c
|
||||
echo WinDebug\vpath.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c implicit.c
|
||||
echo WinDebug\implicit.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c loadapi.c
|
||||
echo WinDebug\loadapi.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c load.c
|
||||
echo WinDebug\load.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\dirent.c
|
||||
echo WinDebug\dirent.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\posixfcn.c
|
||||
echo WinDebug\posixfcn.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\glob.c
|
||||
echo WinDebug\glob.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\fnmatch.c
|
||||
echo WinDebug\fnmatch.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\pathstuff.c
|
||||
echo WinDebug\pathstuff.obj >>link.dbg
|
||||
cl.exe /nologo /MT /W4 /GX /Zi /YX /Od %GUILECFLAGS% /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c guile.c
|
||||
echo WinDebug\guile.obj >>link.dbg
|
||||
:LinkDbg
|
||||
echo off
|
||||
echo "Linking WinDebug/%make%.exe"
|
||||
rem link.exe %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj .\WinDebug/rule.obj .\WinDebug/remote-stub.obj .\WinDebug/commands.obj .\WinDebug/file.obj .\WinDebug/getloadavg.obj .\WinDebug/default.obj .\WinDebug/signame.obj .\WinDebug/expand.obj .\WinDebug/dir.obj .\WinDebug/main.obj .\WinDebug/getopt1.obj .\WinDebug/job.obj .\WinDebug/output.obj .\WinDebug/read.obj .\WinDebug/version.obj .\WinDebug/getopt.obj .\WinDebug/arscan.obj .\WinDebug/remake.obj .\WinDebug/hash.obj .\WinDebug/strcache.obj .\WinDebug/misc.obj .\WinDebug/ar.obj .\WinDebug/function.obj .\WinDebug/vpath.obj .\WinDebug/implicit.obj .\WinDebug/dirent.obj .\WinDebug/glob.obj .\WinDebug/fnmatch.obj .\WinDebug/pathstuff.obj
|
||||
echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg
|
||||
link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe @link.dbg
|
||||
if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
|
||||
if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
|
||||
if not exist .\WinRel\nul mkdir .\WinRel
|
||||
echo on
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /D TIVOLI /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c variable.c
|
||||
echo WinRel\variable.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c rule.c
|
||||
echo WinRel\rule.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remote-stub.c
|
||||
echo WinRel\remote-stub.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c commands.c
|
||||
echo WinRel\commands.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c file.c
|
||||
echo WinRel\file.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getloadavg.c
|
||||
echo WinRel\getloadavg.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c default.c
|
||||
echo WinRel\default.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c signame.c
|
||||
echo WinRel\signame.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c expand.c
|
||||
echo WinRel\expand.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c dir.c
|
||||
echo WinRel\dir.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 %GUILECFLAGS% /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c main.c
|
||||
echo WinRel\main.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt1.c
|
||||
echo WinRel\getopt1.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c job.c
|
||||
echo WinRel\job.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c output.c
|
||||
echo WinRel\output.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c read.c
|
||||
echo WinRel\read.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c version.c
|
||||
echo WinRel\version.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt.c
|
||||
echo WinRel\getopt.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c arscan.c
|
||||
echo WinRel\arscan.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remake.c
|
||||
echo WinRel\remake.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c hash.c
|
||||
echo WinRel\hash.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c strcache.c
|
||||
echo WinRel\strcache.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c misc.c
|
||||
echo WinRel\misc.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c ar.c
|
||||
echo WinRel\ar.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c function.c
|
||||
echo WinRel\function.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c vpath.c
|
||||
echo WinRel\vpath.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c implicit.c
|
||||
echo WinRel\implicit.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c loadapi.c
|
||||
echo WinRel\loadapi.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c load.c
|
||||
echo WinRel\load.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\dirent.c
|
||||
echo WinRel\dirent.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\posixfcn.c
|
||||
echo WinRel\posixfcn.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\glob.c
|
||||
echo WinRel\glob.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\fnmatch.c
|
||||
echo WinRel\fnmatch.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\pathstuff.c
|
||||
echo WinRel\pathstuff.obj >>link.rel
|
||||
cl.exe /nologo /MT /W4 /GX /YX /O2 %GUILECFLAGS% /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c guile.c
|
||||
echo WinRel\guile.obj >>link.rel
|
||||
:LinkRel
|
||||
echo off
|
||||
echo "Linking WinRel/%make%.exe"
|
||||
rem link.exe %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj .\WinRel/rule.obj .\WinRel/remote-stub.obj .\WinRel/commands.obj .\WinRel/file.obj .\WinRel/getloadavg.obj .\WinRel/default.obj .\WinRel/signame.obj .\WinRel/expand.obj .\WinRel/dir.obj .\WinRel/main.obj .\WinRel/getopt1.obj .\WinRel/job.obj .\WinRel/output.obj .\WinRel/read.obj .\WinRel/version.obj .\WinRel/getopt.obj .\WinRel/arscan.obj .\WinRel/remake.obj .\WinRel/misc.obj .\WinRel/hash.obj .\WinRel/strcache.obj .\WinRel/ar.obj .\WinRel/function.obj .\WinRel/vpath.obj .\WinRel/implicit.obj .\WinRel/dirent.obj .\WinRel/glob.obj .\WinRel/fnmatch.obj .\WinRel/pathstuff.obj
|
||||
echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel
|
||||
link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe @link.rel
|
||||
if not exist .\WinRel/%make%.exe echo "WinRel build failed"
|
||||
if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
|
||||
set make=
|
||||
GoTo BuildEnd
|
||||
:GCCBuild
|
||||
echo on
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H %GUILECFLAGS% -c main.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c output.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c strcache.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c loadapi.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c load.c
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/compat/posixfcn.c -o posixfcn.o
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% %GUILECFLAGS% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c guile.c
|
||||
:LinkGCC
|
||||
cl.exe /nologo /MT /W4 /GX /YX %OPTS% /I %OUTDIR% /I . /I glob /I w32/include /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR%OUTDIR% /Fp%OUTDIR%\%MAKE%.pch /Fo%OUTDIR%\%1.obj /Fd%OUTDIR%\%MAKE%.pdb %EXTRAS% /c %1.c
|
||||
@echo off
|
||||
Rem The version NN of libgnumake-NN.dll.a should be bumped whenever
|
||||
Rem the API changes in binary-incompatible manner.
|
||||
@echo on
|
||||
gcc -mthreads -gdwarf-2 -g3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o guile.o job.o output.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o loadapi.o load.o glob.o fnmatch.o pathstuff.o posixfcn.o w32_misc.o sub_proc.o w32err.o %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -Wl,--out-implib=libgnumake-1.dll.a
|
||||
@GoTo BuildEnd
|
||||
echo %OUTDIR%\%1.obj >>%OUTDIR%\link.sc
|
||||
goto :EOF
|
||||
|
||||
:GccCompile
|
||||
:: GCC Compile
|
||||
echo on
|
||||
gcc -mthreads -Wall -gdwarf-2 -g3 %OPTS% -I%OUTDIR% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%\%1.o -c %1.c
|
||||
@echo off
|
||||
goto :EOF
|
||||
|
||||
:Link
|
||||
echo Linking %OUTDIR%/%MAKE%.exe
|
||||
if "%COMPILER%" == "gcc" goto GccLink
|
||||
|
||||
:: MSVC Link
|
||||
echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib >>%OUTDIR%\link.sc
|
||||
echo on
|
||||
link.exe /NOLOGO /SUBSYSTEM:console /PDB:%OUTDIR%\%MAKE%.pdb %LINKOPTS% /OUT:%OUTDIR%\%MAKE%.exe @%OUTDIR%\link.sc
|
||||
@echo off
|
||||
goto :EOF
|
||||
|
||||
:GccLink
|
||||
:: GCC Link
|
||||
echo on
|
||||
gcc -mthreads -gdwarf-2 -g3 -o %OUTDIR%\%MAKE%.exe %OUTDIR%\variable.o %OUTDIR%\rule.o %OUTDIR%\remote-stub.o %OUTDIR%\commands.o %OUTDIR%\file.o %OUTDIR%\getloadavg.o %OUTDIR%\default.o %OUTDIR%\signame.o %OUTDIR%\expand.o %OUTDIR%\dir.o %OUTDIR%\main.o %OUTDIR%\getopt1.o %OUTDIR%\guile.o %OUTDIR%\job.o %OUTDIR%\output.o %OUTDIR%\read.o %OUTDIR%\version.o %OUTDIR%\getopt.o %OUTDIR%\arscan.o %OUTDIR%\remake.o %OUTDIR%\misc.o %OUTDIR%\hash.o %OUTDIR%\strcache.o %OUTDIR%\ar.o %OUTDIR%\function.o %OUTDIR%\vpath.o %OUTDIR%\implicit.o %OUTDIR%\loadapi.o %OUTDIR%\load.o %OUTDIR%\glob\glob.o %OUTDIR%\glob\fnmatch.o %OUTDIR%\w32\pathstuff.o %OUTDIR%\w32\compat\posixfcn.o %OUTDIR%\w32\w32os.o %OUTDIR%\w32\subproc\misc.o %OUTDIR%\w32\subproc\sub_proc.o %OUTDIR%\w32\subproc\w32err.o %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -Wl,--out-implib=%OUTDIR%\libgnumake-1.dll.a
|
||||
@echo off
|
||||
goto :EOF
|
||||
|
||||
:ConfigSCM
|
||||
echo Generating config from SCM templates
|
||||
sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > %OUTDIR%\config.h.W32.sed
|
||||
echo s,%%PACKAGE%%,make,g >> %OUTDIR%\config.h.W32.sed
|
||||
sed -f %OUTDIR%\config.h.W32.sed config.h.W32.template > config.h.W32
|
||||
echo static const char *const GUILE_module_defn = ^" \> gmk-default.h
|
||||
sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\\/" gmk-default.scm >> gmk-default.h
|
||||
echo ^";>> gmk-default.h
|
||||
goto :EOF
|
||||
|
||||
:ChkGuile
|
||||
if not "%OS%" == "Windows_NT" goto NoGuile
|
||||
pkg-config --help > %OUTDIR%\guile.tmp 2> NUL
|
||||
if ERRORLEVEL 1 goto NoPkgCfg
|
||||
|
||||
echo Checking for Guile 2.0
|
||||
if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax
|
||||
pkg-config --cflags --short-errors "guile-2.0" > %OUTDIR%\guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\guile.tmp
|
||||
|
||||
pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > %OUTDIR%\guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\guile.tmp
|
||||
|
||||
if not "%GUILECFLAGS%" == "" goto GuileDone
|
||||
|
||||
echo Checking for Guile 1.8
|
||||
pkg-config --cflags --short-errors "guile-1.8" > %OUTDIR%\guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\guile.tmp
|
||||
|
||||
pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > %OUTDIR%\guile.tmp
|
||||
if not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\guile.tmp
|
||||
|
||||
if not "%GUILECFLAGS%" == "" goto GuileDone
|
||||
|
||||
echo No Guile found, building without Guile
|
||||
goto GuileDone
|
||||
|
||||
:NoPkgCfg
|
||||
echo pkg-config not found, building without Guile
|
||||
|
||||
:GuileDone
|
||||
if "%GUILECFLAGS%" == "" goto :EOF
|
||||
|
||||
echo Guile found, building with Guile
|
||||
set "GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE"
|
||||
goto :EOF
|
||||
|
||||
:Usage
|
||||
echo Usage: %0 [options] [gcc]
|
||||
echo Options:
|
||||
|
@ -299,12 +233,18 @@ echo. --debug For GCC only, make a debug build
|
|||
echo. (MSVC build always makes both debug and release)
|
||||
echo. --without-guile Do not compile Guile support even if found
|
||||
echo. --help Display these instructions and exit
|
||||
:BuildEnd
|
||||
@echo off
|
||||
set GUILELIBS=
|
||||
set GUILECFLAGS=
|
||||
set PKGMSC=
|
||||
set OPT=
|
||||
goto :EOF
|
||||
|
||||
:Reset
|
||||
set COMPILER=
|
||||
set DEBUG=
|
||||
set GUILE=
|
||||
set GUILECFLAGS=
|
||||
set GUILELIBS=
|
||||
set LINKOPTS=
|
||||
set MAKE=
|
||||
set NOGUILE=
|
||||
echo on
|
||||
set OPTS=
|
||||
set OUTDIR=
|
||||
set PKGMSC=
|
||||
goto :EOF
|
||||
|
|
196
job.c
196
job.c
|
@ -23,6 +23,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "filedef.h"
|
||||
#include "commands.h"
|
||||
#include "variable.h"
|
||||
#include "os.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
@ -541,11 +542,7 @@ child_handler (int sig UNUSED)
|
|||
{
|
||||
++dead_children;
|
||||
|
||||
if (job_rfd >= 0)
|
||||
{
|
||||
close (job_rfd);
|
||||
job_rfd = -1;
|
||||
}
|
||||
jobserver_signal ();
|
||||
|
||||
#ifdef __EMX__
|
||||
/* The signal handler must called only once! */
|
||||
|
@ -1012,35 +1009,12 @@ free_child (struct child *child)
|
|||
/* If we're using the jobserver and this child is not the only outstanding
|
||||
job, put a token back into the pipe for it. */
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if (has_jobserver_semaphore () && jobserver_tokens > 1)
|
||||
if (jobserver_enabled () && jobserver_tokens > 1)
|
||||
{
|
||||
if (! release_jobserver_semaphore ())
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
const char *estr = map_windows32_error_to_string (err);
|
||||
ONS (fatal, NILF,
|
||||
_("release jobserver semaphore: (Error %ld: %s)"), err, estr);
|
||||
}
|
||||
|
||||
DB (DB_JOBS, (_("Released token for child %p (%s).\n"), child, child->file->name));
|
||||
}
|
||||
#else
|
||||
if (job_fds[1] >= 0 && jobserver_tokens > 1)
|
||||
{
|
||||
char token = '+';
|
||||
int r;
|
||||
|
||||
/* Write a job token back to the pipe. */
|
||||
|
||||
EINTRLOOP (r, write (job_fds[1], &token, 1));
|
||||
if (r != 1)
|
||||
pfatal_with_name (_("write jobserver"));
|
||||
|
||||
jobserver_release (1);
|
||||
DB (DB_JOBS, (_("Released token for child %p (%s).\n"),
|
||||
child, child->file->name));
|
||||
}
|
||||
#endif
|
||||
|
||||
--jobserver_tokens;
|
||||
|
||||
|
@ -1092,60 +1066,6 @@ unblock_sigs (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(MAKE_JOBSERVER) && !defined(WINDOWS32)
|
||||
RETSIGTYPE
|
||||
job_noop (int sig UNUSED)
|
||||
{
|
||||
}
|
||||
/* Set the child handler action flags to FLAGS. */
|
||||
static void
|
||||
set_child_handler_action_flags (int set_handler, int set_alarm)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
#ifdef __EMX__
|
||||
/* The child handler must be turned off here. */
|
||||
signal (SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
|
||||
memset (&sa, '\0', sizeof sa);
|
||||
sa.sa_handler = child_handler;
|
||||
sa.sa_flags = set_handler ? 0 : SA_RESTART;
|
||||
#if defined SIGCHLD
|
||||
if (sigaction (SIGCHLD, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGCHLD");
|
||||
#endif
|
||||
#if defined SIGCLD && SIGCLD != SIGCHLD
|
||||
if (sigaction (SIGCLD, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGCLD");
|
||||
#endif
|
||||
#if defined SIGALRM
|
||||
if (set_alarm)
|
||||
{
|
||||
/* If we're about to enter the read(), set an alarm to wake up in a
|
||||
second so we can check if the load has dropped and we can start more
|
||||
work. On the way out, turn off the alarm and set SIG_DFL. */
|
||||
if (set_handler)
|
||||
{
|
||||
sa.sa_handler = job_noop;
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction (SIGALRM, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGALRM");
|
||||
alarm (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm (0);
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction (SIGALRM, &sa, NULL) < 0)
|
||||
pfatal_with_name ("sigaction: SIGALRM");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Start a job to run the commands specified in CHILD.
|
||||
CHILD is updated to reflect the commands and ID of the child process.
|
||||
|
@ -1516,13 +1436,8 @@ start_job_command (struct child *child)
|
|||
# ifdef __EMX__
|
||||
/* If we aren't running a recursive command and we have a jobserver
|
||||
pipe, close it before exec'ing. */
|
||||
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
|
||||
{
|
||||
CLOSE_ON_EXEC (job_fds[0]);
|
||||
CLOSE_ON_EXEC (job_fds[1]);
|
||||
}
|
||||
if (job_rfd >= 0)
|
||||
CLOSE_ON_EXEC (job_rfd);
|
||||
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
|
||||
jobserver_pre_child ();
|
||||
|
||||
/* Never use fork()/exec() here! Use spawn() instead in exec_command() */
|
||||
child->pid = child_execute_job (child->good_stdin ? FD_STDIN : bad_stdin,
|
||||
|
@ -1537,13 +1452,8 @@ start_job_command (struct child *child)
|
|||
}
|
||||
|
||||
/* undo CLOSE_ON_EXEC() after the child process has been started */
|
||||
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
|
||||
{
|
||||
fcntl (job_fds[0], F_SETFD, 0);
|
||||
fcntl (job_fds[1], F_SETFD, 0);
|
||||
}
|
||||
if (job_rfd >= 0)
|
||||
fcntl (job_rfd, F_SETFD, 0);
|
||||
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
|
||||
jobserver_post_child ();
|
||||
|
||||
#else /* !__EMX__ */
|
||||
|
||||
|
@ -1554,15 +1464,10 @@ start_job_command (struct child *child)
|
|||
/* We are the child side. */
|
||||
unblock_sigs ();
|
||||
|
||||
/* If we aren't running a recursive command and we have a jobserver
|
||||
pipe, close it before exec'ing. */
|
||||
if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0)
|
||||
{
|
||||
close (job_fds[0]);
|
||||
close (job_fds[1]);
|
||||
}
|
||||
if (job_rfd >= 0)
|
||||
close (job_rfd);
|
||||
/* If we AREN'T running a recursive command and we have a jobserver,
|
||||
clear it before exec'ing. */
|
||||
if (!(flags & COMMANDS_RECURSE) && jobserver_enabled ())
|
||||
jobserver_clear ();
|
||||
|
||||
#ifdef SET_STACK_SIZE
|
||||
/* Reset limits, if necessary. */
|
||||
|
@ -1952,18 +1857,10 @@ new_job (struct file *file)
|
|||
just once). Also more thought needs to go into the entire algorithm;
|
||||
this is where the old parallel job code waits, so... */
|
||||
|
||||
#ifdef WINDOWS32
|
||||
else if (has_jobserver_semaphore ())
|
||||
#else
|
||||
else if (job_fds[0] >= 0)
|
||||
#endif
|
||||
else if (jobserver_enabled ())
|
||||
while (1)
|
||||
{
|
||||
int got_token;
|
||||
#ifndef WINDOWS32
|
||||
char token;
|
||||
int saved_errno;
|
||||
#endif
|
||||
|
||||
DB (DB_JOBS, ("Need a job token; we %shave children\n",
|
||||
children ? "" : "don't "));
|
||||
|
@ -1972,36 +1869,8 @@ new_job (struct file *file)
|
|||
if (!jobserver_tokens)
|
||||
break;
|
||||
|
||||
#ifndef WINDOWS32
|
||||
/* Read a token. As long as there's no token available we'll block.
|
||||
We enable interruptible system calls before the read(2) so that if
|
||||
we get a SIGCHLD while we're waiting, we'll return with EINTR and
|
||||
we can process the death(s) and return tokens to the free pool.
|
||||
|
||||
Once we return from the read, we immediately reinstate restartable
|
||||
system calls. This allows us to not worry about checking for
|
||||
EINTR on all the other system calls in the program.
|
||||
|
||||
There is one other twist: there is a span between the time
|
||||
reap_children() does its last check for dead children and the time
|
||||
the read(2) call is entered, below, where if a child dies we won't
|
||||
notice. This is extremely serious as it could cause us to
|
||||
deadlock, given the right set of events.
|
||||
|
||||
To avoid this, we do the following: before we reap_children(), we
|
||||
dup(2) the read FD on the jobserver pipe. The read(2) call below
|
||||
uses that new FD. In the signal handler, we close that FD. That
|
||||
way, if a child dies during the section mentioned above, the
|
||||
read(2) will be invoked with an invalid FD and will return
|
||||
immediately with EBADF. */
|
||||
|
||||
/* Make sure we have a dup'd FD. */
|
||||
if (job_rfd < 0)
|
||||
{
|
||||
DB (DB_JOBS, ("Duplicate the job FD\n"));
|
||||
EINTRLOOP (job_rfd, dup (job_fds[0]));
|
||||
}
|
||||
#endif
|
||||
/* Prepare for jobserver token acquisition. */
|
||||
jobserver_pre_acquire ();
|
||||
|
||||
/* Reap anything that's currently waiting. */
|
||||
reap_children (0, 0);
|
||||
|
@ -2010,8 +1879,7 @@ new_job (struct file *file)
|
|||
can run now (i.e., waiting for load). */
|
||||
start_waiting_jobs ();
|
||||
|
||||
/* If our "free" slot has become available, use it; we don't need an
|
||||
actual token. */
|
||||
/* If our "free" slot is available, use it; we don't need a token. */
|
||||
if (!jobserver_tokens)
|
||||
break;
|
||||
|
||||
|
@ -2020,26 +1888,8 @@ new_job (struct file *file)
|
|||
if (!children)
|
||||
O (fatal, NILF, "INTERNAL: no children as we go to sleep on read\n");
|
||||
|
||||
#ifdef WINDOWS32
|
||||
/* On Windows we simply wait for the jobserver semaphore to become
|
||||
* signalled or one of our child processes to terminate.
|
||||
*/
|
||||
got_token = wait_for_semaphore_or_child_process ();
|
||||
if (got_token < 0)
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
const char *estr = map_windows32_error_to_string (err);
|
||||
ONS (fatal, NILF,
|
||||
_("semaphore or child process wait: (Error %ld: %s)"),
|
||||
err, estr);
|
||||
}
|
||||
#else
|
||||
/* Set interruptible system calls, and read() for a job token. */
|
||||
set_child_handler_action_flags (1, waiting_jobs != NULL);
|
||||
EINTRLOOP (got_token, read (job_rfd, &token, 1));
|
||||
saved_errno = errno;
|
||||
set_child_handler_action_flags (0, waiting_jobs != NULL);
|
||||
#endif
|
||||
/* Get a token. */
|
||||
got_token = jobserver_acquire (waiting_jobs != NULL);
|
||||
|
||||
/* If we got one, we're done here. */
|
||||
if (got_token == 1)
|
||||
|
@ -2048,16 +1898,6 @@ new_job (struct file *file)
|
|||
c, c->file->name));
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef WINDOWS32
|
||||
/* If the error _wasn't_ expected (EINTR or EBADF), punt. Otherwise,
|
||||
go back and reap_children(), and try again. */
|
||||
errno = saved_errno;
|
||||
if (errno != EINTR && errno != EBADF)
|
||||
pfatal_with_name (_("read jobs pipe"));
|
||||
if (errno == EBADF)
|
||||
DB (DB_JOBS, ("Read returned EBADF.\n"));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
2
job.h
2
job.h
|
@ -115,6 +115,8 @@ struct child
|
|||
|
||||
extern struct child *children;
|
||||
|
||||
/* A signal handler for SIGCHLD, if needed. */
|
||||
RETSIGTYPE child_handler (int sig);
|
||||
int is_bourne_compatible_shell(const char *path);
|
||||
void new_job (struct file *file);
|
||||
void reap_children (int block, int err);
|
||||
|
|
217
main.c
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/>. */
|
||||
|
||||
#include "makeint.h"
|
||||
#include "os.h"
|
||||
#include "filedef.h"
|
||||
#include "dep.h"
|
||||
#include "variable.h"
|
||||
|
@ -270,15 +271,12 @@ static unsigned int inf_jobs = 0;
|
|||
|
||||
/* File descriptors for the jobs pipe. */
|
||||
|
||||
char *jobserver_fds = 0;
|
||||
|
||||
int job_fds[2] = { -1, -1 };
|
||||
int job_rfd = -1;
|
||||
char *jobserver_fds = NULL;
|
||||
|
||||
/* Handle for the mutex used on Windows to synchronize output of our
|
||||
children under -O. */
|
||||
|
||||
char *sync_mutex = 0;
|
||||
char *sync_mutex = NULL;
|
||||
|
||||
/* Maximum load average at which multiple jobs will be run.
|
||||
Negative values mean unlimited, while zero means limit to
|
||||
|
@ -600,7 +598,7 @@ struct output make_sync;
|
|||
|
||||
/* Mask of signals that are being caught with fatal_error_signal. */
|
||||
|
||||
#ifdef POSIX
|
||||
#ifdef POSIX
|
||||
sigset_t fatal_signal_set;
|
||||
#else
|
||||
# ifdef HAVE_SIGSETMASK
|
||||
|
@ -1597,85 +1595,33 @@ main (int argc, char **argv, char **envp)
|
|||
starting_directory = current_directory;
|
||||
|
||||
#ifdef MAKE_JOBSERVER
|
||||
/* If the jobserver-fds option is seen, make sure that -j is reasonable.
|
||||
/* If the jobserver_fds option is seen, make sure that -j is reasonable.
|
||||
This can't be usefully set in the makefile, and we want to verify the
|
||||
FDs are valid before any other aspect of make has a chance to start
|
||||
using them for something else. */
|
||||
|
||||
if (jobserver_fds)
|
||||
{
|
||||
/* Make sure the jobserver option has the proper format. */
|
||||
const char *cp = jobserver_fds;
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if (! open_jobserver_semaphore (cp))
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
const char *estr = map_windows32_error_to_string (err);
|
||||
fatal (NILF, strlen (cp) + INTSTR_LENGTH + strlen (estr),
|
||||
_("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
|
||||
cp, err, estr);
|
||||
}
|
||||
DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), cp));
|
||||
#else
|
||||
if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
|
||||
OS (fatal, NILF,
|
||||
_("internal error: invalid --jobserver-fds string '%s'"), cp);
|
||||
|
||||
DB (DB_JOBS,
|
||||
(_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
|
||||
#endif
|
||||
|
||||
/* The combination of a pipe + !job_slots means we're using the
|
||||
jobserver. If !job_slots and we don't have a pipe, we can start
|
||||
infinite jobs. If we see both a pipe and job_slots >0 that means the
|
||||
/* The combination of jobserver_fds and !job_slots means we're using the
|
||||
jobserver. If !job_slots and no jobserver_fds, we can start infinite
|
||||
jobs. If we see both jobserver_fds and job_slots >0 that means the
|
||||
user set -j explicitly. This is broken; in this case obey the user
|
||||
(ignore the jobserver pipe for this make) but print a message.
|
||||
If we've restarted, we already printed this the first time. */
|
||||
(ignore the jobserver for this make) but print a message. If we've
|
||||
restarted, we already printed this the first time. */
|
||||
|
||||
if (!job_slots)
|
||||
jobserver_parse_arg (jobserver_fds);
|
||||
|
||||
else if (! restarts)
|
||||
O (error, NILF,
|
||||
_("warning: -jN forced in submake: disabling jobserver mode."));
|
||||
|
||||
if (job_slots > 0)
|
||||
{
|
||||
if (! restarts)
|
||||
O (error, NILF,
|
||||
_("warning: -jN forced in submake: disabling jobserver mode."));
|
||||
}
|
||||
#ifndef WINDOWS32
|
||||
#ifdef HAVE_FCNTL
|
||||
# define FD_OK(_f) ((fcntl ((_f), F_GETFD) != -1) || (errno != EBADF))
|
||||
#else
|
||||
# define FD_OK(_f) 1
|
||||
#endif
|
||||
/* Create a duplicate pipe, that will be closed in the SIGCHLD
|
||||
handler. If this fails with EBADF, the parent has closed the pipe
|
||||
on us because it didn't think we were a submake. If so, print a
|
||||
warning then default to -j1. */
|
||||
else if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1])
|
||||
|| (job_rfd = dup (job_fds[0])) < 0)
|
||||
{
|
||||
if (errno != EBADF)
|
||||
pfatal_with_name (_("dup jobserver"));
|
||||
|
||||
O (error, NILF,
|
||||
_("warning: jobserver unavailable: using -j1. Add '+' to parent make rule."));
|
||||
job_slots = 1;
|
||||
job_fds[0] = job_fds[1] = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (job_slots > 0)
|
||||
{
|
||||
#ifdef WINDOWS32
|
||||
free_jobserver_semaphore ();
|
||||
#else
|
||||
if (job_fds[0] >= 0)
|
||||
close (job_fds[0]);
|
||||
if (job_fds[1] >= 0)
|
||||
close (job_fds[1]);
|
||||
#endif
|
||||
job_fds[0] = job_fds[1] = -1;
|
||||
|
||||
/* If job_slots is set now then we're not using jobserver */
|
||||
jobserver_clear ();
|
||||
free (jobserver_fds);
|
||||
jobserver_fds = 0;
|
||||
jobserver_fds = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1902,7 +1848,7 @@ main (int argc, char **argv, char **envp)
|
|||
}
|
||||
|
||||
#ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
|
||||
#if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG)
|
||||
#if !defined(HAVE_WAIT_NOHANG) || defined(MAKE_JOBSERVER)
|
||||
/* Set up to handle children dying. This must be done before
|
||||
reading in the makefiles so that 'shell' function calls will work.
|
||||
|
||||
|
@ -1910,9 +1856,9 @@ main (int argc, char **argv, char **envp)
|
|||
functionality here and rely on the signal handler and counting
|
||||
children.
|
||||
|
||||
If we're using the jobs pipe we need a signal handler so that
|
||||
SIGCHLD is not ignored; we need it to interrupt the read(2) of the
|
||||
jobserver pipe in job.c if we're waiting for a token.
|
||||
If we're using the jobs pipe we need a signal handler so that SIGCHLD is
|
||||
not ignored; we need it to interrupt the read(2) of the jobserver pipe if
|
||||
we're waiting for a token.
|
||||
|
||||
If none of these are true, we don't need a signal handler at all. */
|
||||
{
|
||||
|
@ -2074,66 +2020,23 @@ main (int argc, char **argv, char **envp)
|
|||
#endif
|
||||
|
||||
#ifdef MAKE_JOBSERVER
|
||||
/* If we have >1 slot but no jobserver-fds, then we're a top-level make.
|
||||
Set up the pipe and install the fds option for our children. */
|
||||
|
||||
if (job_slots > 1)
|
||||
{
|
||||
#ifdef WINDOWS32
|
||||
/* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects
|
||||
* and one of them is the job-server semaphore object. Limit the
|
||||
* number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */
|
||||
/* If we have >1 slot at this point, then we're a top-level make.
|
||||
Set up the jobserver.
|
||||
|
||||
if (job_slots >= MAXIMUM_WAIT_OBJECTS)
|
||||
{
|
||||
job_slots = MAXIMUM_WAIT_OBJECTS - 1;
|
||||
DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), job_slots));
|
||||
}
|
||||
|
||||
if (! create_jobserver_semaphore (job_slots - 1))
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
const char *estr = map_windows32_error_to_string (err);
|
||||
ONS (fatal, NILF,
|
||||
_("creating jobserver semaphore: (Error %ld: %s)"), err, estr);
|
||||
}
|
||||
#else
|
||||
char c = '+';
|
||||
|
||||
if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
|
||||
pfatal_with_name (_("creating jobs pipe"));
|
||||
#endif
|
||||
|
||||
/* Every make assumes that it always has one job it can run. For the
|
||||
Every make assumes that it always has one job it can run. For the
|
||||
submakes it's the token they were given by their parent. For the
|
||||
top make, we just subtract one from the number the user wants. We
|
||||
want job_slots to be 0 to indicate we're using the jobserver. */
|
||||
top make, we just subtract one from the number the user wants. */
|
||||
|
||||
jobserver_setup (job_slots - 1);
|
||||
|
||||
/* We're using the jobserver so set job_slots to 0. */
|
||||
master_job_slots = job_slots;
|
||||
|
||||
#ifdef WINDOWS32
|
||||
/* We're using the jobserver so set job_slots to 0. */
|
||||
job_slots = 0;
|
||||
#else
|
||||
while (--job_slots)
|
||||
{
|
||||
int r;
|
||||
|
||||
EINTRLOOP (r, write (job_fds[1], &c, 1));
|
||||
if (r != 1)
|
||||
pfatal_with_name (_("init jobserver pipe"));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill in the jobserver_fds for our children. */
|
||||
|
||||
#ifdef WINDOWS32
|
||||
jobserver_fds = xmalloc (MAX_PATH + 1);
|
||||
strcpy (jobserver_fds, get_jobserver_semaphore_name ());
|
||||
#else
|
||||
jobserver_fds = xmalloc ((INTSTR_LENGTH * 2) + 2);
|
||||
sprintf (jobserver_fds, "%d,%d", job_fds[0], job_fds[1]);
|
||||
#endif
|
||||
jobserver_fds = jobserver_get_arg ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2489,10 +2392,6 @@ main (int argc, char **argv, char **envp)
|
|||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
|
||||
/* Close the dup'd jobserver pipe if we opened one. */
|
||||
if (job_rfd >= 0)
|
||||
close (job_rfd);
|
||||
|
||||
#ifdef _AMIGA
|
||||
exec_command (nargv);
|
||||
exit (0);
|
||||
|
@ -3444,13 +3343,7 @@ clean_jobserver (int status)
|
|||
have written all our tokens so do that now. If tokens are left
|
||||
after any other error code, that's bad. */
|
||||
|
||||
#ifdef WINDOWS32
|
||||
if (has_jobserver_semaphore () && jobserver_tokens)
|
||||
#else
|
||||
char token = '+';
|
||||
|
||||
if (job_fds[0] != -1 && jobserver_tokens)
|
||||
#endif
|
||||
if (jobserver_enabled() && jobserver_tokens)
|
||||
{
|
||||
if (status != 2)
|
||||
ON (error, NILF,
|
||||
|
@ -3459,18 +3352,7 @@ clean_jobserver (int status)
|
|||
else
|
||||
/* Don't write back the "free" token */
|
||||
while (--jobserver_tokens)
|
||||
{
|
||||
#ifdef WINDOWS32
|
||||
if (! release_jobserver_semaphore ())
|
||||
perror_with_name ("release_jobserver_semaphore", "");
|
||||
#else
|
||||
int r;
|
||||
|
||||
EINTRLOOP (r, write (job_fds[1], &token, 1));
|
||||
if (r != 1)
|
||||
perror_with_name ("write", "");
|
||||
#endif
|
||||
}
|
||||
jobserver_release (0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3479,42 +3361,21 @@ clean_jobserver (int status)
|
|||
if (master_job_slots)
|
||||
{
|
||||
/* We didn't write one for ourself, so start at 1. */
|
||||
unsigned int tcnt = 1;
|
||||
unsigned int tokens = 1 + jobserver_acquire_all ();
|
||||
|
||||
#ifdef WINDOWS32
|
||||
while (acquire_jobserver_semaphore ())
|
||||
++tcnt;
|
||||
#else
|
||||
/* Close the write side, so the read() won't hang. */
|
||||
close (job_fds[1]);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int r;
|
||||
EINTRLOOP (r, read (job_fds[0], &token, 1));
|
||||
if (r != 1)
|
||||
break;
|
||||
++tcnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tcnt != master_job_slots)
|
||||
if (tokens != master_job_slots)
|
||||
ONN (error, NILF,
|
||||
"INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
|
||||
tcnt, master_job_slots);
|
||||
tokens, master_job_slots);
|
||||
|
||||
#ifdef WINDOWS32
|
||||
free_jobserver_semaphore ();
|
||||
#else
|
||||
close (job_fds[0]);
|
||||
#endif
|
||||
jobserver_clear ();
|
||||
|
||||
/* Clean out jobserver_fds so we don't pass this information to any
|
||||
sub-makes. Also reset job_slots since it will be put on the command
|
||||
line, not in MAKEFLAGS. */
|
||||
job_slots = default_job_slots;
|
||||
free (jobserver_fds);
|
||||
jobserver_fds = 0;
|
||||
jobserver_fds = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ changelog-check:
|
|||
po-check:
|
||||
if test -f po/POTFILES.in; then \
|
||||
grep '^[^#]' po/POTFILES.in | sort > $@-1; \
|
||||
$(PERL) -wn -e 'if (/\b_\(/) { $$ARGV eq "makeint.h" || print "$$ARGV\n" and close ARGV }' *.c *.h | sort > $@-2; \
|
||||
$(PERL) -wn -e 'if (/\b_\(/) { $$ARGV eq "./makeint.h" || print "$$ARGV\n" and close ARGV }' `find . -name '*.[ch]'` | sed 's,^\./,,' | sort > $@-2; \
|
||||
diff -u $@-1 $@-2 || exit 1; \
|
||||
rm -f $@-1 $@-2; \
|
||||
fi
|
||||
|
|
|
@ -234,6 +234,9 @@
|
|||
<File
|
||||
RelativePath=".\w32\pathstuff.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\w32\w32os.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\w32\subproc\sub_proc.c">
|
||||
</File>
|
||||
|
|
|
@ -623,8 +623,6 @@ extern int batch_mode_shell;
|
|||
extern char cmd_prefix;
|
||||
|
||||
extern unsigned int job_slots;
|
||||
extern int job_fds[2];
|
||||
extern int job_rfd;
|
||||
#ifndef NO_FLOAT
|
||||
extern double max_load_average;
|
||||
#else
|
||||
|
|
77
os.h
Normal file
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
|
||||
misc.c
|
||||
output.c
|
||||
posixos.c
|
||||
read.c
|
||||
remake.c
|
||||
remote-cstms.c
|
||||
|
@ -43,3 +44,4 @@ variable.h
|
|||
vmsfunctions.c
|
||||
vmsjobs.c
|
||||
vpath.c
|
||||
w32/w32os.c
|
||||
|
|
320
posixos.c
Normal file
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 NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
|
||||
if (dnam != NULL)
|
||||
free (dnam->nam$l_esa);
|
||||
free (dnam->nam$l_esa);
|
||||
free (dnam);
|
||||
free (dir);
|
||||
}
|
||||
|
|
|
@ -32,11 +32,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
EXTERN_DECL(HANDLE process_init, (VOID_DECL));
|
||||
EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,
|
||||
HANDLE stderrh));
|
||||
HANDLE stderrh));
|
||||
EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,
|
||||
char *exec_path, char *as_user));
|
||||
char *exec_path, char *as_user));
|
||||
EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data,
|
||||
int stdin_data_len));
|
||||
int stdin_data_len));
|
||||
EXTERN_DECL(long process_file_io, (HANDLE proc));
|
||||
EXTERN_DECL(void process_cleanup, (HANDLE proc));
|
||||
EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus));
|
||||
|
@ -45,6 +45,7 @@ EXTERN_DECL(HANDLE process_easy, (char** argv, char** env,
|
|||
int outfd, int errfd));
|
||||
EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
|
||||
EXTERN_DECL(int process_used_slots, (VOID_DECL));
|
||||
EXTERN_DECL(DWORD process_set_handles, (HANDLE *handles));
|
||||
|
||||
/* support routines */
|
||||
EXTERN_DECL(long process_errno, (HANDLE proc));
|
||||
|
@ -58,14 +59,4 @@ EXTERN_DECL(int process_errcnt, (HANDLE proc));
|
|||
EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));
|
||||
EXTERN_DECL(void process_noinherit, (int fildes));
|
||||
|
||||
/* jobserver routines */
|
||||
EXTERN_DECL(int open_jobserver_semaphore, (const char* name));
|
||||
EXTERN_DECL(int create_jobserver_semaphore, (int tokens));
|
||||
EXTERN_DECL(void free_jobserver_semaphore, (VOID_DECL));
|
||||
EXTERN_DECL(int acquire_jobserver_semaphore, (VOID_DECL));
|
||||
EXTERN_DECL(int release_jobserver_semaphore, (VOID_DECL));
|
||||
EXTERN_DECL(int has_jobserver_semaphore, (VOID_DECL));
|
||||
EXTERN_DECL(char* get_jobserver_semaphore_name, (VOID_DECL));
|
||||
EXTERN_DECL(int wait_for_semaphore_or_child_process, (VOID_DECL));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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 fake_exits_pending = 0;
|
||||
|
||||
/* Windows jobserver implementation variables */
|
||||
static char jobserver_semaphore_name[MAX_PATH + 1];
|
||||
static HANDLE jobserver_semaphore = NULL;
|
||||
|
||||
/* Open existing jobserver semaphore */
|
||||
int open_jobserver_semaphore(const char* name)
|
||||
{
|
||||
jobserver_semaphore = OpenSemaphore(
|
||||
SEMAPHORE_ALL_ACCESS, // Semaphore access setting
|
||||
FALSE, // Child processes DON'T inherit
|
||||
name); // Semaphore name
|
||||
|
||||
if (jobserver_semaphore == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create new jobserver semaphore */
|
||||
int create_jobserver_semaphore(int tokens)
|
||||
{
|
||||
sprintf(jobserver_semaphore_name, "gmake_semaphore_%d", _getpid());
|
||||
|
||||
jobserver_semaphore = CreateSemaphore(
|
||||
NULL, // Use default security descriptor
|
||||
tokens, // Initial count
|
||||
tokens, // Maximum count
|
||||
jobserver_semaphore_name); // Semaphore name
|
||||
|
||||
if (jobserver_semaphore == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Close jobserver semaphore */
|
||||
void free_jobserver_semaphore()
|
||||
{
|
||||
if (jobserver_semaphore != NULL)
|
||||
{
|
||||
CloseHandle(jobserver_semaphore);
|
||||
jobserver_semaphore = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrement semaphore count */
|
||||
int acquire_jobserver_semaphore()
|
||||
{
|
||||
DWORD dwEvent = WaitForSingleObject(
|
||||
jobserver_semaphore, // Handle to semaphore
|
||||
0); // DON'T wait on semaphore
|
||||
|
||||
return (dwEvent == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
/* Increment semaphore count */
|
||||
int release_jobserver_semaphore()
|
||||
{
|
||||
BOOL bResult = ReleaseSemaphore(
|
||||
jobserver_semaphore, // handle to semaphore
|
||||
1, // increase count by one
|
||||
NULL); // not interested in previous count
|
||||
|
||||
return (bResult);
|
||||
}
|
||||
|
||||
int has_jobserver_semaphore()
|
||||
{
|
||||
return (jobserver_semaphore != NULL);
|
||||
}
|
||||
|
||||
char* get_jobserver_semaphore_name()
|
||||
{
|
||||
return (jobserver_semaphore_name);
|
||||
}
|
||||
|
||||
/* Wait for either the jobserver semaphore to become signalled or one of our
|
||||
* child processes to terminate.
|
||||
/*
|
||||
* Fill a HANDLE list with handles to wait for.
|
||||
*/
|
||||
int wait_for_semaphore_or_child_process()
|
||||
DWORD
|
||||
process_set_handles(HANDLE *handles)
|
||||
{
|
||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD dwHandleCount = 1;
|
||||
DWORD dwEvent;
|
||||
DWORD count = 0;
|
||||
int i;
|
||||
|
||||
/* Add jobserver semaphore to first slot. */
|
||||
handles[0] = jobserver_semaphore;
|
||||
|
||||
/* Build array of handles to wait for */
|
||||
for (i = 0; i < proc_index; i++)
|
||||
{
|
||||
for (i = 0; i < proc_index; i++) {
|
||||
/* Don't wait on child processes that have already finished */
|
||||
if (fake_exits_pending && proc_array[i]->exit_code)
|
||||
continue;
|
||||
|
||||
handles[dwHandleCount++] = (HANDLE) proc_array[i]->pid;
|
||||
handles[count++] = (HANDLE) proc_array[i]->pid;
|
||||
}
|
||||
|
||||
dwEvent = WaitForMultipleObjects(
|
||||
dwHandleCount, // number of objects in array
|
||||
handles, // array of objects
|
||||
FALSE, // wait for any object
|
||||
INFINITE); // wait until object is signalled
|
||||
|
||||
switch(dwEvent)
|
||||
{
|
||||
case WAIT_FAILED:
|
||||
return -1;
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
/* Indicate that the semaphore was signalled */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
/* Assume that one or more of the child processes terminated. */
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -756,7 +658,7 @@ process_begin(
|
|||
pproc->lerrno = E_NO_MEM;
|
||||
free( command_line );
|
||||
if ((pproc->last_err == ERROR_INVALID_PARAMETER
|
||||
|| pproc->last_err == ERROR_MORE_DATA)
|
||||
|| pproc->last_err == ERROR_MORE_DATA)
|
||||
&& envsize_needed > 32*1024) {
|
||||
fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n",
|
||||
envsize_needed);
|
||||
|
|
196
w32/w32os.c
Normal file
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