FennelBuildSystem
From Eigenpedia
Contents |
Overview
This page describes the workings of the Fennel build. It is intended as a guide for anyone who needs to use, maintain or enhance the build system.
On Linux, both 32-bit and 64-bit builds are supported. For 64-bit machines which support both build environments, see Fennel64Bit#Build Machine Setup Notes.
For Windows 32-bit builds, see also WindowsBuildSetup.
Mac OS X builds as of Fennel 0.9.3 (so far tested with Snow Leopard; see FennelPlatformsOSX).
No other platforms are supported yet (see #Future Work).
If you are building Fennel as part of Farrago or LucidDB, follow the corresponding top-level build instructions instead; however, you should still read through this page to make sure you have the necessary build tools available, and for debugging the build if anything goes wrong.
Toolchain Dependencies
The build system is based on cmake. At least cmake 2.6 is required; you can find the documentation here.
Older Fennel versions used autotools (autoconf/automake/libtool) instead, but those had to be abandoned when we moved the Windows build from mingw gcc to Microsoft Visual C++ (MSVC).
Additional tools:
- bison
- flex
- on Linux: g++ toolchain (at least 4.1.x; there are currently some problems with 4.3.2)
- on Windows: MSVC 2008 Express
- on Windows: Cygwin for shell scripting support, bison, flex, etc
- NOTE: We use Cygwin for the build, but NOT for runtime! In the past, we used mingw for the runtime, but no longer; now it is just bare Windows.
- on OSX: MacPorts provides cmake, bison, flex, gawk (for tests), etc. XCode from Apple provides gcc/g++ etc
On Ubuntu, you can install cmake with apt-get install cmake. Run cmake --version and make sure it is at least 2.6; if it is older, do apt-get remove cmake and then (still as root):
wget http://www.cmake.org/files/v2.6/cmake-2.6.3.tar.gz tar xzf cmake-2.6.3.tar.gz cd cmake-2.6.3 ./bootstrap make make install
Or download an architecture-specific binary (e.g. cmake-2.6.3-Linux-i386.tar.gz) from the cmake download site.
initBuild.sh script
When building in a new sandbox, the initial build must run certain one-time steps in order to perform activities such as generating Makefiles. This is encapsulated by the initBuild.sh script.
initBuild can also be re-run later in an existing sandbox in order to rebuild everything from clean.
Options:
- --with[out]-farrago: Controls whether to build the JNI glue code needed for integrating Fennel into the companion Farrago (Java) project. If --with-farrago is specified, the JAVA_HOME environment variable must be defined so that JNI includes can be found.
- --with[out]-optimization: See FennelBuildVariations.
- --with[out]-debug: See FennelBuildVariations.
- --without-thirdparty-build: Controls whether thirdparty components such as STLport and Boost should be (re)built too.
- --with[out]-tests: Controls whether tests are run as part of the build.
- --with[out]-aio-required: Controls whether libaio is treated on mandatory on Linux.
The initBuild script works as follows:
- Parse the command-line options
- If needed, unpack thirdparty components needed by Fennel
- Clean out any cached cmake information to make sure the build starts from scratch
- Run cmake to generate Makefiles, passing down flags via command-line parameters such as OPT_FLAG=--with-optimization
- Windows only: see #Windows Hacks below
- Unless --without-thirdparty-build is specified: build STLport and boost by invoking the scripts build/buildStlportLibs.sh and build/buildBoostLibs.sh
- make clean
- (On Windows, nmake is used instead of make)
- make all
- If --with-tests is specified: make check to run all tests
The generated Makefiles are capable of automatically re-running cmake as needed after any CMakeLists.txt script is edited.
Thirdparty Library Dependencies
Fennel depends on STLport and Boost. If you are working from a full Eigenbase source distribution, the correct versions are already available in the thirdparty directory (a sibling of the fennel directory). If you are working from a Fennel-only source distribution, you'll need to download the source distributions for these libraries independently, create a thirdparty directory in the correct location, and unpack them there.
CMakeLists.txt
CMakeLists.txt contains the directives which control how cmake generates Makefiles (similar to Makefile.am for automake).
The top-level file has directives for the following:
- include needed cmake modules (e.g. CTest for running tests)
- check flags passed down from initBuild.sh and configure compiler and linker options accordingly
- check existence of necessary headers (e.g. libaio.h) and libraries (e.g. uuid)
- generate non-Makefiles needed at build-time such as fennelenv.sh and config.h
- process component subdirectories (each of which contains its own CMakeLists.txt)
- define custom Makefile targets check, checkPreambles, tags, emacs_cscope, and cscope
Subdirectory builds can be classified as follows:
- components (btree, cache, calculator, common, db, device, exec, flatfile, ftrs, hashexe, segment, sorter, synch, tuple, txn): these build object files from sources, but do not build any DLLs
- non-JNI DLL builds (libfennel, lucidera/libfennel_lu): these build DLL's from components
- JNI DLL builds (farrago, lucidera/farrago): these build JNI DLL's which glue additional code on top of component DLL's
- tests (test, calctest, lucidera/test): these build test libraries and unit test executables
- util: utility program executables
Dependencies between components are described in the library overview (slightly out-of-date, but the principles hold).
In some cases (e.g. common+synch), multiple components are rolled into a single DLL.
Generated Makefiles
The generated makefiles take care of standard needs such as header file dependencies automatically. They also support parallel make (e.g. make -j 2).
By default, the make output is a terse progress report:
jvs@bagheera:~/open/tpu/fennel$ make Scanning dependencies of target common [ 0%] Building CXX object common/CMakeFiles/common.dir/Backtrace.cpp.o [ 0%] Building CXX object common/CMakeFiles/common.dir/BernoulliRng.cpp.o [ 0%] Building CXX object common/CMakeFiles/common.dir/ByteArrayInputStream.cpp.o [ 1%] Building CXX object common/CMakeFiles/common.dir/ByteArrayOutputStream.cpp.o ...
To get details such as compiler options, use VERBOSE=1:
jvs@bagheera:~/open/tpu/fennel$ VERBOSE=1 make [ 1%] Building CXX object common/CMakeFiles/common.dir/ByteArrayOutputStream.cpp.o cd /home/jvs/open/tpu/fennel/common && /usr/bin/c++ -DFENNEL_COMMON_EXPORTS -pipe -ftemplate-depth-64 -Wall -Wno-unused-parameter -Wno-unused -Wno-sign-compare -Werror -DHAVE_CONFIG_H -D_REENTRANT -D_STLP_USE_DYNAMIC_LIB=1 -D_STLP_NO_ANACHRONISMS=1 -DBOOST_NO_HASH=1 -DLITTLEENDIAN -D_STLP_DEBUG=1 -D_STLP_DEBUG_UNINITIALIZED=1 -DDEBUG -g -fPIC -DPIC -g -I/home/jvs/open/tpu/thirdparty/stlport/stlport -I/home/jvs/open/tpu/thirdparty/boost -I/home/jvs/open/tpu/fennel -I/home/jvs/open/tpu/fennel/.. -o CMakeFiles/common.dir/ByteArrayOutputStream.cpp.o -c /home/jvs/open/tpu/fennel/common/ByteArrayOutputStream.cpp ...
Windows Build Hacks
On Windows, a few hacks are needed to deal with cmake limitations.
The first one is based on this cmake FAQ entry for how to create convenience libraries. On Linux, we just use the -whole-archive approach, but that doesn't work on Windows, so there, we use the hack described here for both. This is implemented in macros generate_obj_list and generate_subdir_obj_list.
The second one compensates for some other cmake problem arising from the first hack (again, Windows only). For some reason, cmake 2.6.2 and up thinks all the FileName.cpp.obj files should already exist even before the build starts. To fix this, the macros above touch the file locations (creating 0-sized files) to satisfy the dependency checks; afterwards, initBuild.sh deletes them before running nmake (otherwise the linker would complain about corrupted object files).
--Jvs 23:41, 15 April 2009 (EDT): If anyone can figure out a better solution for this, please let me know! Currently, this hack makes the Windows build environment less usable.
Windows DLL Exports
On Windows, it is necessary for each DLL to declare which symbols it exports, and for referencing DLLs to declare corresponding imports. We define one compiler macro per module for this purpose, and use it to decorate definitions in .h files (usually classes), e.g.
class FENNEL_DEVICE_EXPORT RandomAccessFileDevice : public RandomAccessDevice, public FileDevice
On non-Windows platforms, the FENNEL_DEVICE_EXPORT macro expands to an empty string. On Windows, it is defined conditionally as follows:
#ifdef FENNEL_DEVICE_EXPORTS #define FENNEL_DEVICE_EXPORT __declspec(dllexport) #else #define FENNEL_DEVICE_EXPORT __declspec(dllimport) #endif
The pluralized macro FENNEL_DEVICE_EXPORTS is defined in device/CMakeLists.txt:
add_definitions(-DFENNEL_DEVICE_EXPORTS)
This causes it to be enabled for building the device DLL, resulting in dllexport; when the code for other DLLs is built, dllimport is used instead.
If you forget to decorate a class definition, the build will work fine on Linux, but it will fail on Windows. (--Jvs 00:01, 16 April 2009 (EDT): Can anyone think of a way to make it fail on Linux too?)
Class definitions take care of most exports, but free functions need special treatment, e.g.
extern void FENNEL_COMMON_EXPORT hexDump(
std::ostream &,void const *,uint cb,
uint cbOffsetInitial = 0);
NOTE: Do not decorate template class definitions! The mechanism used for expanding templates and resolving duplicates is different from the non-template resolution mechanism.
Template Instance Inheritance Special Case
A messy special-case arises because of the way the tuple library defined classes such as TupleProjection : public std::vector<uint>.
The export rules say that if a derived class extends a base class, the base class methods are automatically exported as well. However, we need this to happen in a specific module, otherwise we end up with duplicate (conflicting) exports from different modules, leading to linker errors. The solution is to introduce class FENNEL_COMMON_EXPORT VectorOfUint : public std::vector<uint>; then anywhere we would normally use std::vector<uint>, we use VectorOfUint instead.
Tests
Fennel unit tests are based on the Boost test library, but when run as a batch, they are registered and invoked from the build via ctest (a companion to cmake).
Before running tests (whether individually or batch), you must modify your environment so that shared libraries can be found. The build automatically generates a script for this purpose; invoke it with either . or source:
$ source fennelenv.sh
The top-level make check target invokes ctest and tells it to run all unit tests:
jvs@bagheera:~/open/tpu/fennel$ make check UpdateCTestConfiguration from :/home/jvs/open/tpu/fennel/DartConfiguration.tcl Parse Config file:/home/jvs/open/tpu/fennel/DartConfiguration.tcl Start processing tests UpdateCTestConfiguration from :/home/jvs/open/tpu/fennel/DartConfiguration.tcl Parse Config file:/home/jvs/open/tpu/fennel/DartConfiguration.tcl Test project /home/jvs/open/tpu/fennel Constructing a list of tests Done constructing a list of tests Changing directory into /home/jvs/open/tpu/fennel/test 1/ 67 Testing ExternalSortExecStreamTest Test command: /home/jvs/open/tpu/fennel/test/ExternalSortExecStreamTest Test timeout computed to be: 1500 Running 7 test cases... *** No errors detected -- Process completed Passed 2/ 67 Testing FlatFileExecStreamTest ...
CMakeLists.txt contains directives for generating the necessary CTestTestfile.cmake and DartConfiguration.tcl files. You can run the ctest executable directly for more control over how tests are run.
Windows Test Runner Problems
- Currently, most Fennel unit tests on Windows encounter a crash at the very end as the process is exiting (after Boost has already reported "No errors detected"). No one has debugged this one yet.
- Also on exit, some tests also encounter memory leak notifications on Windows, probably bogus. These can be suppressed with export BOOST_TEST_DETECT_MEMORY_LEAK=0.
Future Work
- OpenSolaris port
-
MacOS X port [FNL-85] - Visual C++ IDE and debugger workspace
- 64-bit Windows port [FNL-87]
- Improvements noted in FennelBuildVariations
- Use cpack to build .rpm, .deb, ...
- resurrect ICU support as part of Unicode-enabling the Fennel calculator
- see if we can use the MODULE library type (instead of SHARED) to get rid of some old mystery hacks: explicit dlopen (in JNI_OnLoad) and FENNEL_JNI_ONLOAD_COMMON, plus the companion AWT hack in org.eigenbase.util.Util.loadLibrary
- fix/suppress compiler warnings on Windows
- fix LucidDB development environment on Windows (sqlline and lucidDbServer scripts aren't working correctly)
- fix Windows test runner problems above
- make check should depend on test executables (this used to work with autotools); for now it's necessary to run make first before make check

