blob: afd7bb9407ec7b07b445a05e390cb03d46c07029 [file] [log] [blame]
Austin Schuh9049e202022-02-20 17:34:16 -08001# Minimum version required
2cmake_minimum_required (VERSION 3.2)
3
4# Project name
5project (osqp)
6
7set(OSQP_VERSION "0.0.0" CACHE STRING "The version number of OSQP")
8if(NOT OSQP_VERSION STREQUAL "0.0.0")
9 configure_file (
10 "${PROJECT_SOURCE_DIR}/configure/version.h.in"
11 "${PROJECT_SOURCE_DIR}/include/version.h"
12 )
13endif()
14
15# Export compile commands
16set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
17
18# Set the output folder where your program will be created
19set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/out)
20set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/out)
21
22# Some non-standard CMake modules
23LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/configure/cmake)
24INCLUDE(FindPythonModule)
25INCLUDE(Utils)
26# include(FindMKL) # Find MKL module
27
28
29# Detect operating system
30# ----------------------------------------------
31message(STATUS "We are on a ${CMAKE_SYSTEM_NAME} system")
32if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
33 set(IS_LINUX ON)
34elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
35 set(IS_MAC ON)
36elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
37 set(IS_WINDOWS ON)
38endif()
39
40
41
42# Set options
43# ----------------------------------------------
44
45# Are unittests generated?
46option (UNITTESTS "Enable unittests generation" OFF)
47
48# Is the code generated for embedded platforms?
49# 1 : Yes. Matrix update not allowed.
50# 2 : Yes. Matrix update allowed.
51if (NOT DEFINED EMBEDDED)
52 message(STATUS "Embedded is OFF")
53else()
54 message(STATUS "Embedded is ${EMBEDDED}")
55endif()
56
57# Is printing enabled?
58option (PRINTING "Enable solver printing" ON)
59if (DEFINED EMBEDDED)
60 message(STATUS "Disabling printing for embedded")
61 set(PRINTING OFF)
62endif()
63message(STATUS "Printing is ${PRINTING}")
64
65
66# Is profiling enabled?
67option (PROFILING "Enable solver profiling (timing)" ON)
68if (DEFINED EMBEDDED)
69 message(STATUS "Disabling profiling for embedded")
70 set(PROFILING OFF)
71endif()
72message(STATUS "Profiling is ${PROFILING}")
73
74# Is user interrupt enabled?
75option (CTRLC "Enable user interrupt (Ctrl-C)" ON)
76if (DEFINED EMBEDDED)
77 message(STATUS "Disabling user interrupt for embedded")
78 set(CTRLC OFF)
79endif()
80message(STATUS "User interrupt is ${CTRLC}")
81
82# Use floats instead of integers
83option (DFLOAT "Use float numbers instead of doubles" OFF)
84message(STATUS "Floats are ${DFLOAT}")
85
86# Use long integers for indexing
87option (DLONG "Use long integers (64bit) for indexing" ON)
88if (NOT (CMAKE_SIZEOF_VOID_P EQUAL 8))
89 message(STATUS "Disabling long integers (64bit) on 32bit machine")
90 set(DLONG OFF)
91endif()
92message(STATUS "Long integers (64bit) are ${DLONG}")
93
94
95option (DEBUG "Debug mode" OFF)
96if (CMAKE_BUILD_TYPE STREQUAL "Debug")
97 set (DEBUG ON)
98 message(STATUS "Debug mode is ${DEBUG}")
99endif()
100
101# Add code coverage
102option (COVERAGE "Perform code coverage" OFF)
103message(STATUS "Code coverage is ${COVERAGE}")
104
105
106# Memory allocators
107# ----------------------------------------------
108
109#Report on custom user header options. This is intended to allow
110#users to provide definitions of their own memory functions
111# The header should define the functions as follows
112#
113# define c_malloc mymalloc
114# define c_calloc mycalloc
115# define c_realloc myrealloc
116# define c_free myfree
117
118if(OSQP_CUSTOM_MEMORY)
119 message(STATUS "User custom memory management header: ${OSQP_CUSTOM_MEMORY}")
120endif()
121
122
123
124# Linear solvers dependencies
125# ---------------------------------------------
126option (ENABLE_MKL_PARDISO "Enable MKL Pardiso solver" ON)
127if (DFLOAT)
128 message(STATUS "Disabling MKL Pardiso Solver with floats")
129 set(ENABLE_MKL_PARDISO OFF)
130elseif(DEFINED EMBEDDED)
131 message(STATUS "Disabling MKL Pardiso Solver for embedded")
132 set(ENABLE_MKL_PARDISO OFF)
133endif()
134message(STATUS "MKL Pardiso: ${ENABLE_MKL_PARDISO}")
135
136
137# Generate header file with the global options
138# ---------------------------------------------
139configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure/osqp_configure.h.in
140 ${CMAKE_CURRENT_SOURCE_DIR}/include/osqp_configure.h
141 NEWLINE_STYLE LF)
142
143# Set Compiler flags
144# ----------------------------------------------
145set(CMAKE_POSITION_INDEPENDENT_CODE ON) # -fPIC
146
147
148if (NOT MSVC)
149
150 if (COVERAGE)
151 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
152 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
153 if(FORTRAN)
154 set(CMAKE_FORTRAN_FLAGS "${CMAKE_FORTRAN_FLAGS} --coverage")
155 endif(FORTRAN)
156 endif()
157
158 if (DEBUG)
159 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g")
160 else()
161 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
162 endif()
163
164 set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lm") # Include math
165 # Include real time library in linux
166 if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
167 set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lrt -ldl")
168 endif()
169endif (NOT MSVC)
170
171# Set sources and includes
172# ----------------------------------------------
173add_subdirectory (src)
174add_subdirectory (include)
175
176
177# if we are building the Python interface, let's look for Python
178# and set some options
179# -----------------------------------------------------------------
180if (PYTHON)
181
182 # Python include directories need to be passed by the python compilation process
183 if (NOT PYTHON_INCLUDE_DIRS)
184 message( FATAL_ERROR "You need Python include directories to build the Python interface" )
185 endif (NOT PYTHON_INCLUDE_DIRS)
186
187 # Include directories for Python headers
188 include_directories(${PYTHON_INCLUDE_DIRS})
189
190 # Pass PYTHON flag to C compiler
191 add_definitions(-DPYTHON)
192
193 if (UNITTESTS)
194 # Disable unittests
195 message(STATUS "Disabling UNITTESTS because we are building Python interface")
196 set(UNITTESTS OFF)
197 endif (UNITTESTS)
198
199endif (PYTHON)
200
201
202# if we are building the Matlab interface, let's look for Matlab
203# and set some options
204# -----------------------------------------------------------------
205if (MATLAB)
206
207 find_package(Matlab)
208
209 if (NOT Matlab_FOUND)
210 message( FATAL_ERROR "You need Matlab libraries to build the Matlab interface" )
211 endif (NOT Matlab_FOUND)
212
213 # Include directories for Matlab headers
214 include_directories(${Matlab_INCLUDE_DIRS})
215
216 message(STATUS "Matlab root is " ${Matlab_ROOT_DIR})
217
218 # Pass MATLAB flag to C compiler
219 add_definitions(-DMATLAB)
220
221 # Insist on the pre 2018 complex data API
222 # so that mxGetPr will work correctly
223 add_definitions(-DMATLAB_MEXSRC_RELEASE=R2017b)
224
225 message(STATUS "Using Matlab pre-2018a API for mxGetPr compatibility")
226
227 if (UNITTESTS)
228 # Disable unittests
229 message(STATUS "Disabling UNITTESTS because we are building Matlab interface")
230 set(UNITTESTS OFF)
231 endif (UNITTESTS)
232
233endif (MATLAB)
234
235# if we are building the R interface, let's look for R
236# and set some options
237# -----------------------------------------------------------------
238if (R_LANG)
239
240 message(STATUS "We are building the R interface")
241
242 # Look for R libraries
243 find_package(R)
244
245 if (NOT R_FOUND)
246 message( FATAL_ERROR "You need R libraries to build the R interface" )
247 endif (NOT R_FOUND)
248
249 message(STATUS "R exec is: " ${R_EXEC})
250 message(STATUS "R root dir is: " ${R_ROOT_DIR})
251 message(STATUS "R includes are in: " ${R_INCLUDE_DIRS})
252
253 # Include directories for R headers
254 include_directories(${R_INCLUDE_DIRS})
255
256 # Pass R_LANG flag to C compiler
257 add_definitions(-DR_LANG)
258
259 if (UNITTESTS)
260 # Disable unittests
261 message(STATUS "Disabling UNITTESTS because we are building the R interface")
262 set(UNITTESTS OFF)
263 endif (UNITTESTS)
264
265endif (R_LANG)
266
267
268# Create Static Library
269# ----------------------------------------------
270
271# Add linear system solvers cumulative library
272add_subdirectory(lin_sys)
273
274# Static library
275add_library (osqpstatic STATIC ${osqp_src} ${osqp_headers} ${linsys_solvers})
276# Give same name to static library output
277set_target_properties(osqpstatic PROPERTIES OUTPUT_NAME osqp)
278
279# Include directories for linear system solvers
280target_include_directories(osqpstatic PRIVATE ${linsys_solvers_includes})
281
282# Declare include directories for the cmake exported target
283target_include_directories(osqpstatic
284 PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
285 "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/osqp>")
286
287# Install Static Library
288# ----------------------------------------------
289
290include(GNUInstallDirs)
291
292install(TARGETS osqpstatic
293 EXPORT ${PROJECT_NAME}
294 ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
295 LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
296 RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
297
298
299# Install Headers
300# ----------------------------------------------
301
302install(FILES ${osqp_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/osqp")
303
304
305
306if (MATLAB)
307target_link_libraries (osqpstatic ${Matlab_LIBRARIES})
308endif (MATLAB)
309
310# If we are building Python/Matlab/R interface:
311# - do not build shared library
312# - do not build demo
313if (NOT PYTHON AND NOT MATLAB AND NOT R_LANG AND NOT EMBEDDED)
314 # Create osqp shared library
315 # NB: Add all the linear system solvers here
316 add_library (osqp SHARED ${osqp_src} ${osqp_headers} ${linsys_solvers})
317
318 # Include directories for linear system solvers
319 target_include_directories(osqp PRIVATE ${linsys_solvers_includes})
320
321 # Declare include directories for the cmake exported target
322 target_include_directories(osqp
323 PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
324 "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/osqp>")
325
326 # Install osqp shared library
327 install(TARGETS osqp
328 EXPORT ${PROJECT_NAME}
329 LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
330 ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
331 RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
332
333 # Create demo executable (linked to static library)
334 add_executable (osqp_demo ${PROJECT_SOURCE_DIR}/examples/osqp_demo.c)
335 target_link_libraries (osqp_demo osqpstatic)
336
337endif (NOT PYTHON AND NOT MATLAB AND NOT R_LANG AND NOT EMBEDDED)
338
339# Create CMake packages for the build directory
340# ----------------------------------------------
341include(CMakePackageConfigHelpers)
342
343export(EXPORT ${PROJECT_NAME}
344 FILE "${CMAKE_CURRENT_BINARY_DIR}/osqp-targets.cmake"
345 NAMESPACE osqp::)
346
347if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/osqp-config.cmake)
348 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/osqp-config.cmake "include(\"\${CMAKE_CURRENT_LIST_DIR}/osqp-targets.cmake\")\n")
349endif()
350
351
352# Create CMake packages for the install directory
353# ----------------------------------------------
354
355set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/osqp)
356
357install(EXPORT ${PROJECT_NAME}
358 FILE osqp-targets.cmake
359 NAMESPACE osqp::
360 DESTINATION ${ConfigPackageLocation})
361
362install(FILES ${CMAKE_CURRENT_BINARY_DIR}/osqp-config.cmake
363 DESTINATION ${ConfigPackageLocation})
364
365
366
367# Add uninstall command
368# ----------------------------------------------
369if(NOT TARGET uninstall)
370 configure_file(
371 "${CMAKE_CURRENT_SOURCE_DIR}/configure/cmake/cmake_uninstall.cmake.in"
372 "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
373 IMMEDIATE @ONLY)
374
375 add_custom_target(uninstall
376 COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
377endif()
378
379
380
381# Add testing
382# ----------------------------------------------
383# Add custom command to generate tests
384if (UNITTESTS)
385 find_package(PythonInterp)
386 if(NOT PYTHONINTERP_FOUND)
387 message( FATAL_ERROR "You need python installed to generate unittests. If you do not want to compile the unittests pass -DUNITTESTS=OFF to cmake." )
388 endif()
389
390 INCLUDE(FindPythonModule)
391 find_python_module(numpy)
392 IF(NOT NUMPY_FOUND)
393 message( FATAL_ERROR "You need numpy python module installed to generate unittests. If you do not want to compile the unittests pass -DUNITTESTS=OFF to cmake." )
394 ENDIF()
395
396 find_python_module(scipy)
397 # Check scipy version for sparse.random functionalities
398 IF((NOT SCIPY_FOUND) OR (SCIPY_VERSION VERSION_LESS 0.17.0))
399 message( FATAL_ERROR "You need scipy python module installed to generate unittests. If you do not want to compile the unittests pass -DUNITTESTS=OFF to cmake." )
400 ENDIF()
401
402 find_python_module(__future__)
403 IF(NOT __FUTURE___FOUND)
404 message( FATAL_ERROR "You need future python module installed to generate unittests. If you do not want to compile the unittests pass -DUNITTESTS=OFF to cmake." )
405 ENDIF()
406
407 # Add test_headers and codegen_test_headers
408 add_subdirectory(tests)
409
410 # Generating tests.stamp so that the test data are not always generated
411 # set(data_timestamp ${PROJECT_SOURCE_DIR}/tests/tests_data.stamp)
412 add_custom_command(
413 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
414 COMMAND ${PYTHON_EXECUTABLE} generate_tests_data.py
415 DEPENDS ${PROJECT_SOURCE_DIR}/tests/generate_tests_data.py
416 OUTPUT ${codegen_test_headers}
417 COMMENT "Generating unittests data files using Python"
418 )
419
420 # Direct linear solver testing
421 include_directories(tests)
422 add_executable(osqp_tester
423 ${PROJECT_SOURCE_DIR}/tests/osqp_tester.cpp
424 ${PROJECT_SOURCE_DIR}/tests/osqp_tester.h
425 ${test_headers}
426 ${codegen_test_headers}
427 )
428 set_target_properties(osqp_tester
429 PROPERTIES
430 CXX_STANDARD 11
431 CXX_STANDARD_REQUIRED YES
432 CXX_EXTENSIONS NO
433 )
434 target_link_libraries (osqp_tester osqpstatic ${CMAKE_DL_LIBS})
435
436 # Add custom memory target
437 add_executable(osqp_tester_custom_memory
438 EXCLUDE_FROM_ALL
439 ${PROJECT_SOURCE_DIR}/tests/osqp_tester.cpp
440 ${PROJECT_SOURCE_DIR}/tests/osqp_tester.h
441 ${test_headers}
442 ${codegen_test_headers}
443 ${PROJECT_SOURCE_DIR}/tests/custom_memory/custom_memory.c
444 ${PROJECT_SOURCE_DIR}/tests/custom_memory/custom_memory.h
445 )
446 target_link_libraries (osqp_tester_custom_memory osqpstatic ${CMAKE_DL_LIBS})
447
448 # Add testing
449 include(CTest)
450 enable_testing()
451 add_test(NAME tester COMMAND $<TARGET_FILE:osqp_tester>)
452endif()