Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blasfeo: add package #15643

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions recipes/blasfeo/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
sources:
# Newer versions at the top
"0.1.3":
url: "https://github.com/giaf/blasfeo/archive/refs/tags/0.1.3.tar.gz"
sha256: "c33eb6467a90d6075a8db34e5ab239ecdda38c5261ae096def122fe7a0f98780"
"0.1.2":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you specifically need this version we generally don't add older versions (you can check the FAQ for more info)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This library blasfeo is a main dependency of another one hpipm which I plan to add later.
I tried building locally hpipm with blasfeo 0.1.3 version as a dependency, but apparently they are not compatible, which is not documented anywhere in either library.
Latest hpipm release works only with blasfeo 0.1.2 so I've added it here also.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus, apparently tests are not compatible with older version so I have to fix that also.

url: "https://github.com/giaf/blasfeo/archive/refs/tags/0.1.2.tar.gz"
sha256: "079c9c90db1249aac59fa649c42667d46f4d458049e5986762035388f22fc005"
174 changes: 174 additions & 0 deletions recipes/blasfeo/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import os

from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.apple import is_apple_os
from conan.tools.files import (
apply_conandata_patches,
copy,
export_conandata_patches,
get,
)
from conan.tools.gnu import Autotools, AutotoolsToolchain

required_conan_version = ">=1.57.0"


class BlasfeoConan(ConanFile):
name = "blasfeo"
description = "Basic linear algebra subroutines for embedded optimization."
topics = (
"blasfeo",
"blas",
"linear-algebra",
"matrices",
"embedded",
"optimization",
)
license = "BSD-2-Clause"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/giaf/blasfeo"
settings = "os", "arch", "compiler", "build_type"

_blasfeo_arch_targets = {
"x86_64": [
"X64_INTEL_SKYLAKE_X",
"X64_INTEL_HASWELL",
"X64_INTEL_SANDY_BRIDGE",
"X64_INTEL_CORE",
"X64_AMD_BULLDOZER",
],
"x86": [
"X86_AMD_JAGUAR",
"X86_AMD_BARCELONA",
],
"armv7": [
"ARMV7A_ARM_CORTEX_A15",
"ARMV7A_ARM_CORTEX_A9",
"ARMV7A_ARM_CORTEX_A7",
],
"armv8": [
"ARMV8A_APPLE_M1",
"ARMV8A_ARM_CORTEX_A76",
"ARMV8A_ARM_CORTEX_A73",
"ARMV8A_ARM_CORTEX_A57",
"ARMV8A_ARM_CORTEX_A55",
"ARMV8A_ARM_CORTEX_A53",
],
"generic": ["GENERIC"],
}

options = {
"fPIC": [True, False],
"shared": [True, False],
"target": [x for list in [i for i in _blasfeo_arch_targets.values()] for x in list],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very awkward way of packing softwarehttps://github.com/giaf/blasfeo#supported-computer-architectures

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is. I will try to add something according to @uilianries suggestion.

"la": [
"HIGH_PERFORMANCE",
"REFERENCE",
"EXTERNAL_BLAS_WRAPPER",
],
"mf": [
"COLMAJ",
"PANELMAJ",
],
}
default_options = {
"fPIC": False,
"shared": False,
"target": "GENERIC",
"la": "HIGH_PERFORMANCE",
"mf": "PANELMAJ",
}

def export_sources(self):
export_conandata_patches(self)

def generate(self):
toolchain = AutotoolsToolchain(self)
toolchain.generate()

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 validate(self):
blasfeo_target = str(self.options.target)
if blasfeo_target != self._blasfeo_arch_targets["generic"][0]:
if blasfeo_target not in self._blasfeo_arch_targets[str(self.settings.arch)]:
raise ConanInvalidConfiguration(
"Invalid arch: {} and target: {} combination.".format(self.settings.arch, self.options.target)
)
if self.settings.os == "Windows":
# Installation instructions do not contain Windows information.
# There is also an open issue for Windows support: https://github.com/giaf/blasfeo/issues/101
raise ConanInvalidConfiguration(
"This recipe does not support {} builds of {}.".format(self.settings.os, self.name)
)
if self.options.shared and is_apple_os(self):
raise ConanInvalidConfiguration(
"{} does not support shared builds for {}.".format(self.name, self.settings.os)
)

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

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

def build(self):
apply_conandata_patches(self)

target = "shared_library" if self.options.shared else "static_library"
args = [
"TARGET={}".format(self.options.target),
"LA={}".format(self.options.la),
"MF={}".format(self.options.mf),
]
autotools = Autotools(self)
autotools.make(target=target, args=args)

def package(self):
copy(
self,
pattern="LICENSE*",
src=self.source_folder,
dst=os.path.join(self.package_folder, "licenses"),
keep_path=False,
)
copy(
self,
pattern="*.h*",
src=os.path.join(self.source_folder, "include"),
dst=os.path.join(self.package_folder, "include"),
keep_path=False,
)
copy(
self,
pattern="*.a",
src=os.path.join(self.source_folder, "lib"),
dst=os.path.join(self.package_folder, "lib"),
keep_path=False,
)
copy(
self,
pattern="*.so",
src=os.path.join(self.source_folder, "lib"),
dst=os.path.join(self.package_folder, "lib"),
keep_path=False,
)

def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "BLASFEO")
self.cpp_info.set_property("cmake_target_name", "BLASFEO::BLASFEO")
self.cpp_info.set_property("pkg_config_name", "blasfeo")
self.cpp_info.names["cmake_find_package"] = "BLASFEO"
self.cpp_info.names["cmake_find_package_multi"] = "BLASFEO"
self.cpp_info.libs = ["blasfeo"]
self.cpp_info.system_libs = ["m"]
8 changes: 8 additions & 0 deletions recipes/blasfeo/all/test_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 LANGUAGES C)

find_package(BLASFEO REQUIRED CONFIG)

add_executable(${PROJECT_NAME} test_package.c)

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


# 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 layout(self):
cmake_layout(self)

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

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")
83 changes: 83 additions & 0 deletions recipes/blasfeo/all/test_package/test_package.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Modified blasfeo/examples/getting_started.c example

#include <stdio.h>
#include <stdlib.h>

#include <blasfeo.h>

int main()
{
printf("Testing processor\n");

char supportString[50];
blasfeo_processor_library_string(supportString);
printf("Library requires processor features:%s\n", supportString);

int features = 0;
if (!blasfeo_processor_cpu_features(&features))
{
printf("Current processor does not support the current compiled BLASFEO library.\n");
printf("Please get a BLASFEO library compatible with this processor.\n");
return 3;
}
blasfeo_processor_feature_string(features, supportString);
printf("Processor supports features:%s\n", supportString);

/*
NOTE: Code above will compile and run without output even if library not linked properly or if not native target.
Code below which does actual matrix calculations requires linked -lm (math.h) and will not compile otherwise.
*/

int n = 4; // matrix size

// A
struct blasfeo_dmat sA; // matrix structure
blasfeo_allocate_dmat(n, n, &sA); // allocate and assign memory needed by A

// B
struct blasfeo_dmat sB; // matrix structure
int B_size = blasfeo_memsize_dmat(n, n); // size of memory needed by B
void *B_mem_align;
v_zeros_align(&B_mem_align, B_size); // allocate memory needed by B
blasfeo_create_dmat(n, n, &sB, B_mem_align); // assign aligned memory to struct

// C
struct blasfeo_dmat sC; // matrix structure
int C_size = blasfeo_memsize_dmat(n, n); // size of memory needed by C
C_size += 64; // 64-bytes alignment
void *C_mem = malloc(C_size);
void *C_mem_align = (void *)((((unsigned long long)C_mem) + 63) / 64 * 64); // align memory pointer
blasfeo_create_dmat(n, n, &sC, C_mem_align); // assign aligned memory to struct

int ii; // loop index

// A
double *A = malloc(n * n * sizeof(double));
for (ii = 0; ii < n * n; ii++)
{
A[ii] = ii;
}
int lda = n;
blasfeo_pack_dmat(n, n, A, lda, &sA, 0, 0); // convert from column-major to BLASFEO dmat
free(A);

// B
blasfeo_dgese(n, n, 0.0, &sB, 0, 0); // set B to zero
for (ii = 0; ii < n; ii++)
{
BLASFEO_DMATEL(&sB, ii, ii) = 1.0; // set B diagonal to 1.0 accessing dmat elements
}

// C
blasfeo_dgese(n, n, -1.0, &sC, 0, 0); // set C to -1.0
blasfeo_dgemm_nt(n, n, n, 1.0, &sA, 0, 0, &sB, 0, 0, 0.0, &sC, 0, 0, &sC, 0, 0);

printf("\nC = \n");
blasfeo_print_dmat(n, n, &sC, 0, 0);

blasfeo_free_dmat(&sA);
v_free_align(B_mem_align);
free(C_mem);

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

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

find_package(BLASFEO REQUIRED CONFIG)

add_executable(${PROJECT_NAME} ../test_package/test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE BLASFEO::BLASFEO)
19 changes: 19 additions & 0 deletions recipes/blasfeo/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)
6 changes: 6 additions & 0 deletions recipes/blasfeo/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
versions:
# Newer versions at the top
"0.1.3":
folder: all
"0.1.2":
folder: all