[vtk-developers] New VTK directory structure and build process (bug fix).
Sebastien BARRE
seb-ml-vtk at barre.nom.fr
Mon May 7 23:08:35 EDT 2001
Hi
Here is some more feedback. More bugs were found (or maybe design flaws...
or just "features" :) ?). Some were fixed. Nothing was committed to the
CVS. Please tell me what do you want me to commit (including the previous
email).
Once again, the new tree is very nice :), and cmake looks promising. Great
work.
Windows build :
My conf :
- Windows 2000 SP1 (Athlon 800 MHz, 300 RAM)
- Tcl 8.3
- Python 2.0
- Microsoft Visual C++ 6
VTK_USE_PARALLEL and VTK_WRAP_JAVA were OFF. Everything else was "ON".
Cmake:
________
cmake*.exe was not found. I had to build the proper targets. No problem. Is
cmake*.exe going to be included in the source distrib (and CVS) like
pcmaker is ?
Note : it would be cool if the Cmake GUI could remember the path chosen in
the "Open File" dialog box.
The Build :
________
I generated the according MSVC++ DSP files, and started building VTK.
BTW, what's the difference between the "Release" and "Release MinSize"
settings ?
"Accidently" I forgot to set the BUILD_SHARED_LIBS flag => when I started
MSVC, the default target was "ALL_BUILD - Win32 Release MinSize" (the two
others were "ALL_BUILD - Win32 Debug" and "ALL_BUILD - Win32 Release"),
which looked fine because there was a "Win32 Release MinSize" setting for
all subtargets (Common, Filtering, Imaging, etc).
The build ran fin... but I was unable to find the .dll files.
Then I remembered how stupid I was and set BUILD_SHARED_LIBS to "On" =>
when I started MSVC again, it complained because the default target was
still "ALL_BUILD - Win32 Release MinSize" but there was *no* "Win32 Release
MinSize" setting anymore for the subtargets :(. Thus, I had to switch to
"Release"... and rebuild everything again :(
It failed on the first lib :
******************************
Linking...
Creating library Release/vtkCommon.lib and object Release/vtkCommon.exp
vtkOutputWindow.obj : error LNK2001: unresolved external symbol "public:
virtual void __thiscall vtkWin32OutputWindow::DisplayText(char const *)"
(?DisplayText at vtkWin32OutputWindow@@UAEXPBD at Z)
vtkOutputWindow.obj : error LNK2001: unresolved external symbol "public:
static class vtkWin32OutputWindow * __cdecl
vtkWin32OutputWindow::New(void)" (?New at vtkWin32OutputWindow@@SAPAV1 at XZ)
Release/vtkCommon.dll : fatal error LNK1120: 2 unresolved externals
******************************
Indeed vtkWin32OutputWindow was *not* compiled. I checked
vtknew/Common/CMakeLists.txt and found :
IF (WIN32)
SOURCE_FILES(LIBRARY_SRCS vtkWin32OutputWindow)
ENDIF (WIN32)
BUG : it has to be changed to :
IF (WIN32)
SOURCE_FILES(Common_SRCS vtkWin32OutputWindow)
ENDIF (WIN32)
... which solved that problem (already posted in my previous email).
The rest of the build worked fine.
Problem : at the end of the build, there was no single directory were the
DLLs could be found : each DLL file was stored in a different directory
(e.g., $BUILD_DIR/Common/Release, $BUILD_DIR/Filtering/Release,
$BUILD_DIR/Graphics/Release). This is a bit problematic as it implies that
each directory should be added to the PATH environment variable in order
the DLL to be found by the system. Nevertheless, I noticed that there is an
empty $BUILD_DIR/Release directory : I guess it would be good if all DLL
files were moved to this directory. This step might just be missing from
the correct Cmake configuration. I moved the DLLs manually, and added
$BUILD_DIR/Release to the PATH.
Note : I think a $BUILDIR/Lib/Release directory would be better, because
all builds (Release, Debug, Release MinSize) could be located under the
same $BUILDIR/Lib directory : less clutter.
Note : I could not find any settings to trigger a non-incremental build
(i.e. no single big vtkdll.dll file).
Tcl :
________
If VTK_USE_RENDERING is "On", then Cmake requires the internal path to
tkWinInt.h. The bundled file is v1.4. Mine is 1.7. Anyway, I tried with
mine (thus, overriding the TK_INTERNAL_PATH cache value, which was properly
found in the new tree anyway).
Correct me if I'm wrong, but it looks to me that all .cxx files are first
parsed/wrapped, then compiled (instead of being "parsed + compiled" one by
one).
The build failed :
******************************
Linking...
Creating library Release/vtkCommonTCL.lib and object
Release/vtkCommonTCL.exp
vtkTclUtil.obj : error LNK2001: unresolved external symbol
__imp__Tcl_DeleteCommand
vtkWindowLevelLookupTableTcl.obj : error LNK2001: unresolved external
symbol __imp__Tcl_DeleteCommand
[...]
Release/vtkCommonTCL.dll : fatal error LNK1120: 16 unresolved externals
Error executing link.exe.
ALL_BUILD - 737 error(s), 7 warning(s)
******************************
OK, this one is tricky. I might be completely wrong, but this is either a
bug or a design flaw. The Cmake documentation is a bit small at the moment
to understand every details.
Obviously, the previous step could not complete because the Tcl/Tk libs
were not linked.
Thus, I had a look at vtknew/CMakeLists.txt, and found that :
[...]
#
# get information for Tcl wrapping
#
OPTION(VTK_WRAP_TCL "wrap classes into the TCL intepreted language")
IF (VTK_WRAP_TCL)
INCLUDE (${CMAKE_SOURCE_DIR}/CMake/Modules/FindTCL.cmake)
# add in the Tcl values if found
IF (TCL_INCLUDE_PATH)
INCLUDE_DIRECTORIES(${TCL_INCLUDE_PATH})
ENDIF (TCL_INCLUDE_PATH)
IF (TCL_LIB_PATH)
LINK_DIRECTORIES (${TCL_LIB_PATH})
ENDIF (TCL_LIB_PATH)
IF (TCL_LIBRARY)
LINK_LIBRARIES (${TCL_LIBRARY})
ENDIF (TCL_LIBRARY)
[...]
Here we are. The Tcl lib is added to the link list only if the TCL_LIBRARY
variable is set.
When is it set ? In a single file (i.e. Cmake module),
vtknew\CMake\Modules\FindTCL.cmake, where there are blocks responsible for
detecting Tcl (or Tk) :
IF (NOT TCL_LIB_PATH)
FIND_LIBRARY(TCL_LIB_PATH tcl82 "C:/Program Files/Tcl/lib" /usr/lib
/usr/local/lib)
IF (TCL_LIB_PATH)
SET (TCL_LIBRARY tcl82 CACHE)
ENDIF (TCL_LIB_PATH)
ENDIF (NOT TCL_LIB_PATH)
Check the SET (TCL_LIBRARY tcl82 CACHE) line, which sets TCL_LIBRARY to
tcl82, and puts the value in the cache ($BUILDIR/CMakeCache.txt).
Two problems :
a) the Tcl/Tk version is hardcoded. To my opinion, this is bad :) In
pcmaker, we (well, mainly I, at the end :) tried to avoid that by asking
the user to enter the *full pathname* to the library (ex:
somepath/tclXX.lib). Then we found the version by extracting the 'XX'
string from the pathname. Hardcoding the version in Cmake means :
- the current Cmake obviously don't work with Tcl 8.3 (which has been a
user request for a long time :),
- the FindTcl.cmake file must be updated every time a new version major or
minor of Tcl arises :(,
- we must include all possible major+minor library versions :((, which
looks problematic to my knowledge, and I guess it is not specific to this rule.
Am I wrong ? I should add that I'm not familiar with Cmake at the moment.
b) I tried to solve the problem simply by adding a new block for the 8.3
version :
IF (NOT TCL_LIB_PATH)
FIND_LIBRARY(TCL_LIB_PATH tcl83 "C:/Program Files/Tcl/lib" /usr/lib
/usr/local/lib)
IF (TCL_LIB_PATH)
SET (TCL_LIBRARY tcl83 CACHE)
ENDIF (TCL_LIB_PATH)
ENDIF (NOT TCL_LIB_PATH)
This failed, for the following reason : the
IF (TCL_LIB_PATH)
SET (TCL_LIBRARY tcl83 CACHE)
ENDIF (TCL_LIB_PATH)
code is only executed (interpreted) if the test 'IF (NOT TCL_LIB_PATH)' is
true :(, this means that if TCL_LIB_PATH is manually set, it will never be
executed. And it is my case : my Tcl is not installed in a usual directory,
thus I *had* to set it manually in the Cmake GUI. As soon as I did that,
the test was false, and the TCL_LIBRARY was never set to a proper value (it
remains unset and does not appear in the cache file). Thus, the Tcl library
was not added to the link list :(
Nevertheless, I replaced the above code by :
IF (NOT TCL_LIB_PATH)
FIND_LIBRARY(TCL_LIB_PATH tcl83 "C:/Program Files/Tcl/lib" /usr/lib
/usr/local/lib)
ENDIF (NOT TCL_LIB_PATH)
IF (TCL_LIB_PATH)
SET (TCL_LIBRARY tcl83 CACHE)
ENDIF (TCL_LIB_PATH)
...rejecting the inner test outside the 'IF (NOT TCL_LIB_PATH)'.
This works, but of course this is NOT the right solution. The fact that
TCL_LIB_PATH is set does not mean that it is set to a 8.3 version at the
moment. Anyway, I needed the TCL_LIBRARY variable to be set in the cache,
hence this workaround is OK at the moment (albeit stupid :).
I do not know anything about Cmake, hence I'm unable to suggest anything to
the CMake gurus :) I guess asking for a '*full pathname* to the lib'
instead of the 'pathname to the directory holding the lib' could help : if
there is some pattern-matching capabilities built into Cmake we could then
find the 'XX' version in 'somepath/tclXX.lib'.
Of course, same goes for Tk in FindTCL.cmake.
Good think, the Tk Render widgets are built correctly.
Python:
________
Cmake asks for the path to Python 2.1 lib :( Well, I know we all have been
asking for Python 2.x (did we ?), but isn't Python 2.1 not a bit too
"young" ? I mean, the official 2.1 release was 3 weeks ago... There is a
risk that important modules might not have been rebuilt/ported to Python
2.1 yet. For example, PyOpenGL has not. Yes I know, It's a piece of
cake to rebuild...but if I do not want to rebuild all my modules at the
moment :)
This would not have been a problem if, like pcmaker, Cmake would allow me
to use whatever version of Python. I did not find a way to achieve this :
once again (see Tcl above), it seems that the "Python 2.1" setting is
hardcoded. More seriously, not only is it hardcoded, but it's hardcoded in
each and every CMakeList.txt file, instead of being hardcoded in a single
Cmake rule (like FindTCL.cmake). I do not worry about that, I'm quite sure
CMake will include this feature soon or later, am I right ? ;) I guess it
would be very good if we could use at least whatever *minor* version of Python.
Moreover, it makes no sense to use Python 2.1 if the Tcl lib is < 8.3 (this
won't work). And as reported above, Tcl 8.3 is not supported by CMake at
the moment.
OK, I had to patch each CMakeLists.txt file, and replace all python21
strings with python20 (20 items replaced in 10 files).
The link failed :
******************************
Linking...
Creating library Release/vtkFilteringPython.lib and object
Release/vtkFilteringPython.exp
vtkCellLocatorPython.obj : error LNK2001: unresolved external symbol
_PyVTKClass_vtkLocatorNew
vtkColorTransferFunctionPython.obj : error LNK2001: unresolved external
symbol _PyVTKClass_vtkScalarsToColorsNew
[...]
Release/vtkFilteringPython.dll : fatal error LNK1120: 10 unresolved externals
Error executing link.exe.
ALL_BUILD - 28 error(s), 0 warning(s)
******************************
The Common lib is parsed correctly. The error is triggered while linking
the Filtering lib, which depends on Common. The 28 errors match exactly the
signatures of functions belonging to *abstract* classes stored in Common.
It appears that, although wrapped and compiled, the Common abstract classes
are not linked and stored in vtkCommonPython.lib (or dll). Thus, linking
Filtering fails. This is problematic. I was unable to find a solution.
Hope this helps.
More information about the vtk-developers
mailing list