[CMake] Ninja race condition compiling VTK with Borland bcc32 compiler

James Johnston JamesJ at motionview3d.com
Mon Jun 15 14:56:06 EDT 2015


Hi,

While newer VTK versions seem to have forgone support for the C++ Builder
compiler, we still have code that extensively uses both VTK 5.4.2 and
proprietary C++ Builder features (including its runtime library, the VCL).
I am seeking to improve build performance of VTK in this situation by using
Ninja.  Using the Borland Makefiles generator in CMake works fine, except
that Borland Make itself has no parallelism and thus the build takes a
lengthy time period.  So I want to find another generator and Ninja looks
promising.

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 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.  While this constitutes eye-bleeding sadness on bcc32's
part, I'd still like to get this working by having the linkers run in
target-specific directories.

And so my question: is there a way to make the Ninja generator use
target-specific current directories when calling the linker to work around
this? 

The NMake JOM generator seems to work around this by changing directory to
target-specific directories; however, the ninja generator does not.  And so,
Ninja with only one thread (i.e. "ninja -j 1") works fine, but the default
configuration ("ninja" == "ninja -j10" on my system) gives me errors.  For
example:

=================================================
[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'
=================================================

My configuration:
 * Windows 7 64-bit on a quad-core hyperthreaded CPU
 * VTK 5.4.2, checked out from the appropriately tagged Git commit
 * CMake 3.3.0-rc1, Kitware-provided Windows binary
 * Ninja v1.5.3, built from source using Visual C++ 2008 Express.
 * C++ Builder 5 Update 1
 * I configure VTK in CMake GUI as follows: CMAKE_BUILD_TYPE=RelWithDebInfo,
VTK_REMOVE_LEGACY=ON, BUILD_TESTING=OFF, BUILD_SHARED_LIBS=ON

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.

Best regards,

James Johnston




More information about the CMake mailing list