Skip to content

Commit

Permalink
Rework CMake dependencies management (Fix #1116)
Browse files Browse the repository at this point in the history
- By default don't build dependencies simply call find_package()
- By default only build C++ library
- IF building Python, Java or .Net wrapper then force build dependencies
  - Build dependencies as STATIC
  - Build and Install (in CMAKE_BINARY_DIR) dependencies at configure time
  • Loading branch information
Mizux committed Apr 11, 2019
1 parent d9d16af commit a49b914
Show file tree
Hide file tree
Showing 30 changed files with 728 additions and 532 deletions.
144 changes: 68 additions & 76 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,100 +1,92 @@
# This file is just an orchestration
cmake_minimum_required(VERSION 3.8.2)
cmake_minimum_required(VERSION 3.5.2)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Default Build Type to be Release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel. (default: Release)"
FORCE)
endif(NOT CMAKE_BUILD_TYPE)

# Use find_package everywhere, no-op if it's a subproject
macro(find_package)
if(NOT TARGET ${ARGV0} AND NOT TARGET ${ARGV0}::${ARGV0})
_find_package(${ARGV})
else()
if(TARGET ${ARGV0})
get_target_property(TGT_VER ${ARGV0} VERSION)
set(TGT ${ARGV0})
else()
get_target_property(TGT_VER ${ARGV0}::${ARGV0} VERSION)
set(TGT ${ARGV0}::${ARGV0})
endif()
message(STATUS "Found ${ARGV0}: CMake Target ${TGT} (found version \"${TGT_VER}\")")
set(${ARGV0}_FOUND TRUE)
endif()
endmacro()
# Apple: Don't modify install_name when touching RPATH.
if(POLICY CMP0068)
cmake_policy(SET CMP0068 NEW)
endif()

project(ortools-meta NONE)
include(utils)
set_version(VERSION)

project(ortools LANGUAGES CXX VERSION ${VERSION})
message(STATUS "version: ${PROJECT_VERSION}")

# Default Build Type to be Release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel. (default: Release)"
FORCE)
endif()

include(CTest)
if(UNIX)
# Needed to create python package from the build directory
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
option(BUILD_SHARED_LIBS "Build shared libraries(.so)." ON)
elseif(MSVC)
# Windows only support static build.
set(BUILD_SHARED_LIBS OFF)
endif()

# When incorporating ortools in a CMake Project, then only C++ library will be built.
# Consequently Python, Java and C# wrapper won't be built.
if("^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
set(ORTOOLS_IS_SUBPROJECT FALSE)
else()
set(ORTOOLS_IS_SUBPROJECT TRUE)
endif()
# By default only the ortools C++ library is built.
option(BUILD_CXX "Build C++ library" ON)
option(BUILD_PYTHON "Build Python Library" OFF)
option(BUILD_JAVA "Build Java Library" OFF)
option(BUILD_DOTNET "Build .NET Library" OFF)
message(STATUS "Build C++ library: ${BUILD_CXX}")
message(STATUS "Build Python: ${BUILD_PYTHON}")
message(STATUS "Build Java: ${BUILD_JAVA}")
message(STATUS "Build .Net: ${BUILD_DOTNET}")

#option(BUILD_DOC "Build doxygen" OFF)
#message(STATUS "Build doxygen: ${BUILD_DOC}")

# By default all dependencies are NOT built (i.e. BUILD_DEPS=OFF).
# IF building any wrapper THEN Force BUILD_DEPS=ON
# IF BUILD_DEPS=ON THEN Force all BUILD_*=ON
include(CMakeDependentOption)
option(BUILD_DEPS "Force re-build of all dependencies" ON)
option(BUILD_CXX "Build C++ library" ON)
CMAKE_DEPENDENT_OPTION(BUILD_PYTHON "Build Python Library" OFF
"BUILD_CXX; NOT ORTOOLS_IS_SUBPROJECT" OFF)
CMAKE_DEPENDENT_OPTION(BUILD_JAVA "Build Java Library" OFF
"BUILD_CXX; NOT ORTOOLS_IS_SUBPROJECT" OFF)
CMAKE_DEPENDENT_OPTION(BUILD_DOTNET "Build .NET Library" OFF
"BUILD_CXX; NOT ORTOOLS_IS_SUBPROJECT" OFF)
CMAKE_DEPENDENT_OPTION(BUILD_DEPS "Force re-build of all dependencies" OFF
"NOT BUILD_PYTHON; NOT BUILD_JAVA; NOT BUILD_DOTNET" ON)
CMAKE_DEPENDENT_OPTION(BUILD_ZLIB "Build the ZLIB dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_absl "Build the abseil-cpp dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_gflags "Build the gflags dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_glog "Build the glog dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_Protobuf "Build the Protobuf dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_CoinUtils "Build the CoinUtils dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_Osi "Build the Osi dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_Clp "Build the Clp dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_Cgl "Build the Cgl dependency Library" OFF
"NOT BUILD_DEPS" ON)
CMAKE_DEPENDENT_OPTION(BUILD_Cbc "Build the Cbc dependency Library" OFF
"NOT BUILD_DEPS" ON)

message(STATUS "Build all dependencies: ${BUILD_DEPS}")
message(STATUS "Build CXX library: ${BUILD_CXX}")
message(STATUS "Build Python Binding: ${BUILD_PYTHON}")
message(STATUS "Build Java Binding: ${BUILD_JAVA}")
message(STATUS "Build .Net Binding: ${BUILD_DOTNET}")

# Add OR Tools Dependencies as CMake subproject if missing
if(BUILD_DEPS)
add_subdirectory(cmake/external external)
endif()
message(STATUS "Build ZLIB: ${BUILD_ZLIB}")
message(STATUS "Build abseil-cpp: ${BUILD_absl}")
message(STATUS "Build gflags: ${BUILD_gflags}")
message(STATUS "Build glog: ${BUILD_glog}")
message(STATUS "Build protobuf: ${BUILD_Protobuf}")
message(STATUS "Build CoinUtils: ${BUILD_CoinUtils}")
message(STATUS "Build Osi: ${BUILD_Osi}")
message(STATUS "Build Clp: ${BUILD_Clp}")
message(STATUS "Build Cgl: ${BUILD_Cgl}")
message(STATUS "Build Cbc: ${BUILD_Cbc}")

if(BUILD_CXX)
include(cpp)
if(BUILD_TESTING)
add_subdirectory(examples/cpp)
endif()
endif()
# Build Needed dependencies
add_subdirectory(cmake/dependencies dependencies)
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/dependencies/install)

if(BUILD_PYTHON)
include(python)
if(BUILD_TESTING)
add_subdirectory(examples/python)
add_subdirectory(examples/notebook)
endif()
endif()
include(CTest)

if(BUILD_JAVA)
include(java)
if(BUILD_TESTING)
add_subdirectory(examples/java)
endif()
endif()
include(cpp)

if(BUILD_DOTNET)
include(dotnet)
if(BUILD_TESTING)
add_subdirectory(examples/dotnet)
endif()
endif()
include(python)
include(java)
include(dotnet)
74 changes: 55 additions & 19 deletions cmake/cpp.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,33 @@
include(utils)
set_version(VERSION)
project(ortools LANGUAGES CXX VERSION ${VERSION})
message(STATUS "ortools version: ${PROJECT_VERSION}")
if(NOT BUILD_CXX)
return()
endif()

# Check dependencies
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREAD_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

find_package(ZLIB REQUIRED)
find_package(absl REQUIRED CONFIG)
set(GFLAGS_USE_TARGET_NAMESPACE TRUE)
find_package(gflags REQUIRED CONFIG)
if(BUILD_gflags)
set(GFLAGS_DEP gflags::gflags_static)
else()
set(GFLAGS_DEP gflags::gflags)
endif()
find_package(glog REQUIRED CONFIG)
find_package(Protobuf REQUIRED CONFIG)
find_package(CoinUtils REQUIRED CONFIG)
find_package(Osi REQUIRED CONFIG)
find_package(Clp REQUIRED CONFIG)
find_package(Cgl REQUIRED CONFIG)
find_package(Cbc REQUIRED CONFIG)

# If wrapper are built, we need to have the install rpath in BINARY_DIR to package
if(BUILD_PYTHON OR BUILD_JAVA OR BUILD_DOTNET)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
endif()

# config options
if(MSVC)
Expand Down Expand Up @@ -44,25 +70,30 @@ else()
endif()
add_definitions(-DUSE_GLOP -DUSE_BOP -DUSE_CBC -DUSE_CLP)

# Verify Dependencies
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)

# Main Target
add_library(${PROJECT_NAME} "")
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11)

if(CMAKE_VERSION VERSION_LESS "3.8.2")
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)
else()
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
endif()

if(NOT APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION})
else()
# Clang don't support version x.y.z with z > 255
set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR})
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 11)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF)
set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${PROJECT_NAME} PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON)
set_target_properties(${PROJECT_NAME} PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
INTERFACE_POSITION_INDEPENDENT_CODE ON
)
set_target_properties(${PROJECT_NAME} PROPERTIES INTERFACE_${PROJECT_NAME}_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})
set_target_properties(${PROJECT_NAME} PROPERTIES COMPATIBLE_INTERFACE_STRING ${PROJECT_NAME}_MAJOR_VERSION)
if(APPLE)
Expand All @@ -86,9 +117,10 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
absl::strings
absl::synchronization
absl::any
gflags::gflags glog::glog
${GFLAGS_DEP}
glog::glog
protobuf::libprotobuf
Cbc::CbcSolver Cbc::OsiCbc Cbc::ClpSolver Cbc::OsiClp
Coin::CbcSolver Coin::OsiCbc Coin::ClpSolver Coin::OsiClp
Threads::Threads)
if(WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC psapi.lib ws2_32.lib)
Expand All @@ -108,7 +140,7 @@ file(GLOB_RECURSE proto_files RELATIVE ${PROJECT_SOURCE_DIR} "ortools/*.proto")
get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
foreach(dir ${protobuf_dirs})
if ("${dir}" MATCHES "BUILD_INTERFACE")
list(APPEND PROTO_DIRS "--proto_path=${dir}")
list(APPEND PROTO_DIRS "\"--proto_path=${dir}\"")
endif()
endforeach()

Expand All @@ -124,7 +156,7 @@ foreach (PROTO_FILE ${proto_files})
OUTPUT ${PROTO_SRC} ${PROTO_HDR}
COMMAND protobuf::protoc
"--proto_path=${PROJECT_SOURCE_DIR}"
"${PROTO_DIRS}"
${PROTO_DIRS}
"--cpp_out=${PROJECT_BINARY_DIR}"
${PROTO_FILE}
DEPENDS ${PROTO_FILE} protobuf::protoc
Expand Down Expand Up @@ -161,6 +193,10 @@ foreach(SUBPROJECT
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}::${SUBPROJECT})
endforeach()

if(BUILD_TESTING)
add_subdirectory(examples/cpp)
endif()

# Install rules
include(GNUInstallDirs)

Expand Down
Loading

0 comments on commit a49b914

Please sign in to comment.