blob: 89b7c22cdf8e7aaf785f4fc90c85e9005f9262e7 [file] [log] [blame]
# ------------------------------------------------------------------------------
# MADlib CMake Build Script
# ------------------------------------------------------------------------------
# -- Paths and MD5 hashes of third-party downloadable source code (third-party
# components needed only by specific ports are downloaded there) ------------
# For in-house testing, we might want to change the base URLs of code-hosting
# sites to something local
# "-DSOURCEFORGE_BASE_URL=http://test.local/projects"
set(SOURCEFORGE_BASE_URL "http://sourceforge.net/projects" CACHE STRING
"Base URL for Sourceforge projects. May be overridden for testing purposes.")
set(BITBUCKET_BASE_URL "https://bitbucket.org" CACHE STRING
"Base URL for Bitbucket projects. May be overridden for testing purposes.")
# Boost might not be present on the system (or simply too old). In this case, we
# download the following version (unless it is already present in
# ${CMAKE_CURRENT_BINARY_DIR}/third_party/downloads).
# It is also possible to specify an alternative path to the Boost tarball when
# running cmake:
# "-DBOOST_TAR_SOURCE=/path/to/boost_x_x_x.tar.gz"
set(BOOST_TAR_VERSION "1.46.1")
set(BOOST_TAR_MD5 341e5d993b19d099bf1a548495ea91ec)
string(REPLACE "." "_" _BOOST_TAR_VERSION_UNDERSCORES ${BOOST_TAR_VERSION})
set(BOOST_TAR "boost_${_BOOST_TAR_VERSION_UNDERSCORES}.tar.gz")
set(BOOST_URL "${SOURCEFORGE_BASE_URL}/boost/files/${BOOST_TAR}")
if(NOT BOOST_TAR_SOURCE)
find_file(BOOST_TAR_SOURCE ${BOOST_TAR}
PATHS ${MAD_THIRD_PARTY}/downloads)
endif(NOT BOOST_TAR_SOURCE)
if(NOT BOOST_TAR_SOURCE)
set(BOOST_TAR_SOURCE ${BOOST_URL})
endif (NOT BOOST_TAR_SOURCE)
# We always download Eigen (unless it is already present in
# ${CMAKE_CURRENT_BINARY_DIR}/third_party/downloads). It is also possible to
# specify an alternative path to the Eigen tarball:
# -DEIGEN_TAR_SOURCE=/path/to/eigen-x.x.x.tar.gz
set(EIGEN_VERSION "3.0.3")
set(EIGEN_TAR_MD5 695f24be85c4fe957ce6a4dd11161f48)
set(EIGEN_TAR "eigen-${EIGEN_VERSION}.tar.gz")
set(EIGEN_URL "${BITBUCKET_BASE_URL}/eigen/eigen/get/${EIGEN_VERSION}.tar.gz")
set(EIGEN_SVN "${BITBUCKET_BASE_URL}/eigen/eigen/tags/${EIGEN_VERSION}")
if(NOT EIGEN_TAR_SOURCE)
find_file(EIGEN_TAR_SOURCE ${EIGEN_TAR}
PATHS ${MAD_THIRD_PARTY}/downloads)
endif(NOT EIGEN_TAR_SOURCE)
if(NOT EIGEN_TAR_SOURCE)
set(EIGEN_TAR_SOURCE ${EIGEN_URL})
endif (NOT EIGEN_TAR_SOURCE)
# -- Paths for madpack third-party components (those that are used by multiple
# ports) --------------------------------------------------------------------
# For in-house testing, we might want to change the base URL to something local
# "-DPYPI_BASE_URL=http://test.local/projects"
set(PYPI_BASE_URL "http://pypi.python.org/packages/source" CACHE STRING
"Base URL for projects from the Python Package Index. May be overridden for testing purposes.")
set(PYGRESQL_TAR_VERSION "4.0")
set(PYGRESQL_TAR_MD5 1aca50e59ff4cc56abe9452a9a49c5ff)
set(PYGRESQL_TAR "PyGreSQL-${PYGRESQL_TAR_VERSION}.tar.gz")
set(PYGRESQL_URL "${PYPI_BASE_URL}/P/PyGreSQL/${PYGRESQL_TAR}")
if(NOT PYGRESQL_TAR_SOURCE)
find_file(PYGRESQL_TAR_SOURCE ${PYGRESQL_TAR}
PATHS ${MAD_THIRD_PARTY}/downloads)
endif(NOT PYGRESQL_TAR_SOURCE)
if(NOT PYGRESQL_TAR_SOURCE)
set(PYGRESQL_TAR_SOURCE ${PYGRESQL_URL})
endif (NOT PYGRESQL_TAR_SOURCE)
# -- Local definitions (filenames, paths, etc.) --------------------------------
set(MAD_PATCH_DIR ${CMAKE_CURRENT_BINARY_DIR}/patch)
set(MAD_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/modules)
# ==============================================================================
# From here on, modifications should rarely be necessary.
# In other words: Be careful when you make changes. You have been warned. Don't
# try this at home.
# ==============================================================================
# -- Third-party dependencies: Find or download Boost --------------------------
find_package(Boost 1.46)
# We use BOOST_ASSERT_MSG, which only exists in Boost 1.46 and later.
# Unfortunately, the FindBoost module seems to be broken with respect to version
# checking, so we will set Boost_FOUND to FALSE if the version is too old.
if(Boost_FOUND)
if(Boost_VERSION LESS 104600)
set(Boost_FOUND FALSE)
endif(Boost_VERSION LESS 104600 )
endif(Boost_FOUND)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
else(Boost_FOUND)
message(STATUS "No sufficiently recent version (>= 1.46) of Boost was found. Will download.")
ExternalProject_Add(EP_boost
PREFIX ${MAD_THIRD_PARTY}
DOWNLOAD_DIR ${MAD_THIRD_PARTY}/downloads
URL ${BOOST_TAR_SOURCE}
URL_MD5 ${BOOST_TAR_MD5}
CMAKE_COMMAND /usr/bin/env echo Ignored: cmake
BUILD_COMMAND /usr/bin/env echo Ignored: make
INSTALL_COMMAND /usr/bin/env echo Ignored: make
BINARY_DIR ${MAD_THIRD_PARTY}/src/EP_boost
)
include_directories(BEFORE ${MAD_THIRD_PARTY}/src/EP_boost)
endif(Boost_FOUND)
# -- Third-party dependencies: Download the C++ linear-algebra library Eigen ---
string(REGEX MATCH "^[a-zA-Z]+" _EIGEN_PROTOCOL ${EIGEN_TAR_SOURCE})
if(_EIGEN_PROTOCOL STREQUAL "https")
# FIXME: This is somewhat ugly
# Unfortunately, CMake does not come with SSL support for file downloads.
# See: http://www.cmake.org/pipermail/cmake/2009-November/thread.html#33589
# Bitbucket on the other hand only provides SSL downloads
# We therefore assume that a "https" protocol refers to a SVN repository
set(_EIGEN_SOURCE
SVN_REPOSITORY ${EIGEN_SVN} UPDATE_COMMAND /usr/bin/env echo Ignored: svn update
)
else(_EIGEN_PROTOCOL STREQUAL "https")
set(_EIGEN_SOURCE
URL ${EIGEN_TAR_SOURCE} URL_MD5 ${EIGEN_TAR_MD5}
)
endif(_EIGEN_PROTOCOL STREQUAL "https")
# FIXME: Eigen is a third-party source that is patched in-place. Other
# third-party headers are patched in the patch directory.
ExternalProject_Add(EP_eigen
PREFIX ${MAD_THIRD_PARTY}
DOWNLOAD_DIR ${MAD_THIRD_PARTY}/downloads
${_EIGEN_SOURCE}
PATCH_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/patch/Eigen.sh"
CMAKE_COMMAND /usr/bin/env echo Ignored: cmake
BUILD_COMMAND /usr/bin/env echo Ignored: make
INSTALL_COMMAND /usr/bin/env echo Ignored: make
BINARY_DIR ${MAD_THIRD_PARTY}/src/EP_eigen
)
include_directories(${MAD_THIRD_PARTY}/src/EP_eigen)
# -- Macros to be used by ports ------------------------------------------------
# Get the architectures in a Mac OS X binary
macro(osx_archs FILENAME OUT_ARCHS)
execute_process(
COMMAND /usr/bin/lipo -info ${FILENAME}
OUTPUT_VARIABLE _LIPO_OUTPUT)
string(REPLACE "\n" "" _LIPO_OUTPUT ${_LIPO_OUTPUT})
string(REGEX REPLACE ".*:[ ]*([^ ].*[^ ])[ ]*\$" "\\1" ${OUT_ARCHS} "${_LIPO_OUTPUT}")
string(REPLACE " " ";" ${OUT_ARCHS} ${${OUT_ARCHS}})
endmacro(osx_archs)
# Add Python files to be preprocessed with m4
macro(add_python_files OUT_PYTHON_TARGET_FILES IN_SOURCE_DIR IN_TARGET_DIR)
set(IN_M4_ARGUMENTS ${ARGN})
get_filename_component(SOURCE_DIR_ABS "${IN_SOURCE_DIR}" ABSOLUTE)
get_filename_component(TARGET_DIR_ABS "${IN_TARGET_DIR}" ABSOLUTE)
file(GLOB_RECURSE PYTHON_FILES
RELATIVE "${SOURCE_DIR_ABS}"
"${SOURCE_DIR_ABS}/*.py_in"
)
set(MADLIB_PYTHON_M4_PREPROCESSING
COMMAND ${CMAKE_COMMAND} -E make_directory "\"\${OUTDIR}\""
COMMAND ${M4_BINARY} ${M4_ARGUMENTS} ${IN_M4_ARGUMENTS}
"\"\${CURRENT_PATH}\"" > "\"\${OUTFILE}\""
)
batch_add_command(
TARGET_PREFIX "${TARGET_DIR_ABS}/"
SOURCE_PREFIX "${SOURCE_DIR_ABS}/"
TARGET_SUFFIX ".py"
SOURCE_SUFFIX "[.]py_in"
RUN "${MADLIB_PYTHON_M4_PREPROCESSING}"
COMMENT "Preprocessing \${CURRENT_FILE} with m4."
TARGET_FILE_LIST_REF ${OUT_PYTHON_TARGET_FILES}
SOURCE_FILE_LIST ${PYTHON_FILES}
)
endmacro(add_python_files)
# Add sql files to be copied
macro(add_sql_files OUT_SQL_TARGET_FILES IN_SOURCE_DIR IN_TARGET_DIR)
get_filename_component(SOURCE_DIR_ABS "${IN_SOURCE_DIR}" ABSOLUTE)
get_filename_component(TARGET_DIR_ABS "${IN_TARGET_DIR}" ABSOLUTE)
file(GLOB_RECURSE SQL_FILES
RELATIVE "${SOURCE_DIR_ABS}"
"${SOURCE_DIR_ABS}/*.sql_in"
)
# psql of PostgreSQL < 9 does not like byte-order marks
set(_MADLIB_VERIFY_AND_COPY_COMMAND
COMMAND "${CMAKE_SOURCE_DIR}/cmake/TestIfNoUTF8BOM.py" "\"\${CURRENT_PATH}\""
COMMAND "${CMAKE_COMMAND}" -E copy "\"\${CURRENT_PATH}\"" "\"\${OUTFILE}\""
)
batch_add_command(
TARGET_PREFIX "${TARGET_DIR_ABS}/"
SOURCE_PREFIX "${SOURCE_DIR_ABS}/"
TARGET_SUFFIX ""
SOURCE_SUFFIX ""
RUN "${_MADLIB_VERIFY_AND_COPY_COMMAND}"
COMMENT "Validating and copying \${CURRENT_FILE}."
TARGET_FILE_LIST_REF ${OUT_SQL_TARGET_FILES}
SOURCE_FILE_LIST ${SQL_FILES}
)
endmacro(add_sql_files)
# Add a connector library for a specific DBMS port
macro(add_madlib_connector_library IN_TARGET_NAME IN_LIB_DIR IN_LIB_LOADER)
set(IN_LIBRARY_SOURCES ${ARGN})
add_library(
${IN_TARGET_NAME}
MODULE
${IN_LIBRARY_SOURCES}
)
add_dependencies(${IN_TARGET_NAME} EP_eigen)
set_target_properties(${IN_TARGET_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${IN_LIB_DIR}"
OUTPUT_NAME "madlib"
BUILD_WITH_INSTALL_RPATH YES
)
if(APPLE)
set_target_properties(${IN_TARGET_NAME} PROPERTIES
LINK_FLAGS "-bundle_loader \"${IN_LIB_LOADER}\"")
endif(APPLE)
endmacro(add_madlib_connector_library)
# -- Speciy files that will be compiled into MADlib core library ---------------
# FIXME: The CMake description of file(GLOB ...) says:
# "We do not recommend using GLOB to collect a list of source files from your
# source tree. If no CMakeLists.txt file changes when a source is added or
# removed then the generated build system cannot know when to ask CMake to
# regenerate."
# We still use GLOB here because we think the benefits outweigh the mentioned
# disadvantage.
file(GLOB_RECURSE MAD_CPP_SOURCES
dbal/*.hpp
modules/*.cpp modules/*.hpp
utils/*.hpp
)
list(APPEND MAD_SOURCES
${MAD_CPP_SOURCES}
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if(CMAKE_COMPILER_IS_GNUCXX)
if(GNUCXX_VERSION VERSION_GREATER 4.4 OR GNUCXX_VERSION VERSION_EQUAL 4.4)
if(_AUTOINCLUDE_LIBSTDCXX)
# FIXME: The following only takes care of the symbolic link
# Need to implement copying of files containing version numbers in
# file name
# Both CentOS/RH 5 ship with old versions of libstdc++
# Starging with gcc 4.4, C++ code may therefore not run any more on
# vanilla installations of CentOS/RH 5. We therefore include libstdc++
# in this case and install it in $MADLIB_ROOT/lib
set(_LIBSTDCXX_FILENAME
"${CMAKE_SHARED_LIBRARY_PREFIX}stdc++${CMAKE_SHARED_LIBRARY_SUFFIX}")
execute_process(
COMMAND ${CMAKE_C_COMPILER}
"-print-file-name=${_LIBSTDCXX_FILENAME}"
OUTPUT_VARIABLE _LIBSTDCXX_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE)
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/lib/${_LIBSTDCXX_FILENAME}"
COMMAND "${CMAKE_COMMAND}" -E copy ${_LIBSTDCXX_PATH}
"${CMAKE_CURRENT_BINARY_DIR}/lib/${_LIBSTDCXX_FILENAME}"
COMMENT "Copying libstdc++ to lib directory."
)
add_custom_target(copyLibStdCXX ALL DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/lib/${_LIBSTDCXX_FILENAME}")
endif(_AUTOINCLUDE_LIBSTDCXX)
# Also install it
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
DESTINATION .
COMPONENT core
FILES_MATCHING REGEX "^.*/[^/]*stdc\\+\\+[^/]*\$"
)
endif(GNUCXX_VERSION VERSION_GREATER 4.4 OR GNUCXX_VERSION VERSION_EQUAL 4.4)
endif(CMAKE_COMPILER_IS_GNUCXX)
# -- Preprocess/copy all Python/SQL files --------------------------------------
add_python_files(
PYTHON_TARGET_FILES
"modules"
"${CMAKE_CURRENT_BINARY_DIR}/modules"
)
add_custom_target(pythonFiles ALL DEPENDS ${PYTHON_TARGET_FILES})
add_sql_files(
SQL_TARGET_FILES
"modules"
"${CMAKE_CURRENT_BINARY_DIR}/modules"
)
add_custom_target(sqlFiles ALL DEPENDS ${SQL_TARGET_FILES})
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules
DESTINATION .
COMPONENT core
REGEX "^(.*/)?\\.DS_Store\$" EXCLUDE
)
# -- Use all necessary patches directory ---------------------------------------
include_directories(BEFORE "${MAD_PATCH_DIR}")
# -- Add subdirectories --------------------------------------------------------
add_subdirectory(patch)
add_subdirectory(bin)
add_subdirectory(config)
add_subdirectory(madpack)
add_subdirectory(ports)