From 417844f19b58ba4980464ef9da29c26cc5219080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana=20G=C3=B3mez?= Date: Mon, 23 Jun 2025 16:42:03 +0200 Subject: [PATCH] Compile tests but fail linking --- CMakeLists.txt | 16 ++++++--- examples/CMakeLists.txt | 4 ++- examples/basic_usage.cpp | 2 +- external/CMakeLists.txt | 54 ++++++++++++++++++++++++------ tests/CMakeLists.txt | 15 +++++++++ tests/test_data_converter.cpp | 3 +- tests/test_kernel_parameters.cpp | 3 +- tests/test_main.cpp | 2 +- tests/test_multiclass_strategy.cpp | 3 +- tests/test_svm_classifier.cpp | 3 +- 10 files changed, 83 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2417019..c7b5856 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.15) project(SVMClassifier VERSION 1.0.0 - LANGUAGES CXX + LANGUAGES C CXX DESCRIPTION "A C++ library for Support Vector Machine classification using PyTorch" HOMEPAGE_URL "https://gitea.rmontanana.es/rmontanana/SVMClassifier" ) @@ -74,14 +74,22 @@ set(HEADERS # Create library add_library(svm_classifier STATIC ${SOURCES} ${HEADERS}) -# Link libraries - Updated to use object libraries instead of static libraries +# Link libraries - Updated to use object libraries and BLAS if available +# target_link_libraries(svm_classifier +# PUBLIC +# ${TORCH_LIBRARIES} +# PRIVATE +# nlohmann_json::nlohmann_json +# $ +# $ +# $<$:blas_functions> +# ) target_link_libraries(svm_classifier PUBLIC ${TORCH_LIBRARIES} PRIVATE nlohmann_json::nlohmann_json - $ - $ + $<$:svm_external_combined> ) # Set include directories diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 55d62e5..94dee0c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,7 +2,9 @@ # Basic usage example add_executable(basic_usage basic_usage.cpp) -target_link_libraries(basic_usage PRIVATE svm_classifier) +target_link_libraries(basic_usage PRIVATE svm_classifier + nlohmann_json::nlohmann_json +) target_include_directories(basic_usage PRIVATE ${CMAKE_SOURCE_DIR}/include) target_compile_features(basic_usage PRIVATE cxx_std_17) diff --git a/examples/basic_usage.cpp b/examples/basic_usage.cpp index 4e66ee3..86ba36c 100644 --- a/examples/basic_usage.cpp +++ b/examples/basic_usage.cpp @@ -73,7 +73,7 @@ void basic_svm_example() std::cout << "Dataset created:" << std::endl; print_tensor_stats(X_train, "X_train"); std::cout << "Unique classes in y_train: "; - auto unique_classes = torch::unique(y_train); + auto unique_classes = std::get<0>(at::_unique(y_train)); for (int i = 0; i < unique_classes.size(0); ++i) { std::cout << unique_classes[i].item() << " "; } diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 41430c3..a7cf5d9 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,4 +1,4 @@ -# External dependencies CMakeLists.txt - Fixed version with OBJECT libraries +# External dependencies CMakeLists.txt - Fixed version with proper BLAS handling include(FetchContent) @@ -23,7 +23,7 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(liblinear) -# Build libsvm as OBJECT library to avoid export issues +# Build libsvm as OBJECT library if(EXISTS "${libsvm_SOURCE_DIR}/svm.cpp") set(LIBSVM_SOURCES "${libsvm_SOURCE_DIR}/svm.cpp") @@ -31,7 +31,7 @@ if(EXISTS "${libsvm_SOURCE_DIR}/svm.cpp") # Set properties for the object library target_include_directories(libsvm_objects - PRIVATE + PUBLIC ${libsvm_SOURCE_DIR} ) @@ -49,8 +49,9 @@ else() set(LIBSVM_INCLUDE_DIR "" PARENT_SCOPE) endif() -# Build liblinear as OBJECT library +# Build liblinear with BLAS as a static library set(LIBLINEAR_SOURCES) +set(BLAS_SOURCES) # Check for main liblinear source files if(EXISTS "${liblinear_SOURCE_DIR}/linear.cpp") @@ -64,7 +65,7 @@ elseif(EXISTS "${liblinear_SOURCE_DIR}/newton.cpp") list(APPEND LIBLINEAR_SOURCES "${liblinear_SOURCE_DIR}/newton.cpp") endif() -# Check for BLAS files in blas directory - Fixed to ensure they're included +# Check for BLAS files in blas directory if(EXISTS "${liblinear_SOURCE_DIR}/blas") # Explicitly add the required BLAS source files set(BLAS_FILES @@ -77,7 +78,7 @@ if(EXISTS "${liblinear_SOURCE_DIR}/blas") # Check which BLAS files actually exist and add them foreach(blas_file ${BLAS_FILES}) if(EXISTS ${blas_file}) - list(APPEND LIBLINEAR_SOURCES ${blas_file}) + list(APPEND BLAS_SOURCES ${blas_file}) message(STATUS "Adding BLAS file: ${blas_file}") endif() endforeach() @@ -85,20 +86,40 @@ else() message(WARNING "BLAS directory not found in liblinear source") endif() -# Create liblinear object library if we have source files +# Create liblinear with BLAS if(LIBLINEAR_SOURCES) + # First create BLAS library if we have BLAS sources + if(BLAS_SOURCES) + add_library(blas_functions STATIC ${BLAS_SOURCES}) + target_include_directories(blas_functions + PUBLIC ${liblinear_SOURCE_DIR}/blas + ) + + # Set C language for BLAS + set_target_properties(blas_functions PROPERTIES + LINKER_LANGUAGE C + POSITION_INDEPENDENT_CODE ON + ) + + # Ensure symbols are exported + if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(blas_functions PRIVATE -fvisibility=default) + endif() + endif() + + # Create liblinear object library add_library(liblinear_objects OBJECT ${LIBLINEAR_SOURCES}) # Set properties for the object library target_include_directories(liblinear_objects - PRIVATE + PUBLIC ${liblinear_SOURCE_DIR} ) # Add blas directory if it exists if(EXISTS "${liblinear_SOURCE_DIR}/blas") target_include_directories(liblinear_objects - PRIVATE ${liblinear_SOURCE_DIR}/blas + PUBLIC ${liblinear_SOURCE_DIR}/blas ) endif() @@ -116,7 +137,15 @@ if(LIBLINEAR_SOURCES) set(LIBLINEAR_BLAS_INCLUDE_DIR ${liblinear_SOURCE_DIR}/blas PARENT_SCOPE) endif() + # Export BLAS library target to parent scope if it exists + if(TARGET blas_functions) + set(LIBLINEAR_BLAS_TARGET blas_functions PARENT_SCOPE) + endif() + message(STATUS "liblinear built with sources: ${LIBLINEAR_SOURCES}") + if(BLAS_SOURCES) + message(STATUS "BLAS functions built as separate static library") + endif() else() # Create minimal liblinear implementation as object library message(WARNING "liblinear source files not found, creating minimal implementation") @@ -165,7 +194,7 @@ else() ) add_library(liblinear_objects OBJECT "${MINIMAL_LIBLINEAR_DIR}/linear.cpp") - target_include_directories(liblinear_objects PRIVATE ${MINIMAL_LIBLINEAR_DIR}) + target_include_directories(liblinear_objects PUBLIC ${MINIMAL_LIBLINEAR_DIR}) target_compile_features(liblinear_objects PRIVATE cxx_std_17) set(LIBLINEAR_INCLUDE_DIR ${MINIMAL_LIBLINEAR_DIR} PARENT_SCOPE) @@ -175,4 +204,7 @@ endif() message(STATUS "External libraries configured:") message(STATUS " - libsvm: ${libsvm_SOURCE_DIR}") message(STATUS " - liblinear: ${liblinear_SOURCE_DIR}") -message(STATUS " - Using OBJECT libraries to avoid export issues") \ No newline at end of file +if(TARGET blas_functions) + message(STATUS " - BLAS functions built as separate static library") +endif() +message(STATUS " - Using combination of OBJECT and STATIC libraries") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0ce1461..a93eb7b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,6 +24,7 @@ target_link_libraries(svm_classifier_tests svm_classifier Catch2::Catch2WithMain nlohmann_json::nlohmann_json + $<$:blas_functions> ) # Set include directories - Handle external libraries dynamically @@ -32,6 +33,20 @@ target_include_directories(svm_classifier_tests ${CMAKE_SOURCE_DIR}/include ) +# Add Catch2 include directories explicitly +if(TARGET Catch2::Catch2) + get_target_property(CATCH2_INCLUDE_DIRS Catch2::Catch2 INTERFACE_INCLUDE_DIRECTORIES) + target_include_directories(svm_classifier_tests PRIVATE ${CATCH2_INCLUDE_DIRS}) +endif() + +# Also add the source directory of Catch2 if available +if(catch2_SOURCE_DIR) + target_include_directories(svm_classifier_tests + PRIVATE + ${catch2_SOURCE_DIR}/src + ) +endif() + # Add libsvm include directory if available if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/../_deps/libsvm-src") target_include_directories(svm_classifier_tests diff --git a/tests/test_data_converter.cpp b/tests/test_data_converter.cpp index 98d93be..1eb1c3a 100644 --- a/tests/test_data_converter.cpp +++ b/tests/test_data_converter.cpp @@ -3,7 +3,8 @@ * @brief Unit tests for DataConverter class */ -#include +#include +#include #include #include diff --git a/tests/test_kernel_parameters.cpp b/tests/test_kernel_parameters.cpp index 0bf726b..8f1bb07 100644 --- a/tests/test_kernel_parameters.cpp +++ b/tests/test_kernel_parameters.cpp @@ -3,7 +3,8 @@ * @brief Unit tests for KernelParameters class */ -#include +#include +#include #include #include diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 796d59b..9bdb110 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -7,7 +7,7 @@ */ #define CATCH_CONFIG_MAIN -#include +#include #include #include diff --git a/tests/test_multiclass_strategy.cpp b/tests/test_multiclass_strategy.cpp index ed36c86..8db15a9 100644 --- a/tests/test_multiclass_strategy.cpp +++ b/tests/test_multiclass_strategy.cpp @@ -3,7 +3,8 @@ * @brief Unit tests for multiclass strategy classes */ -#include +#include +#include #include #include #include diff --git a/tests/test_svm_classifier.cpp b/tests/test_svm_classifier.cpp index f1333cc..96fcdda 100644 --- a/tests/test_svm_classifier.cpp +++ b/tests/test_svm_classifier.cpp @@ -3,7 +3,8 @@ * @brief Integration tests for SVMClassifier class */ -#include +#include +#include #include #include #include