From d5efdc31adb855e12effb032113cb0d56993f622 Mon Sep 17 00:00:00 2001 From: Brendan O'Donoghue Date: Mon, 10 Jan 2022 17:39:45 +0000 Subject: [PATCH] improve cmake build system --- .github/workflows/build.yml | 11 ++++--- CMakeLists.txt | 56 ++++++++++++++++++++++++++++++---- cmake/scs_types.h.in | 22 +++++++++++++ docs/src/api/compile_flags.rst | 2 +- docs/src/examples/qp.c | 4 ++- docs/src/examples/qp.c.out | 8 ++--- docs/src/install/c.rst | 14 +++++++-- include/glbopts.h | 12 -------- include/scs.h | 14 +++++++++ test/run_tests.c | 10 +++++- 10 files changed, 122 insertions(+), 31 deletions(-) create mode 100644 cmake/scs_types.h.in diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 56b8533f..005e8485 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,14 +3,17 @@ name: Build on: [push, pull_request] +matrix: + long: [0, 1] + jobs: linux: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - run: sudo apt-get install libopenblas-dev liblapack-dev - - run: make - - run: make test + - run: make DLONG=${{ matrix.long }} + - run: make test DLONG=${{ matrix.long }} - run: out/run_tests_direct # test direct solver - run: out/run_tests_indirect # test indirect solver @@ -27,7 +30,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: brew install openblas lapack - - run: make - - run: make test + - run: make DLONG=${{ matrix.long }} + - run: make test DLONG=${{ matrix.long }} - run: out/run_tests_direct # test direct solver - run: out/run_tests_indirect # test indirect solver diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eff046e..391b1946 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,10 @@ if(BUILD_TESTING) enable_testing() endif() +# Add uninstall target +# After 'make install' can run 'make uninstall' to remove. +include(AddUninstallTarget) + ### Some variables useful for sampling the building process # Note that the GPU profile is not compiled. set(LINSYS linsys) @@ -95,6 +99,44 @@ set(DIRSRC ${LINSYS}/cpu/direct) set(INDIRSRC ${LINSYS}/cpu/indirect) set(EXTERNAL ${LINSYS}/external) +# Options +# ---------------------------------------------- +# Use floats instead of doubles +option(SFLOAT "Use single precision floats rather than doubles" OFF) +message(STATUS "Single precision floats (32bit) are ${SFLOAT}") + +# Use long integers for indexing +option(DLONG "Use long integers (64bit) for indexing" OFF) +message(STATUS "Long integers (64bit) are ${DLONG}") + + +set(COMPILER_OPTS "-DUSE_LAPACK -DCOPYAMATRIX -DCTRLC") + +# Primitive types +if(SFLOAT) + set(SCS_FLOAT_TYPE "float") + set(COMPILER_OPTS "-DSFLOAT ${COMPILER_OPTS}") +else() + set(SCS_FLOAT_TYPE "double") +endif() + +if(DLONG) + set(SCS_INT_TYPE "long long") + set(COMPILER_OPTS "-DDLONG ${COMPILER_OPTS}") +else() + set(SCS_INT_TYPE "int") +endif() + +message(STATUS "COMPILER_OPTS = ${COMPILER_OPTS}") + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/scs_types.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/include/scs_types.h + NEWLINE_STYLE LF) + +# Public headers +set(${PROJECT_NAME}_PUBLIC_HDR + include/scs_types.h + include/scs.h) # Common source files set(${PROJECT_NAME}_SRC @@ -164,7 +206,7 @@ target_include_directories(${${PROJECT_NAME}_DIRECT} PUBLIC "$") # Compiled with blas and lapack, can solve LPs, SOCPs, SDPs, ECPs, and PCPs -target_compile_definitions(${${PROJECT_NAME}_DIRECT} PRIVATE -DUSE_LAPACK -DCOPYAMATRIX -DCTRLC) +target_compile_definitions(${${PROJECT_NAME}_DIRECT} PRIVATE ${COMPILER_OPTS}) # The library depends on math (m) blas and lapack target_link_libraries(${${PROJECT_NAME}_DIRECT} PRIVATE @@ -175,7 +217,7 @@ target_link_libraries(${${PROJECT_NAME}_DIRECT} PRIVATE # Set some properties set_target_properties(${${PROJECT_NAME}_DIRECT} PROPERTIES VERSION ${scs_VERSION} - PUBLIC_HEADER "${${PROJECT_NAME}_HDR}") + PUBLIC_HEADER "${${PROJECT_NAME}_PUBLIC_HDR}") add_library(scs::${${PROJECT_NAME}_DIRECT} ALIAS ${${PROJECT_NAME}_DIRECT}) @@ -211,7 +253,7 @@ target_include_directories(${${PROJECT_NAME}_INDIRECT} PUBLIC "$") # Compiled with blas and lapack, can solve LPs, SOCPs, SDPs, ECPs, and PCPs -target_compile_definitions(${${PROJECT_NAME}_INDIRECT} PRIVATE -DUSE_LAPACK -DCOPYAMATRIX -DCTRLC -DINDIRECT) +target_compile_definitions(${${PROJECT_NAME}_INDIRECT} PRIVATE ${COMPILER_OPTS} -DINDIRECT) # The library depends on math (m) blas and lapack target_link_libraries(${${PROJECT_NAME}_INDIRECT} PUBLIC @@ -222,7 +264,7 @@ target_link_libraries(${${PROJECT_NAME}_INDIRECT} PUBLIC # Set some properties set_target_properties(${${PROJECT_NAME}_INDIRECT} PROPERTIES VERSION ${scs_VERSION} - PUBLIC_HEADER "${${${PROJECT_NAME}_INDIRECT}_HDR}") + PUBLIC_HEADER "${${PROJECT_NAME}_PUBLIC_HDR}") add_library(scs::${${PROJECT_NAME}_INDIRECT} ALIAS ${${PROJECT_NAME}_INDIRECT}) @@ -252,20 +294,22 @@ install_basic_package_files(${PROJECT_NAME} ### Add the tests if(BUILD_TESTING) add_executable(run_tests_direct test/run_tests.c) + target_compile_definitions(run_tests_direct PRIVATE ${COMPILER_OPTS}) target_link_libraries(run_tests_direct PRIVATE scs::scsdir) target_include_directories(run_tests_direct PRIVATE - "$") + "$" ) add_test(NAME run_tests_direct COMMAND run_tests_direct WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) add_executable(run_tests_indirect test/run_tests.c) + target_compile_definitions(run_tests_indirect PRIVATE ${COMPILER_OPTS}) target_link_libraries(run_tests_indirect PRIVATE scs::scsindir) target_include_directories(run_tests_indirect PRIVATE - "$") + "$" ) add_test(NAME run_tests_indirect COMMAND run_tests_indirect diff --git a/cmake/scs_types.h.in b/cmake/scs_types.h.in new file mode 100644 index 00000000..aca4ae35 --- /dev/null +++ b/cmake/scs_types.h.in @@ -0,0 +1,22 @@ +/* + * GENERATED BY CMAKE + */ + +/* + * Definitions of primitive types used in SCS. + */ + +#ifndef SCS_TYPES_H_GUARD +#define SCS_TYPES_H_GUARD + +#ifdef __cplusplus +extern "C" { +#endif + +typedef @SCS_INT_TYPE@ scs_int; +typedef @SCS_FLOAT_TYPE@ scs_float; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/docs/src/api/compile_flags.rst b/docs/src/api/compile_flags.rst index ea112064..e837f240 100644 --- a/docs/src/api/compile_flags.rst +++ b/docs/src/api/compile_flags.rst @@ -23,7 +23,7 @@ executing, e.g., :code:`make DLONG=1`, to set the :code:`DLONG` flag to True. - True/False - 0 * - :code:`SFLOAT` - - If True use 32 bit floats, else 64 bit + - If True use 32 bit floats, else 64 bit (WARNING: currently broken) - True/False - 0 * - :code:`CTRLC` diff --git a/docs/src/examples/qp.c b/docs/src/examples/qp.c index e30b985a..44d54f13 100644 --- a/docs/src/examples/qp.c +++ b/docs/src/examples/qp.c @@ -1,4 +1,6 @@ -#include "scs.h" /* SCS API */ +#include "scs.h" /* SCS API */ +#include /* printf */ +#include /* memory allocation */ /* Set up and solve basic qp */ int main(int argc, char **argv) { diff --git a/docs/src/examples/qp.c.out b/docs/src/examples/qp.c.out index 6ad869dc..206bab34 100644 --- a/docs/src/examples/qp.c.out +++ b/docs/src/examples/qp.c.out @@ -13,12 +13,12 @@ lin-sys: sparse-direct ------------------------------------------------------------------ iter | pri res | dua res | gap | obj | scale | time (s) ------------------------------------------------------------------ - 0| 1.78e+00 1.00e+00 1.42e+00 -1.04e+00 1.00e-01 2.28e-05 - 175| 3.34e-11 4.17e-10 4.07e-10 1.24e+00 2.08e+01 4.26e-04 + 0| 1.78e+00 1.00e+00 1.42e+00 -1.04e+00 1.00e-01 2.14e-05 + 175| 3.34e-11 4.17e-10 4.07e-10 1.24e+00 2.08e+01 1.25e-04 ------------------------------------------------------------------ status: solved -timings: total: 1.17e-03s = setup: 7.40e-04s + solve: 4.28e-04s - lin-sys: 3.06e-05s, cones: 1.57e-05s, accel: 2.42e-05s +timings: total: 2.01e-04s = setup: 7.52e-05s + solve: 1.26e-04s + lin-sys: 2.56e-05s, cones: 1.43e-05s, accel: 2.20e-05s ------------------------------------------------------------------ objective = 1.235000 ------------------------------------------------------------------ diff --git a/docs/src/install/c.rst b/docs/src/install/c.rst index ef88d4d9..3aa48c86 100644 --- a/docs/src/install/c.rst +++ b/docs/src/install/c.rst @@ -35,6 +35,15 @@ project, please call the following command make ctest +Some :ref:`compile flags ` can be overridden using the +command line, for example we can compile the library (and headers) to use 64 bit +integers using: + +.. code:: bash + + cmake -DCMAKE_INSTALL_PREFIX:PATH= -DDLONG=ON ../ + make + By default the build-system will compile the library as shared. If you want to compile it as static, please call the following command when you configure the project @@ -45,8 +54,9 @@ project make The CMake build-system exports two CMake targets called :code:`scs::scsdir` and -:code:`scs::scsindir` which can be imported using the find_package CMake command and -used by calling target_link_libraries as in the following example: +:code:`scs::scsindir` as well as a header file `scs.h` that defines the API. The +libraries can be imported using the find_package CMake command and used by +calling target_link_libraries as in the following example: .. code:: bash diff --git a/include/glbopts.h b/include/glbopts.h index 957c1efb..04608df5 100644 --- a/include/glbopts.h +++ b/include/glbopts.h @@ -16,18 +16,6 @@ extern "C" { #define SCS_VERSION \ ("3.0.0") /* string literals automatically null-terminated */ -/* SCS returns one of the following integers: */ -#define SCS_INFEASIBLE_INACCURATE (-7) -#define SCS_UNBOUNDED_INACCURATE (-6) -#define SCS_SIGINT (-5) -#define SCS_FAILED (-4) -#define SCS_INDETERMINATE (-3) -#define SCS_INFEASIBLE (-2) /* primal infeasible, dual unbounded */ -#define SCS_UNBOUNDED (-1) /* primal unbounded, dual infeasible */ -#define SCS_UNFINISHED (0) /* never returned, used as placeholder */ -#define SCS_SOLVED (1) -#define SCS_SOLVED_INACCURATE (2) - /* verbosity level */ #ifndef VERBOSITY #define VERBOSITY (0) diff --git a/include/scs.h b/include/scs.h index e03f38e7..8d1641c8 100644 --- a/include/scs.h +++ b/include/scs.h @@ -22,6 +22,20 @@ typedef struct SCS_LIN_SYS_WORK ScsLinSysWork; /** Struct containing SCS workspace. Implemented in `scs_work.h`. */ typedef struct SCS_WORK ScsWork; + +/* SCS returns one of the following integer exit flags: */ +#define SCS_INFEASIBLE_INACCURATE (-7) +#define SCS_UNBOUNDED_INACCURATE (-6) +#define SCS_SIGINT (-5) +#define SCS_FAILED (-4) +#define SCS_INDETERMINATE (-3) +#define SCS_INFEASIBLE (-2) /* primal infeasible, dual unbounded */ +#define SCS_UNBOUNDED (-1) /* primal unbounded, dual infeasible */ +#define SCS_UNFINISHED (0) /* never returned, used as placeholder */ +#define SCS_SOLVED (1) +#define SCS_SOLVED_INACCURATE (2) + + /** This defines the data matrices which should be supplied in compressed * sparse column format with zero based indexing. */ diff --git a/test/run_tests.c b/test/run_tests.c index bfb5026d..65384839 100644 --- a/test/run_tests.c +++ b/test/run_tests.c @@ -11,13 +11,21 @@ #include "problems/hs21_tiny_qp_rw.h" #include "problems/infeasible_tiny_qp.h" #include "problems/qafiro_tiny_qp.h" -#include "problems/random_prob.h" #include "problems/rob_gauss_cov_est.h" #include "problems/small_lp.h" #include "problems/small_qp.h" #include "problems/test_validation.h" #include "problems/unbounded_tiny_qp.h" +#ifndef DLONG /* TODO: this reads a file written with 32bit ints */ +#include "problems/random_prob.h" +#else +char * random_prob(void) { + scs_printf("skipped\n"); + return 0; +} +#endif + int tests_run = 0; static const char *all_tests(void) {