[cmake-developers] [CMake 0015620]: Ninja generator triggers race condition in Borland bcc32 linker causing intermittent build failure
Mantis Bug Tracker
mantis at public.kitware.com
Wed Jun 17 11:37:08 EDT 2015
The following issue has been SUBMITTED.
======================================================================
http://public.kitware.com/Bug/view.php?id=15620
======================================================================
Reported By: James Johnston
Assigned To:
======================================================================
Project: CMake
Issue ID: 15620
Category: CMake
Reproducibility: always
Severity: major
Priority: normal
Status: new
======================================================================
Date Submitted: 2015-06-17 11:37 EDT
Last Modified: 2015-06-17 11:37 EDT
======================================================================
Summary: Ninja generator triggers race condition in Borland
bcc32 linker causing intermittent build failure
Description:
Unfortunately, it appears that the Borland linker utilizes temporary files with
a hard-coded name (e.g. turboc.$ln); these temporary files are written to the
linker's current directory. (Determined via Process Monitor). If two or more
concurrent linkers are run with the same current directory, some of them may
fail as shown below because they will both be trying to use the same temporary
filename.
The Ninja generator, unfortunately seems to keep the current directory to
CMAKE_BINARY_DIR. If the CMake project contains multiple libraries (e.g. VTK
5.4.2, which I tested and has dozens), then it is possible that Ninja will
invoke two concurrent linkers with the same current directory of
CMAKE_BINARY_DIR. They may then conflict with each other - both attempting to
write to a file named ${CMAKE_BINARY_DIR}/turboc.$ln, for example.
To compare, the NMake jom generator runs the linker for each target in a unique
target-specific directory, such that this problem never arises. If the Ninja
generator could also do this, it would work around this issue. (In fact, it
would work around any compiler that happens to write temporary files to its
current directory).
Steps to Reproduce:
My configuration:
* Quad-core hyper-threaded Core i7 CPU
* C++ Builder 5 Update 1
* VTK 5.4.2 (this version still builds under C++ Builder, unlike some newer
versions)
* CMake 3.3.0-rc1 (Kitware-provided binary)
* Ninja 1.5.3, built from source using VC++ 2008 Express
* VTK configured: CMAKE_BUILD_TYPE=RelWithDebInfo, VTK_REMOVE_LEGACY=ON,
BUILD_TESTING=OFF, BUILD_SHARED_LIBS=ON
1. Configure VTK with the above settings. (e.g. to C:\VTK-build)
2. Run "ninja" to start the build.
3. The build *may* fail if two projects happen to link concurrently. Of
course, it will always succeed if you pass "-j 1" to Ninja to only use one CPU
core.
4. Even if you don't immediately experience failure, you can use Sysinternals
Process Monitor from Microsoft to monitor the files being written on your
system. Note that you'll see repeated writes to files like
"C:\VTK-build\turboc.$ln".
Additional Information:
While I tested this with C++ Builder 5, the error appears to exist even in the
newest C++ Builder versions:
http://docwiki.embarcadero.com/RADStudio/XE8/en/E2216_Unable_to_create_turboc.$ln_(C%2B%2B)
Sample error when building VTK 5.4.2:
=====================
[214/2008] Linking CXX shared library bin\vtkDICOMParser.dll Borland C++ 5.5.1
for Win32 Copyright (c) 1993, 2000 Borland Turbo Incremental Link 5.66 Copyright
(c) 1997-2002 Borland
Fatal: No object file or .EXE name was given
Borland Implib Version 3.0.22 Copyright (c) 1991, 2000 Inprise Corporation Error
bin\: unable to open file [215/2008] Linking C shared library bin\vtkzlib.dll
FAILED: cmd.exe /C "cd . && C:\PROGRA~2\Borland\CBUILD~1\Bin\bcc32.exe -tWR
-tW- -tWD -ebin\vtkzlib.dll -tWM -lS:104857
6 -lSc:4098 -lH:1048576 -lHc:8192 -v import32.lib
Utilities\vtkzlib\CMakeFiles\vtkzlib.dir\adler32.obj <snip more OBJ files> &&
implib -c -w bin\vtkzlib.lib bin\vtkzlib.dll && cd ."
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland Turbo Incremental
Link 5.66 Copyright (c) 1997-2002 Borland
Fatal: Unable to open file 'turboc.$ln'
=====================
Here is the offending snippet from one of the generated ninja files -
build.ninja:
=================================================
build bin\vtkzlib.dll bin\vtkzlib.lib: C_SHARED_LIBRARY_LINKER__vtkzlib
Utilities\vtkzlib\CMakeFiles\vtkzlib.dir\adler32.obj <snip more OBJ files>
LANGUAGE_COMPILE_FLAGS = -tWM -Od
LINK_FLAGS = -tWM -lS:1048576 -lSc:4098 -lH:1048576 -lHc:8192 -v
LINK_LIBRARIES = import32.lib
POST_BUILD = cd .
PRE_LINK = cd .
TARGET_FILE = bin\vtkzlib.dll
TARGET_IMPLIB = bin\vtkzlib.lib
TARGET_PDB = vtkzlib.dll.dbg
=================================================
And the corresponding ninja rule:
=================================================
rule C_SHARED_LIBRARY_LINKER__vtkzlib
command = cmd.exe /C "$PRE_LINK &&
C:\PROGRA~2\Borland\CBUILD~1\Bin\bcc32.exe -tWR -tW- -tWD -e$TARGET_FILE
$LINK_FLAGS $LINK_PATH $LINK_LIBRARIES $in && implib -c -w $TARGET_IMPLIB
$TARGET_FILE && $POST_BUILD"
description = Linking C shared library $TARGET_FILE
restat = $RESTAT
=================================================
Notice POST_BUILD and PRE_LINK variables don't change directory to something
else. What I think will work around this bcc32 design flaw is if it can do
something like:
POST_BUILD = cd ..\..
PRE_LINK = cd Utilities\vtkzlib
(Or alternatively, cd to absolute paths like the NMake JOM example below).
And of course, adjust the relative paths in other parameters to the build rule
To contrast, NMake JOM generator has it right in order to work around this
bcc32 issue - notice we change directory to a target-specific directory before
linking, and then go back when done:
=================================================
Utilities\vtkzlib\CMakeFiles\vtkzlib.dir\build.make:
bin\vtkzlib.dll: Utilities\vtkzlib\CMakeFiles\vtkzlib.dir\adler32.obj
<snip more OBJ files>
bin\vtkzlib.dll: Utilities\vtkzlib\CMakeFiles\vtkzlib.dir\build.make
<snip CMake progress command>
cd
C:\Users\JamesJ\Documents\Repositories\SuperRepo\VTK-JOM\Utilities\vtkzlib
C:\PROGRA~2\Borland\CBUILD~1\Bin\bcc32.exe -tWR -tW- -tWD @<<
-e..\..\bin\vtkzlib.dll -tWM -lS:1048576 -lSc:4098 -lH:1048576 -lHc:8192 -v
import32.lib $(vtkzlib_OBJECTS) $(vtkzlib_EXTERNAL_OBJECTS) <<
implib -c -w ..\..\bin\vtkzlib.lib ..\..\bin\vtkzlib.dll
cd C:\Users\JamesJ\Documents\Repositories\SuperRepo\VTK-JOM
=================================================
For what it's worth, at this time, I think this issue is limited to the linker
and not to the single-unit compilation of a CPP file to OBJ file. I ran Process
Monitor for a few seconds while VTK was compiling, and it seems that the only
file writes to the build tree were either legitimate writes to named
intermediate/output files, or else to these problematic files from the linker.
======================================================================
Issue History
Date Modified Username Field Change
======================================================================
2015-06-17 11:37 James Johnston New Issue
======================================================================
More information about the cmake-developers
mailing list