From 8787bfb204e84a999fbfe448224213279bfdbbb7 Mon Sep 17 00:00:00 2001 From: Corentin Le Molgat Date: Wed, 3 Apr 2019 12:54:46 +0200 Subject: [PATCH] Add CMake based build * Fix super build (e.g. FetchContent) integration * cmake: option() honors normal variables (CMP0077) * Add Test --- .gitignore | 4 + CMakeLists.txt | 143 +++++++++++++++++++ Clp/CMakeLists.txt | 253 +++++++++++++++++++++++++++++++++ Clp/config.h.cmake.in | 113 +++++++++++++++ Clp/config_clp.h.cmake.in | 13 ++ Clp/test/CMakeLists.txt | 34 +++++ Clp/test/ClpTest.cpp | 287 ++++++++++++++++++++++++++++++++++++++ cmake/CheckEnv.cmake | 151 ++++++++++++++++++++ cmake/Config.cmake.in | 25 ++++ cmake/ParseAc.cmake | 28 ++++ 10 files changed, 1051 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 Clp/CMakeLists.txt create mode 100644 Clp/config.h.cmake.in create mode 100644 Clp/config_clp.h.cmake.in create mode 100644 Clp/test/CMakeLists.txt create mode 100644 Clp/test/ClpTest.cpp create mode 100644 cmake/CheckEnv.cmake create mode 100644 cmake/Config.cmake.in create mode 100644 cmake/ParseAc.cmake diff --git a/.gitignore b/.gitignore index f28ec2dcb..2e910964f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ aclocal.m4* acinclude.m4 autom4te* +*.swp +.vs/ +build/ +cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..bb95c63bd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,143 @@ +cmake_minimum_required(VERSION 3.16) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +include(ParseAc) +parse_ac(VERSION MAJOR MINOR PATCH) + +project(Clp VERSION ${VERSION} LANGUAGES CXX C) +set(PROJECT_NAMESPACE coin) +message(STATUS "${PROJECT_NAME} version: ${PROJECT_VERSION}") +#message(STATUS "major: ${PROJECT_VERSION_MAJOR}") +#message(STATUS "minor: ${PROJECT_VERSION_MINOR}") +#message(STATUS "patch: ${PROJECT_VERSION_PATCH}") + +# Default Build Type to be Release +get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(isMultiConfig) + if(NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_CONFIGURATION_TYPES "Release;Debug" CACHE STRING + "Choose the type of builds, options are: Debug Release RelWithDebInfo MinSizeRel. (default: Release;Debug)" + FORCE) + endif() + message(STATUS "Configuration types: ${CMAKE_CONFIGURATION_TYPES}") +else() + 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() + message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +endif() + +# Layout build dir like install dir +include(GNUInstallDirs) +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) +if(UNIX) + option(BUILD_SHARED_LIBS "Build shared libraries (.so or .dylib)." ON) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + # for multi-config build system (e.g. Xcode, Ninja Multi-Config) + foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${OutputConfig} OUTPUTCONFIG) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) + endforeach() +else() + # Currently Only support static build for windows + option(BUILD_SHARED_LIBS "Build shared libraries (.dll)." OFF) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + # for multi-config builds (e.g. msvc) + foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${OutputConfig} OUTPUTCONFIG) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) + endforeach() +endif() + +if(MSVC AND BUILD_SHARED_LIBS) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +endif() + +# config options +if(MSVC) + # Build with multiple processes + add_definitions(/MP) + add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_DEPRECATE) + # MSVC warning suppressions + add_definitions( + /wd4018 # 'expression' : signed/unsigned mismatch + /wd4065 # switch statement contains 'default' but no 'case' labels + /wd4101 # 'identifier' : unreferenced local variable + /wd4102 # 'label' : unreferenced label + /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data + /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data + /wd4309 # 'conversion' : truncation of constant value + /wd4805 # 'operation' : unsafe mix of type 'type1' and type 'type2' in operation. + /wd4996 # The compiler encountered a deprecated declaration. + ) +endif() +if(APPLE) + set( + CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override -Wno-unused-command-line-argument -Wno-unused-result -Wno-exceptions" + ) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") +endif() + +# ZLIB +if(NOT TARGET ZLIB::ZLIB) + find_package(ZLIB) +endif() +if(ZLIB_FOUND OR TARGET ZLIB::ZLIB) + message(STATUS "Use zlib") + set(HAVE_ZLIB_H "1" CACHE INTERNAL "Use zlib") + set(COIN_HAS_ZLIB "1" CACHE INTERNAL "Use zlib") +endif() + +# PThread +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads) +if(CMAKE_USE_PTHREADS_INIT) + set(PTHREADS_FOUND TRUE) +else() + set(PTHREADS_FOUND FALSE) +endif() + +# CoinUtils +if(NOT TARGET Coin::CoinUtils) + find_package(CoinUtils REQUIRED CONFIG) +endif() +# Osi +if(NOT TARGET Coin::Osi) + find_package(Osi REQUIRED CONFIG) +endif() + +include(CheckEnv) +include(CTest) + +add_subdirectory(Clp) + +include(GNUInstallDirs) +install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE Coin:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +include(CMakePackageConfigHelpers) +configure_package_config_file(cmake/Config.cmake.in + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +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) diff --git a/Clp/CMakeLists.txt b/Clp/CMakeLists.txt new file mode 100644 index 000000000..8b3b672da --- /dev/null +++ b/Clp/CMakeLists.txt @@ -0,0 +1,253 @@ +set(NAME "CLP") + +# PTHREAD +if(PTHREADS_FOUND) + set(${NAME}_PTHREADS "1" CACHE INTERNAL "Use pthread") +endif() + +set(COIN_${NAME}_CHECKLEVEL "0" CACHE INTERNAL + "${NAME} check level") +set(COIN_${NAME}_VERBOSITY "0" CACHE INTERNAL + "${NAME} verbosity level") +configure_file(config.h.cmake.in config.h) +configure_file(config_clp.h.cmake.in config_clp.h) + +set(_SRCS + src/ClpCholeskyBase.cpp + src/ClpCholeskyDense.cpp + src/ClpConstraint.cpp + src/ClpConstraintLinear.cpp + src/ClpConstraintQuadratic.cpp + src/ClpDualRowDantzig.cpp + src/ClpDualRowPivot.cpp + src/ClpDualRowSteepest.cpp + src/ClpDummyMatrix.cpp + src/ClpDynamicExampleMatrix.cpp + src/ClpDynamicMatrix.cpp + src/ClpEventHandler.cpp + src/ClpFactorization.cpp + src/ClpGubDynamicMatrix.cpp + src/ClpGubMatrix.cpp + src/ClpHelperFunctions.cpp + src/ClpInterior.cpp + src/ClpLinearObjective.cpp + src/ClpLsqr.cpp + src/ClpMatrixBase.cpp + src/ClpMessage.cpp + src/ClpModel.cpp + src/ClpNetworkBasis.cpp + src/ClpNetworkMatrix.cpp + src/ClpNode.cpp + src/ClpNonLinearCost.cpp + src/ClpObjective.cpp + src/ClpPEDualRowDantzig.cpp + src/ClpPEDualRowSteepest.cpp + src/ClpPEPrimalColumnDantzig.cpp + src/ClpPEPrimalColumnSteepest.cpp + src/ClpPESimplex.cpp + src/ClpPackedMatrix.cpp + src/ClpPdco.cpp + src/ClpPdcoBase.cpp + src/ClpPlusMinusOneMatrix.cpp + src/ClpPredictorCorrector.cpp + src/ClpPresolve.cpp + src/ClpPrimalColumnDantzig.cpp + src/ClpPrimalColumnPivot.cpp + src/ClpPrimalColumnSteepest.cpp + src/ClpQuadraticObjective.cpp + src/ClpSimplex.cpp + src/ClpSimplexDual.cpp + src/ClpSimplexNonlinear.cpp + src/ClpSimplexOther.cpp + src/ClpSimplexPrimal.cpp + src/ClpSolve.cpp + src/Clp_C_Interface.cpp + src/IdiSolve.cpp + src/Idiot.cpp + ) + +set(_HDRS + src/ClpCholeskyBase.hpp + src/ClpCholeskyDense.hpp + src/ClpConfig.h + src/ClpConstraint.hpp + src/ClpConstraintLinear.hpp + src/ClpConstraintQuadratic.hpp + src/ClpDualRowDantzig.hpp + src/ClpDualRowPivot.hpp + src/ClpDualRowSteepest.hpp + src/ClpDummyMatrix.hpp + src/ClpDynamicExampleMatrix.hpp + src/ClpDynamicMatrix.hpp + src/ClpEventHandler.hpp + src/ClpFactorization.hpp + src/ClpGubDynamicMatrix.hpp + src/ClpGubMatrix.hpp + src/ClpInterior.hpp + src/ClpLinearObjective.hpp + src/ClpMatrixBase.hpp + src/ClpMessage.hpp + src/ClpModel.hpp + src/ClpNetworkMatrix.hpp + src/ClpNode.hpp + src/ClpNonLinearCost.hpp + src/ClpObjective.hpp + src/ClpPackedMatrix.hpp + src/ClpParameters.hpp + src/ClpPdcoBase.hpp + src/ClpPdco.hpp + src/ClpPEDualRowDantzig.hpp + src/ClpPEDualRowSteepest.hpp + src/ClpPEPrimalColumnDantzig.hpp + src/ClpPEPrimalColumnSteepest.hpp + src/ClpPESimplex.hpp + src/ClpPlusMinusOneMatrix.hpp + src/ClpPresolve.hpp + src/ClpPrimalColumnDantzig.hpp + src/ClpPrimalColumnPivot.hpp + src/ClpPrimalColumnSteepest.hpp + src/ClpQuadraticObjective.hpp + src/ClpSimplex.hpp + src/ClpSimplexDual.hpp + src/ClpSimplexNonlinear.hpp + src/ClpSimplexOther.hpp + src/ClpSimplexPrimal.hpp + src/ClpSolve.hpp + src/Clp_C_Interface.h + src/Idiot.hpp + ) + +include(GNUInstallDirs) + +add_library(Clp ${_SRCS} ${_HDRS}) +target_include_directories(Clp PUBLIC + $ + $ + $) +target_compile_definitions(Clp + PUBLIC HAVE_CONFIG_H + PRIVATE CLP_BUILD COIN_HAS_CLP) +if(CMAKE_VERSION VERSION_LESS "3.8.2") + set_property(TARGET Clp PROPERTY CXX_STANDARD 11) + set_property(TARGET Clp PROPERTY CXX_STANDARD_REQUIRED ON) +else() + target_compile_features(Clp PUBLIC cxx_std_11) +endif() +if(APPLE) + set_target_properties(Clp PROPERTIES INSTALL_RPATH "@loader_path") +elseif(UNIX) + set_target_properties(Clp PROPERTIES INSTALL_RPATH "$ORIGIN") +endif() +target_link_libraries(Clp PUBLIC + Coin::CoinUtils + Coin::Osi) +set_target_properties(Clp PROPERTIES + PUBLIC_HEADER "${_HDRS};src/CbcOrClpParam.cpp;${CMAKE_CURRENT_BINARY_DIR}/config_clp.h" + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}) +add_library(Coin::Clp ALIAS Clp) + +# Install +install(TARGETS Clp + EXPORT ${PROJECT_NAME}Targets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/coin + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + +############## +## OsiClp ## +############## +set(_SRCS src/OsiClp/OsiClpSolverInterface.cpp) +set(_HDRS src/OsiClp/OsiClpSolverInterface.hpp) + +add_library(OsiClp ${_SRCS} ${_HDRS}) +target_include_directories(OsiClp PUBLIC + $ + $) +target_compile_definitions(OsiClp + PUBLIC HAVE_CONFIG_H + PRIVATE CLP_BUILD) +if(CMAKE_VERSION VERSION_LESS "3.8.2") + set_property(TARGET OsiClp PROPERTY CXX_STANDARD 11) + set_property(TARGET OsiClp PROPERTY CXX_STANDARD_REQUIRED ON) +else() + target_compile_features(OsiClp PUBLIC cxx_std_11) +endif() +if(APPLE) + set_target_properties(OsiClp PROPERTIES INSTALL_RPATH "@loader_path") +elseif(UNIX) + set_target_properties(OsiClp PROPERTIES INSTALL_RPATH "$ORIGIN") +endif() +target_link_libraries(OsiClp PUBLIC + Coin::CoinUtils + Coin::Osi + Coin::Clp) +set_target_properties(OsiClp PROPERTIES + PUBLIC_HEADER "${_HDRS}" + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}) +add_library(Coin::OsiClp ALIAS OsiClp) + +# Install +install(TARGETS OsiClp + EXPORT ${PROJECT_NAME}Targets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/coin + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + +################# +## ClpSolver ## +################# +set(_SRCS + src/ClpSolver.cpp + src/CbcOrClpParam.cpp + src/Clp_ampl.cpp + src/MyEventHandler.cpp + src/MyMessageHandler.cpp + src/unitTest.cpp) + +set(_HDRS + src/CbcOrClpParam.hpp + src/Clp_ampl.h + src/MyEventHandler.hpp + src/MyMessageHandler.hpp) + +add_library(ClpSolver ${_SRCS} ${_HDRS}) +target_include_directories(ClpSolver PUBLIC + $ + $) +target_compile_definitions(ClpSolver + PUBLIC HAVE_CONFIG_H + PRIVATE CLP_BUILD COIN_HAS_CLP) +if(CMAKE_VERSION VERSION_LESS "3.8.2") + set_property(TARGET ClpSolver PROPERTY CXX_STANDARD 11) + set_property(TARGET ClpSolver PROPERTY CXX_STANDARD_REQUIRED ON) +else() + target_compile_features(ClpSolver PUBLIC cxx_std_11) +endif() +if(APPLE) + set_target_properties(ClpSolver PROPERTIES INSTALL_RPATH "@loader_path") + target_compile_options(ClpSolver PRIVATE -undefined suppress -flat_namespace) +elseif(UNIX) + set_target_properties(ClpSolver PROPERTIES INSTALL_RPATH "$ORIGIN") +endif() +target_link_libraries(ClpSolver PUBLIC Coin::Clp) +set_target_properties(ClpSolver PROPERTIES + PUBLIC_HEADER "${_HDRS}" + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}) +add_library(Coin::ClpSolver ALIAS ClpSolver) + +# Install +install(TARGETS ClpSolver + EXPORT ${PROJECT_NAME}Targets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/coin + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/Clp/config.h.cmake.in b/Clp/config.h.cmake.in new file mode 100644 index 000000000..c12b3d40c --- /dev/null +++ b/Clp/config.h.cmake.in @@ -0,0 +1,113 @@ +/*config.h. Generated by configure_file.*/ + +#define COIN_HAS_COINUTILS 1 +#define COIN_HAS_OSI 1 + +/* VERSION */ +#define VERSION "${VERSION}" +/* ${NAME}_VERSION */ +#define ${NAME}_VERSION "${VERSION}" +/* ${NAME}_VERSION_MAJOR */ +#define ${NAME}_VERSION_MAJOR ${MAJOR} +/* ${NAME}_VERSION_MINOR */ +#define ${NAME}_VERSION_MINOR ${MINOR} +/* ${NAME}_VERSION_RELEASE */ +#define ${NAME}_VERSION_RELEASE ${PATCH} + +/* HAVE_MATH_H */ +#cmakedefine HAVE_MATH_H ${HAVE_MATH_H} +/* HAVE_CTYPE_H */ +#cmakedefine HAVE_CTYPE_H ${HAVE_CTYPE_H} +/* HAVE_INTTYPES_H */ +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} +/* HAVE_FLOAT_H */ +#cmakedefine HAVE_FLOAT_H ${HAVE_FLOAT_H} +/* HAVE_IEEEFP_H */ +#cmakedefine HAVE_IEEEFP_H ${HAVE_IEEEFP_H} +/* HAVE_STDARG_H */ +#cmakedefine HAVE_STDARG_H ${HAVE_STDARG_H} +/* HAVE_STDDEF_H */ +#cmakedefine HAVE_STDDEF_H ${HAVE_STDDEF_H} +/* HAVE_STDINT_H */ +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} +/* HAVE_STDIO_H */ +#cmakedefine HAVE_STDIO_H ${HAVE_STDIO_H} +/* HAVE_STDLIB_H */ +#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} +/* HAVE_ASSERT_H */ +#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H} +/* HAVE_DLFCN_H */ +#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} +/* HAVE_ENDIAN_H */ +#cmakedefine HAVE_ENDIAN_H ${HAVE_ENDIAN_H} +/* HAVE_MEMORY_H */ +#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} +/* HAVE_STRINGS_H */ +#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} +/* HAVE_STRING_H */ +#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} +/* HAVE_TIME_H */ +#cmakedefine HAVE_TIME_H ${HAVE_TIME_H} +/* HAVE_UNISTD_H */ +#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} +/* HAVE_SYS_STAT_H */ +#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H} +/* HAVE_SYS_TYPES_H */ +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} + +/* HAVE_CMATH */ +#cmakedefine HAVE_CMATH ${HAVE_CMATH} +/* HAVE_CCTYPE */ +#cmakedefine HAVE_CCTYPE ${HAVE_CCTYPE} +/* HAVE_CINTTYPES */ +#cmakedefine HAVE_CINTTYPES ${HAVE_CINTTYPES} +/* HAVE_CFLOAT */ +#cmakedefine HAVE_CFLOAT ${HAVE_CFLOAT} +/* HAVE_CIEEEFP */ +#cmakedefine HAVE_CIEEEFP ${HAVE_CIEEEFP} +/* HAVE_CSTDARG */ +#cmakedefine HAVE_CSTDARG ${HAVE_CSTDARG} +/* HAVE_CSTDDEF */ +#cmakedefine HAVE_CSTDDEF ${HAVE_CSTDDEF} +/* HAVE_CSTDINT */ +#cmakedefine HAVE_CSTDINT ${HAVE_CSTDINT} +/* HAVE_CSTDIO */ +#cmakedefine HAVE_CSTDIO ${HAVE_CSTDIO} +/* HAVE_CSTDLIB */ +#cmakedefine HAVE_CSTDLIB ${HAVE_CSTDLIB} +/* HAVE_CASSERT */ +#cmakedefine HAVE_CASSERT ${HAVE_CASSERT} +/* HAVE_CSTRING */ +#cmakedefine HAVE_CSTRING ${HAVE_CSTRING} +/* HAVE_CTIME */ +#cmakedefine HAVE_CTIME ${HAVE_CTIME} + +/* COIN_C_FINITE */ +#cmakedefine COIN_C_FINITE ${COIN_C_FINITE} +/* COIN_C_ISNAN */ +#cmakedefine COIN_C_ISNAN ${COIN_C_ISNAN} +/* COIN_INT64_T */ +#cmakedefine COIN_INT64_T ${COIN_INT64_T} +/* COIN_UINT64_T */ +#cmakedefine COIN_UINT64_T ${COIN_UINT64_T} +/* COIN_INTPTR_T */ +#cmakedefine COIN_INTPTR_T ${COIN_INTPTR_T} + +/* COIN_${NAME}_CHECKLEVEL */ +#define COIN_${NAME}_CHECKLEVEL ${COIN_${NAME}_CHECKLEVEL} +/* COIN_${NAME}_VERBOSITY */ +#define COIN_${NAME}_VERBOSITY ${COIN_${NAME}_VERBOSITY} + +/* PACKAGE */ +#cmakedefine PACKAGE +/* PACKAGE_NAME */ +#cmakedefine PACKAGE_NAME +/* PACKAGE_VERSION */ +#cmakedefine PACKAGE_VERSION +/* PACKAGE_STRING */ +#cmakedefine PACKAGE_STRING +/* PACKAGE_TARNAME */ +#cmakedefine PACKAGE_TARNAME +/* PACKAGE_BUGREPORT */ +#cmakedefine PACKAGE_BUGREPORT + diff --git a/Clp/config_clp.h.cmake.in b/Clp/config_clp.h.cmake.in new file mode 100644 index 000000000..8dc44bf97 --- /dev/null +++ b/Clp/config_clp.h.cmake.in @@ -0,0 +1,13 @@ +#ifndef __CONFIG_${NAME}_H__ +#define __CONFIG_${NAME}_H__ + +/* ${NAME}_VERSION */ +#define ${NAME}_VERSION "${VERSION}" +/* ${NAME}_VERSION_MAJOR */ +#define ${NAME}_VERSION_MAJOR ${MAJOR} +/* ${NAME}_VERSION_MINOR */ +#define ${NAME}_VERSION_MINOR ${MINOR} +/* ${NAME}_VERSION_RELEASE */ +#define ${NAME}_VERSION_RELEASE ${PATCH} + +#endif diff --git a/Clp/test/CMakeLists.txt b/Clp/test/CMakeLists.txt new file mode 100644 index 000000000..a5093ec10 --- /dev/null +++ b/Clp/test/CMakeLists.txt @@ -0,0 +1,34 @@ + +add_executable(ClpTest "ClpTest.cpp") +target_include_directories(Clp PUBLIC + $ + $) +target_compile_definitions(ClpTest + PUBLIC HAVE_CONFIG_H + PRIVATE CLP_BUILD COIN_HAS_CLP) +if(CMAKE_VERSION VERSION_LESS "3.8.2") + set_property(TARGET ClpTest PROPERTY CXX_STANDARD 11) + set_property(TARGET ClpTest PROPERTY CXX_STANDARD_REQUIRED ON) +else() + target_compile_features(ClpTest PUBLIC cxx_std_11) +endif() +if(APPLE) + set_target_properties(ClpTest PROPERTIES + INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") +elseif(UNIX) + cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR + BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR} + OUTPUT_VARIABLE libdir_relative_path) + set_target_properties(ClpTest PROPERTIES + INSTALL_RPATH "$ORIGIN/${libdir_relative_path}:$ORIGIN") +endif() +target_link_libraries(ClpTest PRIVATE + Coin::CoinUtils + Coin::Osi + Coin::Clp) +set_target_properties(ClpTest PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}) +add_executable(Coin::ClpTest ALIAS ClpTest) + +add_test(NAME ClpTest COMMAND ClpTest) diff --git a/Clp/test/ClpTest.cpp b/Clp/test/ClpTest.cpp new file mode 100644 index 000000000..cd3d68562 --- /dev/null +++ b/Clp/test/ClpTest.cpp @@ -0,0 +1,287 @@ +// This is a simple example to create a model by row +#include "ClpSimplex.hpp" +#include "CoinBuild.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinModel.hpp" +#include "CoinTime.hpp" +#include +#include +#include +#include +#include +#include + +int main(int argc, const char *argv[]) { + std::cout << "coinutils version: " << COINUTILS_VERSION << std::endl; + std::cout << "osi version: " << OSI_VERSION << std::endl; + std::cout << "clp version: " << CLP_VERSION << std::endl; +#if COIN_BIG_INDEX<2 + try { + // Empty model + ClpSimplex model; + + // Objective - just nonzeros + int objIndex[] = {0, 2}; + double objValue[] = {1.0, 4.0}; + // Upper bounds - as dense vector + double upper[] = {2.0, COIN_DBL_MAX, 4.0}; + + // Create space for 3 columns + model.resize(0, 3); + // Fill in + int i; + // Virtuous way + // First objective + for (i = 0; i < 2; i++) + model.setObjectiveCoefficient(objIndex[i], objValue[i]); + // Now bounds (lower will be zero by default but do again) + for (i = 0; i < 3; i++) { + model.setColumnLower(i, 0.0); + model.setColumnUpper(i, upper[i]); + } + /* + We could also have done in non-virtuous way e.g. + double * objective = model.objective(); + and then set directly + */ + // Faster to add rows all at once - but this is easier to show + // Now add row 1 as >= 2.0 + int row1Index[] = {0, 2}; + double row1Value[] = {1.0, 1.0}; + model.addRow(2, row1Index, row1Value, + 2.0, COIN_DBL_MAX); + // Now add row 2 as == 1.0 + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -5.0, 1.0}; + model.addRow(3, row2Index, row2Value, + 1.0, 1.0); + // solve + model.dual(); + + /* + Adding one row at a time has a significant overhead so let's + try a more complicated but faster way + + First time adding in 10000 rows one by one + */ + model.allSlackBasis(); + ClpSimplex modelSave = model; + double time1 = CoinCpuTime(); + int k; + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -5.0, 1.0}; + model.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1); + model.dual(); + model = modelSave; + // Now use build + CoinBuild buildObject; + time1 = CoinCpuTime(); + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -5.0, 1.0}; + buildObject.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + model.addRows(buildObject); + printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1); + model.dual(); + model = modelSave; + int del[] = {0, 1, 2}; + model.deleteRows(2, del); + // Now use build +-1 + CoinBuild buildObject2; + time1 = CoinCpuTime(); + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -1.0, 1.0}; + buildObject2.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + model.addRows(buildObject2, true); + printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1); + model.dual(); + model = modelSave; + model.deleteRows(2, del); + // Now use build +-1 + CoinModel modelObject2; + time1 = CoinCpuTime(); + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -1.0, 1.0}; + modelObject2.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + model.addRows(modelObject2, true); + printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1); + model.dual(); + model = ClpSimplex(); + // Now use build +-1 + CoinModel modelObject3; + time1 = CoinCpuTime(); + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -1.0, 1.0}; + modelObject3.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + model.loadProblem(modelObject3, true); + printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1); + model.writeMps("xx.mps"); + model.dual(); + model = modelSave; + // Now use model + CoinModel modelObject; + time1 = CoinCpuTime(); + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -5.0, 1.0}; + modelObject.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + model.addRows(modelObject); + printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1); + model.dual(); + model.writeMps("b.mps"); + // Method using least memory - but most complicated + time1 = CoinCpuTime(); + // Assumes we know exact size of model and matrix + // Empty model + ClpSimplex model2; + { + // Create space for 3 columns and 10000 rows + int numberRows = 10000; + int numberColumns = 3; + // This is fully dense - but would not normally be so + int numberElements = numberRows * numberColumns; + // Arrays will be set to default values + model2.resize(numberRows, numberColumns); + double * elements = new double [numberElements]; + CoinBigIndex * starts = new CoinBigIndex [numberColumns+1]; + int * rows = new int [numberElements];; + int * lengths = new int[numberColumns]; + // Now fill in - totally unsafe but .... + // no need as defaults to 0.0 double * columnLower = model2.columnLower(); + double * columnUpper = model2.columnUpper(); + double * objective = model2.objective(); + double * rowLower = model2.rowLower(); + double * rowUpper = model2.rowUpper(); + // Columns - objective was packed + for (k = 0; k < 2; k++) { + int iColumn = objIndex[k]; + objective[iColumn] = objValue[k]; + } + for (k = 0; k < numberColumns; k++) + columnUpper[k] = upper[k]; + // Rows + for (k = 0; k < numberRows; k++) { + rowLower[k] = 1.0; + rowUpper[k] = 1.0; + } + // Now elements + double row2Value[] = {1.0, -5.0, 1.0}; + CoinBigIndex put = 0; + for (k = 0; k < numberColumns; k++) { + starts[k] = put; + lengths[k] = numberRows; + double value = row2Value[k]; + for (int i = 0; i < numberRows; i++) { + rows[put] = i; + elements[put] = value; + put++; + } + } + starts[numberColumns] = put; + // assign to matrix + CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0); + matrix->assignMatrix(true, numberRows, numberColumns, numberElements, + elements, rows, starts, lengths); + ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix); + model2.replaceMatrix(clpMatrix, true); + printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1); + // If matrix is really big could switch off creation of row copy + // model2.setSpecialOptions(256); + } + model2.dual(); + model2.writeMps("a.mps"); + // Print column solution + int numberColumns = model.numberColumns(); + + // Alternatively getColSolution() + double * columnPrimal = model.primalColumnSolution(); + // Alternatively getReducedCost() + double * columnDual = model.dualColumnSolution(); + // Alternatively getColLower() + double * columnLower = model.columnLower(); + // Alternatively getColUpper() + double * columnUpper = model.columnUpper(); + // Alternatively getObjCoefficients() + double * columnObjective = model.objective(); + + int iColumn; + + std::cout << " Primal Dual Lower Upper Cost" + << std::endl; + + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + double value; + std::cout << std::setw(6) << iColumn << " "; + value = columnPrimal[iColumn]; + if (fabs(value) < 1.0e5) + std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; + else + std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; + value = columnDual[iColumn]; + if (fabs(value) < 1.0e5) + std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; + else + std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; + value = columnLower[iColumn]; + if (fabs(value) < 1.0e5) + std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; + else + std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; + value = columnUpper[iColumn]; + if (fabs(value) < 1.0e5) + std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; + else + std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; + value = columnObjective[iColumn]; + if (fabs(value) < 1.0e5) + std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; + else + std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; + + std::cout << std::endl; + } + std::cout << "--------------------------------------" << std::endl; + // Test CoinAssert + std::cout << "If Clp compiled without NDEBUG below should give assert, if with NDEBUG or COIN_ASSERT CoinError" << std::endl; + model = modelSave; + model.deleteRows(2, del); + // Deliberate error + model.deleteColumns(1, del + 2); + // Now use build +-1 + CoinBuild buildObject3; + time1 = CoinCpuTime(); + for (k = 0; k < 10000; k++) { + int row2Index[] = {0, 1, 2}; + double row2Value[] = {1.0, -1.0, 1.0}; + buildObject3.addRow(3, row2Index, row2Value, + 1.0, 1.0); + } + model.addRows(buildObject3, true); + } catch (CoinError e) { + e.print(); + if (e.lineNumber() >= 0) + std::cout << "This was from a CoinAssert" << std::endl; + } +#else + printf("addRows not available with COIN_BIG_INDEX=2\n"); +#endif + return 0; +} + diff --git a/cmake/CheckEnv.cmake b/cmake/CheckEnv.cmake new file mode 100644 index 000000000..b24770250 --- /dev/null +++ b/cmake/CheckEnv.cmake @@ -0,0 +1,151 @@ +# Flags +include (CheckIncludeFile) +check_include_file(math.h HAVE_MATH_H) +check_include_file(ctype.h HAVE_CTYPE_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(float.h HAVE_FLOAT_H) +check_include_file(ieeefp.h HAVE_IEEEFP_H) +check_include_file(stdarg.h HAVE_STDARG_H) +check_include_file(stddef.h HAVE_STDDEF_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stdio.h HAVE_STDIO_H) +check_include_file(stdlib.h HAVE_STDLIB_H) +check_include_file(assert.h HAVE_ASSERT_H) +check_include_file(dlfcn.h HAVE_DLFCN_H) +check_include_file(endian.h HAVE_ENDIAN_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(strings.h HAVE_STRINGS_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(time.h HAVE_TIME_H) +check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) + +include (CheckIncludeFileCXX) +check_include_file_cxx(cmath HAVE_CMATH) +check_include_file_cxx(cctype HAVE_CCTYPE) +check_include_file_cxx(cinttypes HAVE_CINTTYPES) +check_include_file_cxx(cfloat HAVE_CFLOAT) +check_include_file_cxx(cieeefp HAVE_CIEEEFP) +check_include_file_cxx(cstdarg HAVE_CSTDARG) +check_include_file_cxx(cstddef HAVE_CSTDDEF) +check_include_file_cxx(cstdint HAVE_CSTDINT) +check_include_file_cxx(cstdio HAVE_CSTDIO) +check_include_file_cxx(cstdlib HAVE_CSTDLIB) +check_include_file_cxx(cassert HAVE_CASSERT) +check_include_file_cxx(cstring HAVE_CSTRING) +check_include_file_cxx(ctime HAVE_CTIME) + +set(STDC_HEADERS 1 CACHE INTERNAL "System has ANSI C header files") + +set(TEST_INCLUDES "") +if(HAVE_CMATH) + list(APPEND TEST_INCLUDES "cmath") +endif() +if(HAVE_CFLOAT) + list(APPEND TEST_INCLUDES "cfloat") +endif() +if(HAVE_CIEEEFP) + list(APPEND TEST_INCLUDES "cieeefp") +endif() +if(HAVE_MATH_H) + list(APPEND TEST_INCLUDES "math.h") +endif() +if(HAVE_FLOAT_H) + list(APPEND TEST_INCLUDES "float.h") +endif() +if(HAVE_IEEEFP_H) + list(APPEND TEST_INCLUDES "ieeefp.h") +endif() + +# ISFINITE +include(CheckCXXSourceCompiles) +check_cxx_source_compiles( + "#include \nint main(){return std::isfinite(0);}" + HAVE_STD_ISFINITE) +include(CheckFunctionExists) +include(CheckCXXSymbolExists) +check_cxx_symbol_exists(isfinite "${TEST_INCLUDES}" HAVE_ISFINITE) +check_cxx_symbol_exists(finite "${TEST_INCLUDES}" HAVE_FINITE) +check_cxx_symbol_exists(_finite "${TEST_INCLUDES}" HAVE__FINITE) +check_cxx_symbol_exists(__finite "${TEST_INCLUDES}" HAVE___FINITE) +if(HAVE_STD_ISFINITE) + set(COIN_C_FINITE "std::isfinite") +elseif(HAVE_ISFINITE) + set(COIN_C_FINITE "isfinite") +elseif(HAVE_FINITE) + set(COIN_C_FINITE "finite") +elseif(HAVE__FINITE) + set(COIN_C_FINITE "_finite") +elseif(HAVE___FINITE) + set(COIN_C_FINITE "__finite") +else() + message(FATAL_ERROR "Can't find isfinite()") +endif() +message(STATUS "Found isfinite: ${COIN_C_FINITE}") + +# ISNAN +include(CheckCXXSourceCompiles) +check_cxx_source_compiles( + "#include \nint main(){return std::isnan(0);}" + HAVE_STD_ISNAN) +include(CheckFunctionExists) +include(CheckCXXSymbolExists) +check_cxx_symbol_exists(isnan "${TEST_INCLUDES}" HAVE_ISNAN) +check_cxx_symbol_exists(_isnan "${TEST_INCLUDES}" HAVE__ISNAN) +check_cxx_symbol_exists(__isnan "${TEST_INCLUDES}" HAVE___ISNAN) +if(HAVE_STD_ISNAN) + set(COIN_C_ISNAN "std::isnan") +elseif(HAVE_ISNAN) + set(COIN_C_ISNAN "isnan") +elseif(HAVE__ISNAN) + set(COIN_C_ISNAN "_isnan") +elseif(HAVE___ISNAN) + set(COIN_C_ISNAN "__isnan") +else() + message(FATAL_ERROR "Can't find isnan()") +endif() +message(STATUS "Found isnan: ${COIN_C_ISNAN}") + +# Basic type +include(CheckTypeSize) +check_type_size("int64_t" SIZEOF_INT64_T) +check_type_size("long long" SIZEOF_LONG_LONG) +check_type_size("long" SIZEOF_LONG) +check_type_size("uint64_t" SIZEOF_UINT64_T) +check_type_size("unsigned long long" SIZEOF_ULONG_LONG) +check_type_size("unsigned long" SIZEOF_ULONG) +check_type_size("intptr_t" SIZEOF_INTPTR_T) +check_type_size("int *" SIZEOF_INT_P) + +if(SIZEOF_INT64_T EQUAL "8") + set(COIN_INT64_T "int64_t") +elseif(SIZEOF_LONG EQUAL "8") + set(COIN_INT64_T "long") +elseif(SIZEOF_LONG_LONG EQUAL "8") + set(COIN_INT64_T "long long") +else() + message(FATAL_ERROR "Can't find suitable int64_t") +endif() +message(STATUS "Found int64_t: ${COIN_INT64_T}") + +if(SIZEOF_UINT64_T EQUAL "8") + set(COIN_UINT64_T "uint64_t") +elseif(SIZEOF_ULONG EQUAL "8") + set(COIN_INT64_T "unsigned long") +elseif(SIZEOF_ULONG_LONG EQUAL "8") + set(COIN_INT64_T "unsigned long long") +else() + message(FATAL_ERROR "Can't find suitable uint64_t") +endif() +message(STATUS "Found uint64_t: ${COIN_UINT64_T}") + +if(SIZEOF_INTPTR_T) + set(COIN_INTPTR_T "intptr_t") +elseif(SIZEOF_INT_P) + set(COIN_INTPTR_T "int *") +else() + message(FATAL_ERROR "Can't find suitable intptr_t") +endif() +message(STATUS "Found intptr_t: ${COIN_INTPTR_T}") + diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in new file mode 100644 index 000000000..bd22be92f --- /dev/null +++ b/cmake/Config.cmake.in @@ -0,0 +1,25 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +if(@ZLIB_FOUND@) + find_dependency(ZLIB REQUIRED) +endif() + +if(@PTHREADS_FOUND@) + find_dependency(Threads REQUIRED) +endif() + +if(${CMAKE_VERSION} VERSION_LESS "3.9.6") + find_dependency(CoinUtils REQUIRED) +else() + find_dependency(CoinUtils REQUIRED CONFIG) +endif() + +if(${CMAKE_VERSION} VERSION_LESS "3.9.6") + find_dependency(Osi REQUIRED) +else() + find_dependency(Osi REQUIRED CONFIG) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/cmake/ParseAc.cmake b/cmake/ParseAc.cmake new file mode 100644 index 000000000..aefb9c4ca --- /dev/null +++ b/cmake/ParseAc.cmake @@ -0,0 +1,28 @@ +function(parse_ac VERSION_STRING VERSION_MAJOR VERSION_MINOR VERSION_PATCH) + file(READ "configure.ac" IN) + if(IN MATCHES "AC_INIT\\(.*trunk.*\\)") + message(WARNING "using trunk...") + set(MAJOR 999) + set(MINOR 0) + set(PATCH 0) + else() + # AC_INIT([Clp],[major.minor.patch or trunk],[url or email]) + string(REGEX MATCH + "AC_INIT\\([^,]+,\\[([0-9]+)\\.([0-9]+)(\\.([0-9]+))?\\],[^\\)]+\\)" AC_INIT ${IN}) + message(STATUS "AC_INIT: ${AC_INIT}") + set(MAJOR ${CMAKE_MATCH_1}) + set(MINOR ${CMAKE_MATCH_2}) + if(CMAKE_MATCH_3) + set(PATCH ${CMAKE_MATCH_4}) + else() + set(PATCH 0) + endif() + endif() + set(VERSION "${MAJOR}.${MINOR}.${PATCH}") + + set(${VERSION_MAJOR} ${MAJOR} PARENT_SCOPE) + set(${VERSION_MINOR} ${MINOR} PARENT_SCOPE) + set(${VERSION_PATCH} ${PATCH} PARENT_SCOPE) + set(${VERSION_STRING} ${VERSION} PARENT_SCOPE) + message(STATUS "version: ${VERSION}") +endfunction()