Files
ortools-clone/cmake/cpp.cmake
2020-05-18 14:15:47 +02:00

391 lines
12 KiB
CMake

if(NOT BUILD_CXX)
return()
endif()
# Check dependencies
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREAD_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
# Tell find_package() to try “Config” mode before “Module” mode if no mode was specified.
# This should avoid find_package() to first find our FindXXX.cmake modules if
# distro package already provide a CMake config file...
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
# libprotobuf force us to depends on ZLIB::ZLIB target
if(BUILD_ZLIB)
find_package(ZLIB REQUIRED CONFIG)
else()
find_package(ZLIB REQUIRED)
endif()
if(BUILD_absl)
find_package(absl REQUIRED CONFIG)
else()
find_package(absl REQUIRED)
endif()
set(ABSL_DEPS
absl::base
absl::cord
absl::random_random
absl::raw_hash_set
absl::hash
absl::memory
absl::meta
absl::status
absl::str_format
absl::strings
absl::synchronization
absl::any
)
set(GFLAGS_USE_TARGET_NAMESPACE TRUE)
if(BUILD_gflags)
find_package(gflags REQUIRED CONFIG)
set(GFLAGS_DEP gflags::gflags_static)
else()
find_package(gflags REQUIRED)
set(GFLAGS_DEP gflags::gflags)
endif()
if(BUILD_glog)
find_package(glog REQUIRED CONFIG)
else()
find_package(glog REQUIRED)
endif()
if(BUILD_Protobuf)
find_package(Protobuf REQUIRED CONFIG)
else()
find_package(Protobuf REQUIRED)
endif()
if(USE_COINOR)
if(BUILD_CoinUtils)
find_package(CoinUtils REQUIRED CONFIG)
else()
find_package(CoinUtils REQUIRED)
endif()
if(BUILD_Osi)
find_package(Osi REQUIRED CONFIG)
else()
find_package(Osi REQUIRED)
endif()
if(BUILD_Clp)
find_package(Clp REQUIRED CONFIG)
else()
find_package(Clp REQUIRED)
endif()
if(BUILD_Cgl)
find_package(Cgl REQUIRED CONFIG)
else()
find_package(Cgl REQUIRED)
endif()
if(BUILD_Cbc)
find_package(Cbc REQUIRED CONFIG)
else()
find_package(Cbc REQUIRED)
endif()
set(COINOR_DEPS Coin::CbcSolver Coin::OsiCbc Coin::ClpSolver Coin::OsiClp)
endif()
# Check optional Dependencies
if(USE_CPLEX)
find_package(CPLEX REQUIRED)
set(CPLEX_DEP CPLEX::CPLEX)
endif()
if(USE_SCIP)
find_package(SCIP REQUIRED)
set(SCIP_DEP SCIP::SCIP)
endif()
if(USE_XPRESS)
find_package(XPRESS REQUIRED)
set(XPRESS_DEP XPRESS::XPRESS)
endif()
# 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()
# Main Target
add_library(${PROJECT_NAME} "")
# Xcode fails to build if library doesn't contains at least one source file.
if(XCODE)
file(GENERATE
OUTPUT ${PROJECT_BINARY_DIR}/${PROJECT_NAME}/version.cpp
CONTENT "namespace {char* version = \"${PROJECT_VERSION}\";}")
target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}/version.cpp)
endif()
list(APPEND OR_TOOLS_COMPILE_DEFINITIONS
"USE_BOP" # enable BOP support
"USE_GLOP" # enable GLOP support
)
if(USE_COINOR)
list(APPEND OR_TOOLS_COMPILE_DEFINITIONS
"USE_CBC" # enable COIN-OR CBC support
"USE_CLP" # enable COIN-OR CLP support
)
endif()
if(USE_CPLEX)
list(APPEND OR_TOOLS_COMPILE_DEFINITIONS "USE_CPLEX")
endif()
if(USE_SCIP)
list(APPEND OR_TOOLS_COMPILE_DEFINITIONS "USE_SCIP")
endif()
if(USE_XPRESS)
list(APPEND OR_TOOLS_COMPILE_DEFINITIONS "USE_XPRESS")
endif()
if(WIN32)
list(APPEND OR_TOOLS_COMPILE_DEFINITIONS "__WIN32__")
endif()
if(MSVC)
list(APPEND OR_TOOLS_COMPILE_OPTIONS
"/bigobj" # Allow big object
"/DNOMINMAX"
"/DWIN32_LEAN_AND_MEAN=1"
"/D_CRT_SECURE_NO_WARNINGS"
"/D_CRT_SECURE_NO_DEPRECATE"
"/MP" # Build with multiple processes
)
# Prefer /MD over /MT and add NDEBUG in Release
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
list(APPEND OR_TOOLS_COMPILE_OPTIONS "/MDd")
else()
list(APPEND OR_TOOLS_COMPILE_OPTIONS "/MD" "/DNDEBUG")
endif()
# MSVC warning suppressions
list(APPEND OR_TOOLS_COMPILE_OPTIONS
"/wd4005" # 'macro-redefinition'
"/wd4018" # 'expression' : signed/unsigned mismatch
"/wd4065" # switch statement contains 'default' but no 'case' labels
"/wd4068" # 'unknown pragma'
"/wd4101" # 'identifier' : unreferenced local variable
"/wd4146" # unary minus operator applied to unsigned type, result still unsigned
"/wd4200" # nonstandard extension used : zero-sized array in struct/union
"/wd4244" # 'conversion' conversion from 'type1' to 'type2', possible loss of data
"/wd4251" # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
"/wd4267" # 'var' : conversion from 'size_t' to 'type', possible loss of data
"/wd4305" # 'identifier' : truncation from 'type1' to 'type2'
"/wd4307" # 'operator' : integral constant overflow
"/wd4309" # 'conversion' : truncation of constant value
"/wd4334" # 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
"/wd4355" # 'this' : used in base member initializer list
"/wd4477" # 'fwprintf' : format string '%s' requires an argument of type 'wchar_t *'
"/wd4506" # no definition for inline function 'function'
"/wd4715" # function' : not all control paths return a value
"/wd4800" # 'type' : forcing value to bool 'true' or 'false' (performance warning)
"/wd4996" # The compiler encountered a deprecated declaration.
)
else()
list(APPEND OR_TOOLS_COMPILE_OPTIONS "-fwrapv")
endif()
# Includes
target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>
)
# Compile options
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
target_compile_definitions(${PROJECT_NAME} PUBLIC ${OR_TOOLS_COMPILE_DEFINITIONS})
target_compile_options(${PROJECT_NAME} PUBLIC ${OR_TOOLS_COMPILE_OPTIONS})
# Properties
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
INSTALL_RPATH "@loader_path"
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
endif()
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)
# Dependencies
target_link_libraries(${PROJECT_NAME} PUBLIC
ZLIB::ZLIB
${ABSL_DEPS}
${GFLAGS_DEP}
glog::glog
protobuf::libprotobuf
${COINOR_DEPS}
${CPLEX_DEP}
${SCIP_DEP}
${XPRESS_DEP}
Threads::Threads)
if(WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC psapi.lib ws2_32.lib)
endif()
# ALIAS
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
# Generate Protobuf cpp sources
set(PROTO_HDRS)
set(PROTO_SRCS)
file(GLOB_RECURSE proto_files RELATIVE ${PROJECT_SOURCE_DIR}
"ortools/bop/*.proto"
"ortools/constraint_solver/*.proto"
"ortools/data/*.proto"
"ortools/glop/*.proto"
"ortools/graph/*.proto"
"ortools/linear_solver/*.proto"
"ortools/sat/*.proto"
"ortools/util/*.proto"
"ortools/linear_solver/*.proto"
)
# Get Protobuf include dir
get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
foreach(dir IN LISTS protobuf_dirs)
if ("${dir}" MATCHES "BUILD_INTERFACE")
list(APPEND PROTO_DIRS "\"--proto_path=${dir}\"")
endif()
endforeach()
foreach(PROTO_FILE IN LISTS proto_files)
#message(STATUS "protoc proto(cc): ${PROTO_FILE}")
get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY)
get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h)
set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc)
#message(STATUS "protoc hdr: ${PROTO_HDR}")
#message(STATUS "protoc src: ${PROTO_SRC}")
add_custom_command(
OUTPUT ${PROTO_SRC} ${PROTO_HDR}
COMMAND protobuf::protoc
"--proto_path=${PROJECT_SOURCE_DIR}"
${PROTO_DIRS}
"--cpp_out=${PROJECT_BINARY_DIR}"
${PROTO_FILE}
DEPENDS ${PROTO_FILE} protobuf::protoc
COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}"
VERBATIM)
list(APPEND PROTO_HDRS ${PROTO_HDR})
list(APPEND PROTO_SRCS ${PROTO_SRC})
endforeach()
#add_library(${PROJECT_NAME}_proto STATIC ${PROTO_SRCS} ${PROTO_HDRS})
add_library(${PROJECT_NAME}_proto OBJECT ${PROTO_SRCS} ${PROTO_HDRS})
set_target_properties(${PROJECT_NAME}_proto PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD 11)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD_REQUIRED ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_EXTENSIONS OFF)
target_include_directories(${PROJECT_NAME}_proto PRIVATE
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
$<TARGET_PROPERTY:protobuf::libprotobuf,INTERFACE_INCLUDE_DIRECTORIES>
)
target_compile_definitions(${PROJECT_NAME}_proto PUBLIC ${OR_TOOLS_COMPILE_DEFINITIONS})
target_compile_options(${PROJECT_NAME}_proto PUBLIC ${OR_TOOLS_COMPILE_OPTIONS})
#target_link_libraries(${PROJECT_NAME}_proto PRIVATE protobuf::libprotobuf)
add_dependencies(${PROJECT_NAME}_proto protobuf::libprotobuf)
add_library(${PROJECT_NAME}::proto ALIAS ${PROJECT_NAME}_proto)
# Add ortools::proto to libortools
#target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}::proto)
target_sources(${PROJECT_NAME} PRIVATE $<TARGET_OBJECTS:${PROJECT_NAME}::proto>)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}::proto)
foreach(SUBPROJECT IN ITEMS
algorithms base bop constraint_solver data glop graph linear_solver lp_data
port sat util)
add_subdirectory(ortools/${SUBPROJECT})
#target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}::${SUBPROJECT})
target_sources(${PROJECT_NAME} PRIVATE $<TARGET_OBJECTS:${PROJECT_NAME}::${SUBPROJECT}>)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}::${SUBPROJECT})
endforeach()
if(BUILD_TESTING)
add_subdirectory(examples/cpp)
endif()
# Install rules
include(GNUInstallDirs)
# Install builded dependencies
if(INSTALL_BUILD_DEPS)
if( BUILD_ZLIB OR
BUILD_absl OR
BUILD_gflags OR
BUILD_glog OR
BUILD_Protobuf OR
BUILD_CoinUtils OR
BUILD_Osi OR
BUILD_Clp OR
BUILD_Cgl OR
BUILD_Cbc
)
install(
DIRECTORY ${CMAKE_BINARY_DIR}/dependencies/install/
DESTINATION ${CMAKE_INSTALL_PREFIX}
)
endif()
endif()
include(GenerateExportHeader)
GENERATE_EXPORT_HEADER(${PROJECT_NAME})
install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}_export.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
install(DIRECTORY ortools
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel
FILES_MATCHING
PATTERN "*.h")
install(DIRECTORY ${PROJECT_BINARY_DIR}/ortools
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel
FILES_MATCHING
PATTERN "*.pb.h"
PATTERN CMakeFiles EXCLUDE)
include(CMakePackageConfigHelpers)
string (TOUPPER "${PROJECT_NAME}" PACKAGE_PREFIX)
configure_package_config_file(cmake/${PROJECT_NAME}Config.cmake.in
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
)
install(
FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
COMPONENT Devel)