Skip to content

Commit

Permalink
(conan-io#16469) osqp: add recipe
Browse files Browse the repository at this point in the history
  • Loading branch information
billyzheli authored and 0xFireWolf committed Apr 2, 2023
1 parent 9c237a9 commit 1f0f7d9
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 0 deletions.
4 changes: 4 additions & 0 deletions recipes/osqp/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sources:
"0.6.2":
url: "https://github.com/osqp/osqp/releases/download/v0.6.2/complete_sources.tar.gz"
sha256: "0a7ade2fa19f13e13bc12f6ea0046ef764049023efb4997a4e72a76534f623ec"
95 changes: 95 additions & 0 deletions recipes/osqp/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from conan import ConanFile
from conan.tools.files import get, copy, rm, rmdir
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
import os

required_conan_version = ">=1.53.0"

class OsqpConan(ConanFile):
name = "osqp"
package_type = "library"
description = "The OSQP (Operator Splitting Quadratic Program) solver is a numerical optimization package."
license = "Apache-2.0"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://osqp.org/"
topics = ("machine-learning", "control", "optimization", "svm", "solver", "lasso", "portfolio-optimization",
"numerical-optimization", "quadratic-programming", "convex-optimization", "model-predictive-control")
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
}

def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC

def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")

def layout(self):
cmake_layout(self, src_folder="src")

def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)

def generate(self):
tc = CMakeToolchain(self)
tc.variables['UNITTESTS'] = not self.conf.get("tools.build:skip_test", default=True, check_type=bool)
tc.variables["PRINTING"] = True
tc.variables["PROFILING"] = True
tc.variables["CTRLC"] = True
tc.variables["DFLOAT"] = False
tc.variables["DLONG"] = True
tc.variables["COVERAGE"] = False
tc.variables["ENABLE_MKL_PARDISO"] = True
tc.generate()

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
copy(self, pattern="LICENSE", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
cmake = CMake(self)
cmake.install()

if self.settings.os == "Windows":
if self.options.shared:
rm(self, "qdldl.dll", os.path.join(self.package_folder, "bin"))
else:
rmdir(self, os.path.join(self.package_folder, "bin"))
else:
if self.options.shared:
rm(self, "*.a", os.path.join(self.package_folder, "lib"))
else:
rm(self, "*.so", os.path.join(self.package_folder, "lib"))
rm(self, "*.dylib", os.path.join(self.package_folder, "lib"))

rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
rmdir(self, os.path.join(self.package_folder, "include", "qdldl"))
rm(self, "*qdldl.*", os.path.join(self.package_folder, "lib"))

def package_info(self):
self.cpp_info.set_property("cmake_file_name", "osqp")
self.cpp_info.set_property("cmake_target_name", "osqp::osqp")
self.cpp_info.libs = ["osqp"]

if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.append("m")
self.cpp_info.system_libs.append("rt")
self.cpp_info.system_libs.append("dl")

# TODO: to remove in conan v2 once cmake_find_package_* generators removed
self.cpp_info.filenames["cmake_find_package"] = "osqp"
self.cpp_info.filenames["cmake_find_package_multi"] = "osqp"
self.cpp_info.names["cmake_find_package"] = "osqp"
self.cpp_info.names["cmake_find_package_multi"] = "osqp"
8 changes: 8 additions & 0 deletions recipes/osqp/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.8)

project(test_package CXX)

find_package(osqp REQUIRED CONFIG)

add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE osqp::osqp)
27 changes: 27 additions & 0 deletions recipes/osqp/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake
import os


# It will become the standard on Conan 2.x
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"

def requirements(self):
self.requires(self.tested_reference_str)

def layout(self):
cmake_layout(self)

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")
69 changes: 69 additions & 0 deletions recipes/osqp/all/test_package/test_package.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Below is a demo copied from an upstream example code,
* It shows how to setup and solve an optimization problem.
* Source code: https://github.com/osqp/osqp/blob/master/examples/osqp_demo.c
* Problem definition: https://osqp.org/docs/examples/setup-and-solve.html
*/
#include "osqp/osqp.h"


int main(void) {
// Load problem data
c_float P_x[3] = {4.0, 1.0, 2.0, };
c_int P_nnz = 3;
c_int P_i[3] = {0, 0, 1, };
c_int P_p[3] = {0, 1, 3, };
c_float q[2] = {1.0, 1.0, };
c_float A_x[4] = {1.0, 1.0, 1.0, 1.0, };
c_int A_nnz = 4;
c_int A_i[4] = {0, 1, 0, 2, };
c_int A_p[3] = {0, 2, 4, };
c_float l[3] = {1.0, 0.0, 0.0, };
c_float u[3] = {1.0, 0.7, 0.7, };
c_int n = 2;
c_int m = 3;

// Exitflag
c_int exitflag = 0;

// Workspace structures
OSQPWorkspace *work;
OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
OSQPData *data = (OSQPData *)c_malloc(sizeof(OSQPData));

// Populate data
if (data) {
data->n = n;
data->m = m;
data->P = csc_matrix(data->n, data->n, P_nnz, P_x, P_i, P_p);
data->q = q;
data->A = csc_matrix(data->m, data->n, A_nnz, A_x, A_i, A_p);
data->l = l;
data->u = u;
}

// Define solver settings as default
if (settings) {
osqp_set_default_settings(settings);
settings->alpha = 1.0; // Change alpha parameter
}

// Setup workspace
exitflag = osqp_setup(&work, data, settings);

// Solve Problem
osqp_solve(work);

// Cleanup
osqp_cleanup(work);
if (data) {
if (data->A) c_free(data->A);
if (data->P) c_free(data->P);
c_free(data);
}
if (settings) c_free(settings);

return exitflag;

return EXIT_SUCCESS;
}
8 changes: 8 additions & 0 deletions recipes/osqp/all/test_v1_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/)
19 changes: 19 additions & 0 deletions recipes/osqp/all/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from conans import ConanFile, CMake
from conan.tools.build import cross_building
import os


# legacy validation with Conan 1.x
class TestPackageV1Conan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package_multi"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)
3 changes: 3 additions & 0 deletions recipes/osqp/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
versions:
"0.6.2":
folder: all

0 comments on commit 1f0f7d9

Please sign in to comment.