Skip to content

Commit

Permalink
Merge pull request #4609 from intelfx/BVLC-work-buildsystem
Browse files Browse the repository at this point in the history
[cmake] Improvements to the build system
  • Loading branch information
shelhamer authored Feb 17, 2017
2 parents 475d619 + 6ed799c commit 9bb1b9c
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 150 deletions.
25 changes: 21 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ caffe_option(USE_OPENCV "Build with OpenCV support" ON)
caffe_option(USE_LEVELDB "Build with levelDB" ON)
caffe_option(USE_LMDB "Build with lmdb" ON)
caffe_option(ALLOW_LMDB_NOLOCK "Allow MDB_NOLOCK when reading LMDB files (only if necessary)" OFF)
caffe_option(USE_OPENMP "Link with OpenMP (when your BLAS wants OpenMP and you get linker errors)" OFF)

# ---[ Dependencies
include(cmake/Dependencies.cmake)
Expand All @@ -55,8 +56,6 @@ if(USE_libstdcpp)
message("-- Warning: forcing libstdc++ (controlled by USE_libstdcpp option in cmake)")
endif()

add_definitions(-DGTEST_USE_OWN_TR1_TUPLE)

# ---[ Warnings
caffe_warnings_disable(CMAKE_CXX_FLAGS -Wno-sign-compare -Wno-uninitialized)

Expand All @@ -65,8 +64,26 @@ configure_file(cmake/Templates/caffe_config.h.in "${PROJECT_BINARY_DIR}/caffe_co

# ---[ Includes
set(Caffe_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
include_directories(${Caffe_INCLUDE_DIR} ${PROJECT_BINARY_DIR})
include_directories(BEFORE src) # This is needed for gtest.
set(Caffe_SRC_DIR ${PROJECT_SOURCE_DIR}/src)
include_directories(${PROJECT_BINARY_DIR})

# ---[ Includes & defines for CUDA

# cuda_compile() does not have per-call dependencies or include pathes
# (cuda_compile() has per-call flags, but we set them here too for clarity)
#
# list(REMOVE_ITEM ...) invocations remove PRIVATE and PUBLIC keywords from collected definitions and include pathes
if(HAVE_CUDA)
# pass include pathes to cuda_include_directories()
set(Caffe_ALL_INCLUDE_DIRS ${Caffe_INCLUDE_DIRS})
list(REMOVE_ITEM Caffe_ALL_INCLUDE_DIRS PRIVATE PUBLIC)
cuda_include_directories(${Caffe_INCLUDE_DIR} ${Caffe_SRC_DIR} ${Caffe_ALL_INCLUDE_DIRS})

# add definitions to nvcc flags directly
set(Caffe_ALL_DEFINITIONS ${Caffe_DEFINITIONS})
list(REMOVE_ITEM Caffe_ALL_DEFINITIONS PRIVATE PUBLIC)
list(APPEND CUDA_NVCC_FLAGS ${Caffe_ALL_DEFINITIONS})
endif()

# ---[ Subdirectories
add_subdirectory(src/gtest)
Expand Down
65 changes: 1 addition & 64 deletions cmake/ConfigGen.cmake
Original file line number Diff line number Diff line change
@@ -1,31 +1,4 @@

################################################################################################
# Helper function to fetch caffe includes which will be passed to dependent projects
# Usage:
# caffe_get_current_includes(<includes_list_variable>)
function(caffe_get_current_includes includes_variable)
get_property(current_includes DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
caffe_convert_absolute_paths(current_includes)

# remove at most one ${PROJECT_BINARY_DIR} include added for caffe_config.h
list(FIND current_includes ${PROJECT_BINARY_DIR} __index)
list(REMOVE_AT current_includes ${__index})

# removing numpy includes (since not required for client libs)
set(__toremove "")
foreach(__i ${current_includes})
if(${__i} MATCHES "python")
list(APPEND __toremove ${__i})
endif()
endforeach()
if(__toremove)
list(REMOVE_ITEM current_includes ${__toremove})
endif()

caffe_list_unique(current_includes)
set(${includes_variable} ${current_includes} PARENT_SCOPE)
endfunction()

################################################################################################
# Helper function to get all list items that begin with given prefix
# Usage:
Expand All @@ -47,39 +20,15 @@ endfunction()
function(caffe_generate_export_configs)
set(install_cmake_suffix "share/Caffe")

# ---[ Configure build-tree CaffeConfig.cmake file ]---
caffe_get_current_includes(Caffe_INCLUDE_DIRS)

set(Caffe_DEFINITIONS "")
if(NOT HAVE_CUDA)
set(HAVE_CUDA FALSE)
list(APPEND Caffe_DEFINITIONS -DCPU_ONLY)
endif()

if(USE_OPENCV)
list(APPEND Caffe_DEFINITIONS -DUSE_OPENCV)
endif()

if(USE_LMDB)
list(APPEND Caffe_DEFINITIONS -DUSE_LMDB)
if (ALLOW_LMDB_NOLOCK)
list(APPEND Caffe_DEFINITIONS -DALLOW_LMDB_NOLOCK)
endif()
endif()

if(USE_LEVELDB)
list(APPEND Caffe_DEFINITIONS -DUSE_LEVELDB)
endif()

if(NOT HAVE_CUDNN)
set(HAVE_CUDNN FALSE)
else()
list(APPEND DEFINITIONS -DUSE_CUDNN)
endif()

if(BLAS STREQUAL "MKL" OR BLAS STREQUAL "mkl")
list(APPEND Caffe_DEFINITIONS -DUSE_MKL)
endif()
# ---[ Configure build-tree CaffeConfig.cmake file ]---

configure_file("cmake/Templates/CaffeConfig.cmake.in" "${PROJECT_BINARY_DIR}/CaffeConfig.cmake" @ONLY)

Expand All @@ -89,18 +38,6 @@ function(caffe_generate_export_configs)

# ---[ Configure install-tree CaffeConfig.cmake file ]---

# remove source and build dir includes
caffe_get_items_with_prefix(${PROJECT_SOURCE_DIR} Caffe_INCLUDE_DIRS __insource)
caffe_get_items_with_prefix(${PROJECT_BINARY_DIR} Caffe_INCLUDE_DIRS __inbinary)
list(REMOVE_ITEM Caffe_INCLUDE_DIRS ${__insource} ${__inbinary})

# add `install` include folder
set(lines
"get_filename_component(__caffe_include \"\${Caffe_CMAKE_DIR}/../../include\" ABSOLUTE)\n"
"list(APPEND Caffe_INCLUDE_DIRS \${__caffe_include})\n"
"unset(__caffe_include)\n")
string(REPLACE ";" "" Caffe_INSTALL_INCLUDE_DIR_APPEND_COMMAND ${lines})

configure_file("cmake/Templates/CaffeConfig.cmake.in" "${PROJECT_BINARY_DIR}/cmake/CaffeConfig.cmake" @ONLY)

# Install the CaffeConfig.cmake and export set to use with install-tree
Expand Down
12 changes: 6 additions & 6 deletions cmake/Cuda.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,17 @@ endif()

set(HAVE_CUDA TRUE)
message(STATUS "CUDA detected: " ${CUDA_VERSION})
include_directories(SYSTEM ${CUDA_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS ${CUDA_CUDART_LIBRARY}
${CUDA_curand_LIBRARY} ${CUDA_CUBLAS_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${CUDA_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${CUDA_CUDART_LIBRARY}
${CUDA_curand_LIBRARY} ${CUDA_CUBLAS_LIBRARIES})

# cudnn detection
if(USE_CUDNN)
detect_cuDNN()
if(HAVE_CUDNN)
add_definitions(-DUSE_CUDNN)
include_directories(SYSTEM ${CUDNN_INCLUDE})
list(APPEND Caffe_LINKER_LIBS ${CUDNN_LIBRARY})
list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_CUDNN)
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${CUDNN_INCLUDE})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${CUDNN_LIBRARY})
endif()
endif()

Expand Down
92 changes: 55 additions & 37 deletions cmake/Dependencies.cmake
Original file line number Diff line number Diff line change
@@ -1,57 +1,76 @@
# This list is required for static linking and exported to CaffeConfig.cmake
# These lists are later turned into target properties on main caffe library target
set(Caffe_LINKER_LIBS "")
set(Caffe_INCLUDE_DIRS "")
set(Caffe_DEFINITIONS "")
set(Caffe_COMPILE_OPTIONS "")

# ---[ Boost
find_package(Boost 1.46 REQUIRED COMPONENTS system thread filesystem)
include_directories(SYSTEM ${Boost_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${Boost_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${Boost_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${Boost_LIBRARIES})

# ---[ Threads
find_package(Threads REQUIRED)
list(APPEND Caffe_LINKER_LIBS ${CMAKE_THREAD_LIBS_INIT})
list(APPEND Caffe_LINKER_LIBS PRIVATE ${CMAKE_THREAD_LIBS_INIT})

# ---[ OpenMP
if(USE_OPENMP)
# Ideally, this should be provided by the BLAS library IMPORTED target. However,
# nobody does this, so we need to link to OpenMP explicitly and have the maintainer
# to flick the switch manually as needed.
#
# Moreover, OpenMP package does not provide an IMPORTED target as well, and the
# suggested way of linking to OpenMP is to append to CMAKE_{C,CXX}_FLAGS.
# However, this naïve method will force any user of Caffe to add the same kludge
# into their buildsystem again, so we put these options into per-target PUBLIC
# compile options and link flags, so that they will be exported properly.
find_package(OpenMP REQUIRED)
list(APPEND Caffe_LINKER_LIBS PRIVATE ${OpenMP_CXX_FLAGS})
list(APPEND Caffe_COMPILE_OPTIONS PRIVATE ${OpenMP_CXX_FLAGS})
endif()

# ---[ Google-glog
include("cmake/External/glog.cmake")
include_directories(SYSTEM ${GLOG_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS ${GLOG_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${GLOG_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${GLOG_LIBRARIES})

# ---[ Google-gflags
include("cmake/External/gflags.cmake")
include_directories(SYSTEM ${GFLAGS_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS ${GFLAGS_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${GFLAGS_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${GFLAGS_LIBRARIES})

# ---[ Google-protobuf
include(cmake/ProtoBuf.cmake)

# ---[ HDF5
find_package(HDF5 COMPONENTS HL REQUIRED)
include_directories(SYSTEM ${HDF5_INCLUDE_DIRS} ${HDF5_HL_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${HDF5_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES})

# ---[ LMDB
if(USE_LMDB)
find_package(LMDB REQUIRED)
include_directories(SYSTEM ${LMDB_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${LMDB_LIBRARIES})
add_definitions(-DUSE_LMDB)
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${LMDB_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${LMDB_LIBRARIES})
list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_LMDB)
if(ALLOW_LMDB_NOLOCK)
add_definitions(-DALLOW_LMDB_NOLOCK)
list(APPEND Caffe_DEFINITIONS PRIVATE -DALLOW_LMDB_NOLOCK)
endif()
endif()

# ---[ LevelDB
if(USE_LEVELDB)
find_package(LevelDB REQUIRED)
include_directories(SYSTEM ${LevelDB_INCLUDE})
list(APPEND Caffe_LINKER_LIBS ${LevelDB_LIBRARIES})
add_definitions(-DUSE_LEVELDB)
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${LevelDB_INCLUDES})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${LevelDB_LIBRARIES})
list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_LEVELDB)
endif()

# ---[ Snappy
if(USE_LEVELDB)
find_package(Snappy REQUIRED)
include_directories(SYSTEM ${Snappy_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${Snappy_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PRIVATE ${Snappy_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PRIVATE ${Snappy_LIBRARIES})
endif()

# ---[ CUDA
Expand All @@ -63,8 +82,7 @@ if(NOT HAVE_CUDA)
message(WARNING "-- CUDA is not detected by cmake. Building without it...")
endif()

# TODO: remove this not cross platform define in future. Use caffe_config.h instead.
add_definitions(-DCPU_ONLY)
list(APPEND Caffe_DEFINITIONS PUBLIC -DCPU_ONLY)
endif()

if(USE_NCCL)
Expand All @@ -80,10 +98,10 @@ if(USE_OPENCV)
if(NOT OpenCV_FOUND) # if not OpenCV 3.x, then imgcodecs are not found
find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc)
endif()
include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS ${OpenCV_LIBS})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${OpenCV_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${OpenCV_LIBS})
message(STATUS "OpenCV found (${OpenCV_CONFIG_PATH})")
add_definitions(-DUSE_OPENCV)
list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_OPENCV)
endif()

# ---[ BLAS
Expand All @@ -93,26 +111,26 @@ if(NOT APPLE)

if(BLAS STREQUAL "Atlas" OR BLAS STREQUAL "atlas")
find_package(Atlas REQUIRED)
include_directories(SYSTEM ${Atlas_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${Atlas_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${Atlas_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${Atlas_LIBRARIES})
elseif(BLAS STREQUAL "Open" OR BLAS STREQUAL "open")
find_package(OpenBLAS REQUIRED)
include_directories(SYSTEM ${OpenBLAS_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${OpenBLAS_LIB})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${OpenBLAS_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${OpenBLAS_LIB})
elseif(BLAS STREQUAL "MKL" OR BLAS STREQUAL "mkl")
find_package(MKL REQUIRED)
include_directories(SYSTEM ${MKL_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${MKL_LIBRARIES})
add_definitions(-DUSE_MKL)
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${MKL_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${MKL_LIBRARIES})
list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_MKL)
endif()
elseif(APPLE)
find_package(vecLib REQUIRED)
include_directories(SYSTEM ${vecLib_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${vecLib_LINKER_LIBS})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${vecLib_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${vecLib_LINKER_LIBS})

if(VECLIB_FOUND)
if(NOT vecLib_INCLUDE_DIR MATCHES "^/System/Library/Frameworks/vecLib.framework.*")
add_definitions(-DUSE_ACCELERATE)
list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_ACCELERATE)
endif()
endif()
endif()
Expand Down Expand Up @@ -156,9 +174,9 @@ if(BUILD_python)
if(PYTHONLIBS_FOUND AND NUMPY_FOUND AND Boost_PYTHON_FOUND)
set(HAVE_PYTHON TRUE)
if(BUILD_python_layer)
add_definitions(-DWITH_PYTHON_LAYER)
include_directories(SYSTEM ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS ${PYTHON_LIBRARIES} ${Boost_LIBRARIES})
list(APPEND Caffe_DEFINITIONS PRIVATE -DWITH_PYTHON_LAYER)
list(APPEND Caffe_INCLUDE_DIRS PRIVATE ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIR} PUBLIC ${Boost_INCLUDE_DIRS})
list(APPEND Caffe_LINKER_LIBS PRIVATE ${PYTHON_LIBRARIES} PUBLIC ${Boost_LIBRARIES})
endif()
endif()
endif()
Expand Down
4 changes: 2 additions & 2 deletions cmake/ProtoBuf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# the standard cmake script with version and python generation support

find_package( Protobuf REQUIRED )
include_directories(SYSTEM ${PROTOBUF_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS ${PROTOBUF_LIBRARIES})
list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${PROTOBUF_INCLUDE_DIR})
list(APPEND Caffe_LINKER_LIBS PUBLIC ${PROTOBUF_LIBRARIES})

# As of Ubuntu 14.04 protoc is no longer a part of libprotobuf-dev package
# and should be installed separately as in: sudo apt-get install protobuf-compiler
Expand Down
15 changes: 5 additions & 10 deletions cmake/Templates/CaffeConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
# After successful configuration the following variables
# will be defined:
#
# Caffe_INCLUDE_DIRS - Caffe include directories
# Caffe_LIBRARIES - libraries to link against
# Caffe_DEFINITIONS - a list of definitions to pass to compiler
# Caffe_LIBRARIES - IMPORTED targets to link against
# (There is no Caffe_INCLUDE_DIRS and Caffe_DEFINITIONS
# because they are specified in the IMPORTED target interface.)
#
# Caffe_HAVE_CUDA - signals about CUDA support
# Caffe_HAVE_CUDNN - signals about cuDNN support
Expand All @@ -27,7 +27,7 @@ if(@USE_OPENCV@)

if(EXISTS ${Caffe_OpenCV_CONFIG_PATH} AND NOT TARGET opencv_core)
message(STATUS "Caffe: using OpenCV config from ${Caffe_OpenCV_CONFIG_PATH}")
include(${Caffe_OpenCV_CONFIG_PATH}/OpenCVModules.cmake)
include(${Caffe_OpenCV_CONFIG_PATH}/OpenCVConfig.cmake)
endif()

else()
Expand All @@ -39,21 +39,16 @@ endif()

# Compute paths
get_filename_component(Caffe_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(Caffe_INCLUDE_DIRS "@Caffe_INCLUDE_DIRS@")

@Caffe_INSTALL_INCLUDE_DIR_APPEND_COMMAND@

# Our library dependencies
if(NOT TARGET caffe AND NOT caffe_BINARY_DIR)
include("${Caffe_CMAKE_DIR}/CaffeTargets.cmake")
endif()

# List of IMPORTED libs created by CaffeTargets.cmake
# These targets already specify all needed definitions and include pathes
set(Caffe_LIBRARIES caffe)

# Definitions
set(Caffe_DEFINITIONS "@Caffe_DEFINITIONS@")

# Cuda support variables
set(Caffe_CPU_ONLY @CPU_ONLY@)
set(Caffe_HAVE_CUDA @HAVE_CUDA@)
Expand Down
Loading

0 comments on commit 9bb1b9c

Please sign in to comment.