CMakeLists.txt 13.6 KB
Newer Older
1
cmake_minimum_required (VERSION 3.2)
2
project (alta CXX)
3

4 5 6 7
#############################
#      Preconfiguration     #
#############################

8
# Set Python version number
9
set(Python_Version "3" CACHE STRING "Python interface version (default Python 3)")
10
set(Python_ADDITIONAL_VERSIONS ${Python_Version})
11

12 13 14 15 16 17 18 19
# Require C++11 options
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)


#############################
#        Dependencies       #
#############################
20
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/configs/cmake/)
21

22
# Find required packages
23
find_package(Eigen3)
24
find_package(OpenMP)
25
find_package(PythonInterp)
26
find_package(PythonLibs)
27
find_package(Doxygen)
28
find_package(Ceres)
29
find_package(NLOPT)
30 31 32

add_definitions(-DALTA_PLUGIN_DIRECTORY="/usr/lib/alta_plugins")

33
# Add core and library include files
34
include_directories("external/build" "sources" ${EIGEN3_INCLUDE_DIR})
35
include_directories("external" "external/Catch/include" "external/quadprog++")
36
include_directories("external/pybind11/include")
37

38
# Look for header only dependencies
39 40 41
find_file(EIGEN_FOUND  "Eigen/Core"      HINTS ${EIGEN3_INCLUDE_DIR})
find_file(CATCH_FOUND  "catch.hpp"       HINTS external/Catch/include)
find_file(FLANN_FOUND  "flann/flann.hpp")
42
find_file(PYBIND_FOUND "pybind11/pybind11.h" HINTS "external/pybind11/include")
43 44 45 46 47

# Check if Eigen is found
if(NOT EIGEN_FOUND)
    message(FATAL_ERROR "Unable to find Eigen header")
endif()
48

49 50 51 52 53 54 55
# Update compilation option to include OpenMP if present
if(OPENMP_FOUND)
    set (CMAKE_CXX_FLAGS ${OpenMP_CXX_FLAGS})
endif(OPENMP_FOUND)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

56

57 58 59 60 61 62
#############################
#      Helper functions     #
#############################

function(alta_add_plugin name sources)
	add_library(${name} SHARED sources/plugins/${sources})
63
        target_link_libraries(${name} core)
64 65 66 67
endfunction(alta_add_plugin)

function(alta_add_soft name sources)
	add_executable(${name} sources/softs/${sources})
68
        target_link_libraries(${name} core)
69 70
endfunction(alta_add_soft)

71 72 73 74 75 76 77 78 79 80 81 82
function(alta_test)
    set(options OPTIONAL)
    set(oneValueArgs NAME)
    set(multiValueArgs COMMAND)
    cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    
    add_test(NAME ${TEST_NAME} COMMAND ${TEST_COMMAND}
             WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
    set_tests_properties("${TEST_NAME}"
                         PROPERTIES ENVIRONMENT "ALTA_PLUGIN_PATH=${CMAKE_BINARY_DIR}/plugins")  
endfunction(alta_test)

83 84 85 86 87 88 89 90 91 92
function(alta_test_python)
    set(options OPTIONAL)
    set(oneValueArgs NAME)
    set(multiValueArgs COMMAND)
    cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    
    add_test(NAME ${TEST_NAME} COMMAND ${TEST_COMMAND}
             WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
    set_tests_properties("${TEST_NAME}"
        PROPERTIES ENVIRONMENT "ALTA_PLUGIN_PATH=${CMAKE_BINARY_DIR}/plugins;PYTHONPATH=${CMAKE_BINARY_DIR}/python")  
93
endfunction(alta_test_python)
94

95
function(alta_test_unit name sources)
96 97
        add_executable(${name} sources/tests/${sources})
        target_link_libraries(${name} core)
98 99
        add_test(NAME ${name} COMMAND ${CMAKE_BINARY_DIR}/tests/${name} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
        set_tests_properties(${name} PROPERTIES ENVIRONMENT "TEST_DATA_DIRECTORY=${CMAKE_SOURCE_DIR}/sources/tests;ALTA_PLUGIN_PATH=${CMAKE_BINARY_DIR}/plugins")
100 101 102 103 104
endfunction(alta_test_unit)

function(alta_test_soft name)
        add_test(NAME ${name} COMMAND ${CMAKE_BINARY_DIR}/softs/${name} --help)
endfunction(alta_test_soft)
105

106
function(alta_download_merl name)
107
    find_file(${name}_FOUND "${name}.binary" PATHS "${CMAKE_BINARY_DIR}/tests/")
108 109
    if(NOT ${name}_FOUND)
        message("Dowloading ${name} from MERL database:")
Laurent Belcour's avatar
Laurent Belcour committed
110 111 112 113
	file(DOWNLOAD
	     "http://people.csail.mit.edu/wojciech/BRDFDatabase/brdfs/${name}.binary"
	     "${CMAKE_BINARY_DIR}/tests/${name}.binary" SHOW_PROGRESS)
	set(${name}_FOUND TRUE PARENT_SCOPE)
114
    endif()
115 116
endfunction(alta_download_merl)

117 118 119 120 121 122

#############################
#         ALTA core         #
#############################

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
123

124 125 126 127
add_library(core STATIC
            sources/core/args.h
            sources/core/common.h
            sources/core/common.cpp
128 129 130 131 132 133
            sources/core/metrics.h
            sources/core/metrics.cpp
            sources/core/params.h
            sources/core/params.cpp
            sources/core/data.h
            sources/core/data.cpp
134
            sources/core/data_storage.h
135 136 137 138 139 140 141 142 143
            sources/core/data_storage.cpp
            sources/core/vertical_segment.h
            sources/core/vertical_segment.cpp
            sources/core/function.h
            sources/core/function.cpp
            sources/core/rational_function.h
            sources/core/rational_function.cpp
            sources/core/plugins_manager.h
            sources/core/plugins_manager.cpp)
144

145 146 147 148 149

add_library(quadprog STATIC
            external/quadprog++/QuadProg++.hh
            external/quadprog++/QuadProg++.cc)

150 151
target_link_libraries(core ${CMAKE_DL_LIBS})

152 153 154 155 156

#############################
#         Plugins           #
#############################

157
#    set(CMAKE_SHARED_LIBRARY_PREFIX "")
158
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
159 160 161
# Note: Required on windows to build the plugins in the 'plugins'
# directory. [Laurent] I have no idea why this is needed.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
162 163

# Data
164 165 166 167
alta_add_plugin(data_astm       data_io/astm.cpp)
alta_add_plugin(data_merl       data_io/merl.cpp)
alta_add_plugin(data_utia       data_io/utia.cpp)
alta_add_plugin(data_brdf_slice data_io/slice.cpp)
168

169
alta_add_plugin(data_grid       data_interpolants/grid.cpp)
170 171 172 173
if(FLANN_FOUND)
    alta_add_plugin(data_rbf    data_interpolants/rbf.cpp)
endif()
#alta_add_plugin(data_matlab data_interpolants/matlab.cpp)
174 175

# Functions
176 177 178
alta_add_plugin(rational_function_legendre		rational_function_legendre/rational_function.cpp)
alta_add_plugin(rational_function_chebychev		rational_function_chebychev/rational_function.cpp)
alta_add_plugin(rational_function_cosine 		rational_function_cosine/rational_function.cpp)
179 180 181 182 183 184 185 186 187
alta_add_plugin(nonlinear_function_abc                  nonlinear_function_abc/function.cpp)
alta_add_plugin(nonlinear_function_beckmann             nonlinear_function_beckmann/function.cpp)
alta_add_plugin(nonlinear_function_blinn                nonlinear_function_blinn/function.cpp)
alta_add_plugin(nonlinear_function_diffuse              nonlinear_function_diffuse/function.cpp)
alta_add_plugin(nonlinear_function_lafortune            nonlinear_function_lafortune/function.cpp)
alta_add_plugin(nonlinear_function_sgd                  nonlinear_function_sgd/function.cpp)
alta_add_plugin(nonlinear_function_spherical_gaussian   nonlinear_function_spherical_gaussian/function.cpp)
alta_add_plugin(nonlinear_function_ward                 nonlinear_function_ward/function.cpp)

188 189 190 191
alta_add_plugin(nonlinear_function_retrobeckmann        nonlinear_function_retrobeckmann/function.cpp)
alta_add_plugin(nonlinear_function_retroblinn		nonlinear_function_retroblinn/function.cpp)
alta_add_plugin(nonlinear_function_retroyoo             nonlinear_function_retroyoo/function.cpp)
alta_add_plugin(nonlinear_fresnel_retroschlick		nonlinear_fresnel_retroschlick/function.cpp)
192 193

alta_add_plugin(nonlinear_fresnel_schlick               nonlinear_fresnel_schlick/function.cpp)
194
alta_add_plugin(nonlinear_fresnel_normalized_schlick    nonlinear_fresnel_normalized_schlick/function.cpp)
195 196 197 198

alta_add_plugin(nonlinear_shadowing_schlick             nonlinear_shadowing_schlick/function.cpp)
alta_add_plugin(nonlinear_shadowing_smith               nonlinear_shadowing_smith/function.cpp)
alta_add_plugin(nonlinear_shadowing_walter_smith        nonlinear_shadowing_walter_smith/function.cpp)
199

200
# Fitters
201 202 203 204
alta_add_plugin(rational_fitter_eigen 			rational_fitter_eigen/rational_fitter.cpp)
alta_add_plugin(rational_fitter_leastsquare		rational_fitter_leastsquare/rational_fitter.cpp)
alta_add_plugin(rational_fitter_quadprog		rational_fitter_quadprog/rational_fitter.cpp)
alta_add_plugin(rational_fitter_parallel		rational_fitter_parallel/rational_fitter.cpp)
205
alta_add_plugin(nonlinear_fitter_eigen                  nonlinear_fitter_eigen/fitter.cpp)
206 207
target_link_libraries(rational_fitter_quadprog quadprog)
target_link_libraries(rational_fitter_parallel quadprog)
208

209

210
# TODO: Add check before compiling  IPOPT
211 212
if (CERES_FOUND)
    alta_add_plugin(nonlinear_fitter_ceres                  nonlinear_fitter_ceres/fitter.cpp)
213
    target_link_libraries(nonlinear_fitter_ceres ${CERES_LIBRARIES})
214
    target_include_directories(nonlinear_fitter_ceres PUBLIC ${CERES_INCLUDE_DIR})
215
    list(APPEND nonlinear_fitters ceres)
216 217 218 219
endif()
if (NLOPT_FOUND)
    alta_add_plugin(nonlinear_fitter_nlopt                  nonlinear_fitter_nlopt/fitter.cpp)
    target_link_libraries(nonlinear_fitter_nlopt ${NLOPT_LIBRARIES})
220
    target_include_directories(nonlinear_fitter_nlopt PUBLIC ${NLOPT_INCLUDE_DIRS})
221
    list(APPEND nonlinear_fitters nlopt)
222
endif()
223
#alta_add_plugin(nonlinear_fitter_ipopt                  nonlinear_fitter_ipopt/fitter.cpp)
224

225
# Python bindings
226
if(PYTHONLIBS_FOUND AND PYBIND_FOUND)
227
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python)
228 229 230 231
    # Note: Required on windows to build the python dll in the 'python'
    # directory. [Laurent] I have no idea why this is needed.
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python)

232
    include_directories(${PYTHON_INCLUDE_DIRS})
233
    add_library(alta SHARED sources/python/alta.cpp)
234
    target_link_libraries(alta core ${PYTHON_LIBRARIES})
235
    set_target_properties(alta PROPERTIES PREFIX "")
236 237 238
    if(APPLE)
        set_target_properties(alta PROPERTIES SUFFIX ".so")
    endif()
239 240 241
    if(WIN32)
        set_target_properties(alta PROPERTIES SUFFIX ".pyd")
    endif()
242 243
endif()

244

245 246 247 248 249 250
#############################
#          Softs            #
#############################

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/softs)

251 252 253 254 255 256 257 258 259
alta_add_soft(brdf2brdf    brdf2brdf/main.cpp)
alta_add_soft(brdf2data    brdf2data/main.cpp)
alta_add_soft(brdf2gnuplot brdf2gnuplot/main.cpp)
#alta_add_soft(brdf2moments brdf2moments/main.cpp)
alta_add_soft(brdf2stats   fit2stat/fit2stat.cpp)
alta_add_soft(data2data    data2data/main.cpp)
alta_add_soft(data2brdf    data2brdf/main.cpp)
alta_add_soft(data2stats   data2stats/data2stats.cpp)
alta_add_soft(data2moments data2moments/main.cpp)
260

261

262 263 264 265
#############################
#          Tests            #
#############################

266
enable_testing()
267

268 269 270 271 272 273 274
# Test all softs with `--help` option
alta_test_soft(brdf2data)
alta_test_soft(data2data)
alta_test_soft(data2stats)
alta_test_soft(data2brdf)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests)
275
include_directories("sources/tests")
276

277 278 279 280 281 282 283 284 285
# Unit test
alta_test_unit(test_data_io  core/data-io.cpp)
alta_test_unit(half-test-1   core/half-test-1.cpp)
alta_test_unit(half-test-2   core/half-test-2.cpp)
alta_test_unit(half-test-3   core/half-test-3.cpp)
alta_test_unit(half-test-4   core/half-test-4.cpp)
alta_test_unit(nonlinear-fit core/nonlinear-fit.cpp)
alta_test_unit(params-test-1 core/params-test-1.cpp)
alta_test_unit(params-test-2 core/params-test-2.cpp)
286 287

if(CPPQUICKCHECK_FOUND)
288
    alta_test_unit(params-qc-1 core/params-qc-1.cpp)
289 290
endif()

291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
# Integration test for rational function fitting
foreach(fitter IN ITEMS eigen leastsquare quadprog parallel)
    add_test(NAME "data2dbrdf_kirby_${fitter}"
             COMMAND "data2brdf" "--input"   "${CMAKE_SOURCE_DIR}/sources/tests/Kirby2.dat"
                                 "--output"  "Kirby2.func"
                                 "--fitter"  "rational_fitter_${fitter}"
             WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests")

    set_tests_properties("data2dbrdf_kirby_${fitter}"
                         PROPERTIES ENVIRONMENT "ALTA_PLUGIN_PATH=${CMAKE_BINARY_DIR}/plugins")
endforeach()

add_test(NAME "brdf2data_kirby"
         COMMAND "brdf2data" "--input"     "Kirby2.func"
                             "--output"    "Kirby2.dat"
                             "--data-file" "${CMAKE_SOURCE_DIR}/sources/tests/Kirby2.dat"
         WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests")

309 310 311
add_test(NAME "data2stats_pinkfelt"
         COMMAND "data2stats" "--input"     "${CMAKE_SOURCE_DIR}/data/brdf/pink-felt-1d.alta"
                              "--ref"       "${CMAKE_SOURCE_DIR}/data/brdf/pink-felt-1d.alta"
312 313
         WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests")

314 315 316 317 318 319 320
foreach(fitter IN ITEMS ${nonlinear_fitters})
    alta_test(NAME "data2brdf_pinkfelt_${fitter}"
              COMMAND "data2brdf"
                      "--input"  "${CMAKE_SOURCE_DIR}/data/brdf/pink-felt-1d.alta"
                      "--output" "pink-felt-1d-${fitter}-blinn.func"
                      "--fitter" "nonlinear_fitter_${fitter}"
                      "--func"   "[nonlinear_function_diffuse, nonlinear_function_blinn]") 
321
endforeach()
322

323
if(PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND AND PYBIND_FOUND)
324
    alta_test_python(NAME "python_test_arguments"
325
                     COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/sources/tests/python/test-arguments.py")
326 327

    alta_test_python(NAME "python_test_vec"
328
                     COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/sources/tests/python/test-vec.py")
329 330

    alta_test_python(NAME "python_test_function"
331
                     COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/sources/tests/python/test-python-function.py")
332 333
endif()

334 335 336 337 338 339 340
# add a target to generate API documentation with Doxygen
if(DOXYGEN_FOUND)
	add_custom_target(doc
			  ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/documents/doxygen.conf
			  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/documents/
			  COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND)