#******************************************************************************
#
# MantaFlow fluid solver framework
#
# Copyright 2011-2015 Tobias Pfaff, Nils Thuerey
#
# This program is free software, distributed under the terms of the
# GNU General Public License (GPL)
# http://www.gnu.org/licenses
#
#******************************************************************************
project (MantaFlow)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/source/cmake/")
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
SET(VERBOSE 1)
SET(MANTAVERSION "0.10a")
#******************************************************************************
# Default paths
# - CMake's path finder is completely useless for Qt5 + Python on Win64
# - allow override from command line on OsX, eg use "cmake .. -DCMAKE_PREFIX_PATH=/Users/someone/qt5.2.1/5.2.1/clang_64/
IF(WIN32)
SET(WIN_QT_PATH "C:/Qt/5.5/msvc2013_64_opengl") # qt5/win64
SET(WIN_PYTHON_PATH "C:/Python34")
SET(WIN_PYTHON_VERSION "34")
SET(CMAKE_LIBRARY_PATH "C:/Program Files (x86)/Windows Kits/8.0/Lib/win8/um/x64")
SET(CMAKE_PREFIX_PATH ${WIN_QT_PATH})
ENDIF()
IF(APPLE)
IF(NOT CMAKE_PREFIX_PATH)
SET(CMAKE_PREFIX_PATH "/usr/local/Cellar/qt5/5.5/") # mac/homebrew
#SET(CMAKE_PREFIX_PATH "/home/myname/qt/5.5/clang_64") # other...
ENDIF()
ENDIF()
#******************************************************************************
# setup default params
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
ELSE()
MESSAGE("Build-type: '${CMAKE_BUILD_TYPE}'")
ENDIF()
# compilation versions
OPTION(DEBUG "Enable debug compilation" OFF)
OPTION(GUI "Compile with GUI (requires QT)" OFF)
OPTION(TBB "Use multi-thread kernels using Intels TBB" OFF)
OPTION(OPENMP "Use multi-thread kernels using OpenMP" OFF)
OPTION(PREPDEBUG "Debug generated files" OFF) # This will beautify generated files, and link to them for compiler errors instead of the original sources
OPTION(DOUBLEPRECISION "Compile with double floating point precision" OFF)
# CUDA is deprecated, and not tested - enable at own risk... (needs cmake version >2.8)
#OPTION(CUDA "Compile with CUDA plugins" OFF)
# special option to compile manta as library, disables python glue code (while trying to keep as much of the rest as possible)
OPTION(NOPYTHON "Compile without python support (limited functionality!)" OFF)
#check consistency of MT options
SET(MT OFF)
SET(MT_TYPE "NONE")
if (TBB)
SET (MT_TYPE "TBB")
SET (MT ON)
endif()
if (OPENMP)
SET (MT_TYPE "OPENMP")
SET (MT ON)
endif()
if (TBB AND OPENMP)
message(FATAL_ERROR "Cannot activate both OPENMP and TBB")
endif()
# make sure debug settings match...
IF(NOT DEBUG)
IF(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
SET(DEBUG 1)
ENDIF()
ENDIF()
IF(DEBUG)
SET(CMAKE_BUILD_TYPE "Debug")
add_definitions ( -DDEBUG=1 )
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS "Options - "
" -DDEBUG='${DEBUG}' "
" -DGUI='${GUI}' "
" -DTBB='${TBB}' "
" -DOPENMP='${OPENMP}' "
" -DPREPDEBUG='${PREPDEBUG}' "
" -DDOUBLEPRECISION='${DOUBLEPRECISION}' "
)
# " -DCUDA='${CUDA}' "
MESSAGE(STATUS "Multithreading type : ${MT_TYPE}")
MESSAGE(STATUS "")
#******************************************************************************
# Pre-processor
# compile prep
SET(SOURCES
source/preprocessor/main.cpp
source/preprocessor/code.cpp
source/preprocessor/tokenize.cpp
source/preprocessor/parse.cpp
source/preprocessor/util.cpp
source/preprocessor/merge.cpp
source/preprocessor/codegen_python.cpp
source/preprocessor/codegen_kernel.cpp
)
add_executable(prep ${SOURCES})
if (NOT WIN32)
set_target_properties(prep PROPERTIES COMPILE_FLAGS "-Wall -O2")
endif()
#******************************************************************************
# Setup main project
SET(F_LIBS "" )
SET(F_LIB_PATHS)
SET(F_LINKADD "") # additional linker flags, not a list
set(PP_PATH "pp")
SET(SILENT_SOURCES)
# need pre-processing
SET(PP_SOURCES
source/general.cpp
source/fluidsolver.cpp
source/conjugategrad.cpp
source/grid.cpp
source/grid4d.cpp
source/levelset.cpp
source/fastmarch.cpp
source/shapes.cpp
source/mesh.cpp
source/particle.cpp
source/movingobs.cpp
source/fileio.cpp
source/noisefield.cpp
source/kernel.cpp
source/vortexsheet.cpp
source/vortexpart.cpp
source/turbulencepart.cpp
source/timing.cpp
source/edgecollapse.cpp
source/plugin/advection.cpp
source/plugin/extforces.cpp
source/plugin/flip.cpp
source/plugin/fire.cpp
source/plugin/kepsilon.cpp
source/plugin/initplugins.cpp
source/plugin/meshplugins.cpp
source/plugin/optflow4d.cpp
source/plugin/pressure.cpp
source/plugin/vortexplugins.cpp
source/plugin/waveletturbulence.cpp
source/plugin/waves.cpp
source/python/defines.py
source/test.cpp
)
SET(PP_HEADERS
source/general.h
source/commonkernels.h
source/conjugategrad.h
source/fastmarch.h
source/fluidsolver.h
source/grid.h
source/grid4d.h
source/mesh.h
source/particle.h
source/levelset.h
source/shapes.h
source/noisefield.h
source/vortexsheet.h
source/kernel.h
source/timing.h
source/movingobs.h
source/fileio.h
source/edgecollapse.h
source/vortexpart.h
source/turbulencepart.h
)
# no pre-processing needed
set(NOPP_SOURCES
source/pwrapper/pymain.cpp
source/pwrapper/pclass.cpp
source/pwrapper/pvec3.cpp
source/pwrapper/pconvert.cpp
source/pwrapper/registry.cpp
source/util/vectorbase.cpp
source/util/vector4d.cpp
source/util/simpleimage.cpp
)
SET(NOPP_HEADERS
source/pwrapper/pythonInclude.h
source/pwrapper/pclass.h
source/pwrapper/registry.h
source/pwrapper/pconvert.h
source/util/integrator.h
source/util/vectorbase.h
source/util/vector4d.h
source/util/quaternion.h
source/util/interpol.h
source/util/mcubes.h
source/util/randomstream.h
source/util/solvana.h
)
if (GUI)
# need QT preprocessor
set(QT_HEADERS
source/gui/mainwindow.h
source/gui/glwidget.h
source/gui/painter.h
source/gui/meshpainter.h
source/gui/qtmain.h
source/gui/customctrl.h
source/gui/particlepainter.h
)
set(QT_SOURCES
source/gui/customctrl.cpp
source/gui/mainwindow.cpp
source/gui/glwidget.cpp
source/gui/customctrl.cpp
source/gui/painter.cpp
source/gui/meshpainter.cpp
source/gui/particlepainter.cpp
source/gui/qtmain.cpp
)
list(APPEND PP_SOURCES ${QT_SOURCES})
list(APPEND PP_HEADERS ${QT_HEADERS})
endif()
# CUDA sources , deprectated
if (CUDA)
list(APPEND PP_SOURCES
source/cuda/meshtools.cu
source/cuda/buoyancy.cu
source/cuda/particle.cu
)
endif()
# include dirs
SET(INCLUDE_PATHS
${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/source
${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/source/util
source/pwrapper
source/cuda
source/util
)
# reduced version without python
if (NOPYTHON)
# replace some of the source lists
set(NOPP_SOURCES
source/nopython/pclass.cpp
source/util/vectorbase.cpp
source/util/simpleimage.cpp
)
# update paths to use nopython versions
SET(INCLUDE_PATHS
${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/source
${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/source/util
source/nopython
source/cuda
source/util
)
add_definitions( -DNOPYTHON=1 )
endif()
# Multithreading
if(MT)
add_definitions( -DMT=1 )
if(TBB)
# Intel TBB
add_definitions( -DTBB=1 )
if (DEBUG)
add_definitions( -DTBB_USE_DEBUG=1 )
list(APPEND F_LIBS tbb)
else()
list(APPEND F_LIBS tbb)
endif()
if (WIN32)
find_package(TBB REQUIRED)
list(APPEND INCLUDE_PATHS ${TBB_INCLUDE_DIRS})
list(APPEND F_LIB_PATHS ${TBB_LIBRARY_DIRS})
elseif(APPLE)
find_package(TBB REQUIRED)
list(APPEND INCLUDE_PATHS ${TBB_INCLUDE_DIRS})
list(APPEND F_LIB_PATHS ${TBB_LIBRARY_DIRS})
endif()
else()
# OpenMP
add_definitions( -DOPENMP=1 )
if (WIN32)
add_definitions( /openmp)
else()
add_definitions(-fopenmp)
SET(F_LINKADD "${F_LINKADD} -fopenmp ")
endif()
endif()
endif()
#******************************************************************************
# add a target to generate API documentation with Doxygen
find_package(Doxygen)
if(DOXYGEN_FOUND)
set(DX_PATH "doxy")
foreach(it ${PP_SOURCES} ${PP_HEADERS} ${NOPP_SOURCES} ${NOPP_HEADERS})
get_filename_component(CURPATH ${it} PATH)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${DX_PATH}/${CURPATH}")
set(CURDX "${DX_PATH}/${it}")
string(REPLACE "/" "_" TGT ${CURDX})
string(REPLACE "source/" "" INFILE ${it})
add_custom_command(OUTPUT ${TGT}
COMMAND prep docgen "0" ${MT_TYPE} "${CMAKE_CURRENT_SOURCE_DIR}/source/" "${INFILE}" "${CURDX}"
DEPENDS prep
IMPLICIT_DEPENDS CXX ${it}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
list(APPEND TGLIST ${TGT})
endforeach(it)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${TGLIST}
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
endif(DOXYGEN_FOUND)
#******************************************************************************
# Link libraries
# enforce certain python version, if necessary
set(PYTHON_FORCE_VERSION) # use any...
#set(PYTHON_FORCE_VERSION 3.5) # uncomment to force specific one
# Python
set(Python_ADDITIONAL_VERSIONS 3.4)
find_package(PythonLibs ${PYTHON_FORCE_VERSION} QUIET)
if((NOT PYTHONLIBS_FOUND) AND WIN32)
set(PYTHON_INCLUDE_DIR "${WIN_PYTHON_PATH}/include")
set(PYTHON_LIBRARY "${WIN_PYTHON_PATH}/libs/python${WIN_PYTHON_VERSION}.lib")
endif()
find_package(PythonLibs ${PYTHON_FORCE_VERSION} REQUIRED)
list(APPEND INCLUDE_PATHS ${PYTHON_INCLUDE_DIRS})
list(APPEND F_LIBS ${PYTHON_LIBRARIES})
# Z compression
if (1)
# default: build from own sources
set(ZLIB_SRC adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c
inflate.c infback.c inftrees.c inffast.c trees.c uncompr.c zutil.c)
foreach(it ${ZLIB_SRC})
list(APPEND SILENT_SOURCES dependencies/zlib-1.2.8/${it})
endforeach(it)
set(ZLIB_ADDFLAGS "-Dverbose=-1")
if(NOT WIN32)
set(ZLIB_ADDFLAGS "-Wno-implicit-function-declaration -Dverbose=-1")
endif()
set_source_files_properties(${SILENT_SOURCES} PROPERTIES COMPILE_FLAGS "${ZLIB_ADDFLAGS}")
list(APPEND INCLUDE_PATHS dependencies/zlib-1.2.8)
endif()
if (0)
# try to locate and use system libs
include(FindZLIB)
list(APPEND INCLUDE_PATHS ${ZLIB_INCLUDE_DIR})
list(APPEND F_LIBS ${ZLIB_LIBRARIES})
endif()
if (0)
# disable
add_definitions(-DNO_ZLIB=1)
endif()
# CUDA
if(CUDA)
add_definitions( -DCUDA=1 )
find_package(CUDA QUIET REQUIRED)
set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF)
# ? if (USE64) set(CUDA_64_BIT_DEVICE_CODE ON) endif()
if(WIN32)
if(DEBUG)
set(CUDA_NVCC_FLAGS -DDEBUG;--compiler-options;-Wall)
else()
set(CUDA_NVCC_FLAGS --use_fast_math;-DNDEBUG;--compiler-options;-Wall;-O2)
endif()
else()
# CUDA does not support gcc > 4.5 yet
if(DEBUG)
set(CUDA_NVCC_FLAGS --pre-include;/usr/local/include/undef_atomics_int128.h;-g;-DDEBUG;-keep;--maxrregcount=31;--compiler-options;-Wall)
else()
#set(CUDA_NVCC_FLAGS -ccbin;gcc-4.5;--use_fast_math;-arch=sm_20;-DNDEBUG;--compiler-options;-Wall;-O3)
set(CUDA_NVCC_FLAGS --pre-include;/usr/local/include/undef_atomics_int128.h;--use_fast_math;-DNDEBUG;--compiler-options;-Wall;-O3)
endif()
endif()
endif()
# increase FP precision?
if(DOUBLEPRECISION)
add_definitions(-DFLOATINGPOINT_PRECISION=2)
endif()
#******************************************************************************
# generate git repository info , currently only for unix systems
IF(NOT WIN32)
set(GITINFO "${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/source/gitinfo.h")
MESSAGE(STATUS "Git info target header ${GITINFO}")
add_custom_command(OUTPUT ${GITINFO}
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/getGitVersion.py" "${GITINFO}"
DEPENDS ${PP_SOURCES} ${PP_HEADERS} ${NOPP_SOURCES} ${NOPP_HEADERS} ${QT_SOURCES} ${QT_HEADERS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} )
ENDIF()
#******************************************************************************
# apply preprocessor
set(SOURCES ${NOPP_SOURCES} ${SILENT_SOURCES})
set(HEADERS ${NOPP_HEADERS})
set(PP_REGCPP)
set(PP_REGS)
set(PP_PREPD "0")
set(PREPPED_SOURCES)
if (PREPDEBUG)
set(PP_PREPD "1")
endif()
FOREACH(it ${PP_SOURCES} ${PP_HEADERS})
get_filename_component(CURPATH ${it} PATH)
get_filename_component(CUREXT ${it} EXT)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/${CURPATH}")
set(CURPP "${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/${it}")
string(REPLACE "source/" "" INFILE ${it})
set(OUTFILES "${CURPP}")
if ("${CUREXT}" STREQUAL ".h" OR "${CUREXT}" STREQUAL ".py")
IF(NOT NOPYTHON)
list(APPEND PP_REGS "${CURPP}.reg")
list(APPEND PP_REGCPP "${CURPP}.reg.cpp")
ENDIF()
set_source_files_properties("${CURPP}.reg.cpp" OBJECT_DEPENDS "${CURPP}")
list(APPEND OUTFILES "${CURPP}.reg")
ENDIF()
# preprocessor
add_custom_command(OUTPUT ${OUTFILES}
COMMAND prep generate ${PP_PREPD} ${MT_TYPE} "${CMAKE_CURRENT_SOURCE_DIR}/source/" "${INFILE}" "${CURPP}"
DEPENDS prep
IMPLICIT_DEPENDS CXX ${it}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_source_files_properties(${OUTFILES} PROPERTIES GENERATED 1)
list(APPEND PREPPED_SOURCES ${CURPP})
ENDFOREACH(it)
list(APPEND SOURCES ${PREPPED_SOURCES})
# link reg files , for python glue code
IF(NOT NOPYTHON)
add_custom_command(OUTPUT ${PP_REGCPP}
COMMAND prep link ${PP_REGS}
DEPENDS prep ${PP_REGS}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Linking reg files")
set_source_files_properties(${PP_REGCPP} PROPERTIES GENERATED 1)
list(APPEND SOURCES ${PP_REGCPP})
ENDIF()
#******************************************************************************
# QT for GUI
if(GUI)
# remap
set(QT_REMAP)
foreach(it ${QT_HEADERS})
list(APPEND QT_REMAP "${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/${it}")
endforeach(it)
add_definitions(-DGUI=1)
list(APPEND INCLUDE_PATHS ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/${PP_PATH}/source/gui source/gui)
cmake_policy(SET CMP0020 NEW)
find_package(Qt5Core QUIET)
if (Qt5Core_FOUND)
message("Using Qt5")
find_package(Qt5Widgets REQUIRED)
find_package(Qt5OpenGL REQUIRED)
qt5_wrap_cpp(MOC_OUTFILES ${QT_REMAP} )
qt5_add_resources(QT_RES resources/res.qrc )
add_definitions(-DGUI=1)
add_definitions(${Qt5Widgets_DEFINITIONS})
list(APPEND INCLUDE_PATHS ${Qt5Widgets_INCLUDE_DIRS} ${Qt5OpenGL_INCLUDE_DIRS})
list(APPEND F_LIBS ${Qt5Widgets_LIBRARIES} ${Qt5OpenGL_LIBRARIES})
list(APPEND SOURCES ${MOC_OUTFILES} ${QT_RES})
else()
message("No Qt5 found (recommended!), trying to use Qt4")
find_package(Qt4 REQUIRED)
set(QT_USE_QTOPENGL TRUE)
qt4_wrap_cpp(MOC_OUTFILES ${QT_REMAP} )
qt4_add_resources(QT_RES resources/res.qrc )
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
list(APPEND F_LIBS ${QT_LIBRARIES})
list(APPEND SOURCES ${MOC_OUTFILES} ${QT_RES})
endif()
if (APPLE)
# mac opengl framework
SET(F_LINKADD "${F_LINKADD} -framework OpenGL ")
else()
find_package(OpenGL REQUIRED)
list(APPEND F_LIBS ${OPENGL_LIBRARIES})
endif()
endif()
#******************************************************************************
# setup executable
SET(EXECCMD manta)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${F_LINKADD} ")
SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${F_LINKADD} ")
include_directories( ${INCLUDE_PATHS})
link_directories( ${F_LIB_PATHS} )
IF(NOT NOPYTHON)
# build regular executable
if(CUDA)
#cuda_include_directories(pp/source/cuda)
cuda_add_executable( ${EXECCMD} ${SOURCES} ${PP_REGISTRY})
target_link_libraries( ${EXECCMD} ${F_LIBS} )
cuda_build_clean_target()
else()
if (WIN32)
# make nice folders for Visual Studio
set_source_files_properties(${PP_SOURCES} ${PP_HEADERS} ${NOPP_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE)
add_executable(${EXECCMD} ${SOURCES} ${PP_REGISTRY} ${PP_SOURCES} ${PP_HEADERS})
source_group(Generated FILES ${SOURCES} ${PP_REGISTRY} ${HEADERS})
else()
add_executable(${EXECCMD} ${SOURCES} ${PP_REGISTRY} ${GITINFO})
endif()
target_link_libraries( ${EXECCMD} ${F_LIBS} )
endif()
# fix for "el capitan" TBB and changed dynamic library env vars, lookup of TBB can cause problems without @rpath
IF(APPLE)
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE OSX_VERSION)
STRING(REGEX MATCH "[0-9]+" OSX_VERSION ${OSX_VERSION})
IF (OSX_VERSION GREATER 14)
ADD_CUSTOM_COMMAND(TARGET manta POST_BUILD COMMAND
${CMAKE_INSTALL_NAME_TOOL} -change libtbb.dylib @rpath/libtbb.dylib $<TARGET_FILE:manta> )
ENDIF()
ENDIF()
ELSE()
# only build static library in nopython mode
ADD_LIBRARY (core OBJECT ${SOURCES} ${GITINFO})
ADD_LIBRARY (${EXECCMD} STATIC $<TARGET_OBJECTS:core>)
ENDIF()
# compiler flags
IF(NOT WIN32)
IF(DEBUG)
# stricter: no optimizations and inlining, comment out if needed...
#add_definitions( -O0 -fno-inline -Wall )
set_target_properties(manta PROPERTIES COMPILE_FLAGS "-O0 -fno-inline -Wall ")
ELSE()
# non-debug, optimized version
#add_definitions( -O3 -Wall )
set_target_properties(manta PROPERTIES COMPILE_FLAGS "-O3 -Wall ")
ENDIF()
# use c++11 for all pre-processed c++ sources
set_source_files_properties(${PREPPED_SOURCES} PROPERTIES COMPILE_FLAGS " -std=c++11 " )
ENDIF()
IF(WIN32)
# get rid of some MSVC warnings
add_definitions( /wd4018 /wd4146 /wd4800 )
# for zlib
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
# unsigned to signed conversions
add_definitions( /wd4267 )
# double <> single precision
add_definitions( /wd4244 /wd4305 )
# disable warnings for unsecure functions
add_definitions( /D "_CRT_SECURE_NO_WARNINGS" )
# enable when using Qt creator:
#add_definitions(/FS)
ENDIF()
# debug summary
# MESSAGE(STATUS "DEBUG Flag-Summary - Includes: '${INCLUDE_PATHS}' | Libs: '${F_LIBS}' | LibPaths: '${F_LIB_PATHS}' ")