From 38b27805fffcd4a65b4601eb1c39f57e1ff34558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana=20G=C3=B3mez?= Date: Mon, 23 Jun 2025 16:57:16 +0200 Subject: [PATCH] Compile all --- CMakeLists.txt | 91 ++++++++++------- external/CMakeLists.txt | 212 +--------------------------------------- tests/CMakeLists.txt | 2 +- 3 files changed, 58 insertions(+), 247 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c7b5856..954bad1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,21 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(Catch2) -# Add external libraries -add_subdirectory(external) +# Fetch libsvm +FetchContent_Declare( + libsvm + GIT_REPOSITORY https://github.com/cjlin1/libsvm.git + GIT_TAG v332 +) +FetchContent_MakeAvailable(libsvm) + +# Fetch liblinear +FetchContent_Declare( + liblinear + GIT_REPOSITORY https://github.com/cjlin1/liblinear.git + GIT_TAG v249 +) +FetchContent_MakeAvailable(liblinear) # Include directories include_directories(${CMAKE_SOURCE_DIR}/include) @@ -71,25 +84,47 @@ set(HEADERS include/svm_classifier/types.hpp ) -# Create library -add_library(svm_classifier STATIC ${SOURCES} ${HEADERS}) +# Add external sources directly to our library +set(EXTERNAL_SOURCES) -# 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> -# ) +# Add libsvm sources +if(EXISTS "${libsvm_SOURCE_DIR}/svm.cpp") + list(APPEND EXTERNAL_SOURCES "${libsvm_SOURCE_DIR}/svm.cpp") +endif() + +# Add liblinear sources +if(EXISTS "${liblinear_SOURCE_DIR}/linear.cpp") + list(APPEND EXTERNAL_SOURCES "${liblinear_SOURCE_DIR}/linear.cpp") +endif() + +if(EXISTS "${liblinear_SOURCE_DIR}/newton.cpp") + list(APPEND EXTERNAL_SOURCES "${liblinear_SOURCE_DIR}/newton.cpp") +elseif(EXISTS "${liblinear_SOURCE_DIR}/tron.cpp") + list(APPEND EXTERNAL_SOURCES "${liblinear_SOURCE_DIR}/tron.cpp") +endif() + +# Add BLAS sources +if(EXISTS "${liblinear_SOURCE_DIR}/blas") + file(GLOB BLAS_C_FILES "${liblinear_SOURCE_DIR}/blas/*.c") + list(APPEND EXTERNAL_SOURCES ${BLAS_C_FILES}) +endif() + +# Create library with all sources +add_library(svm_classifier STATIC ${SOURCES} ${HEADERS} ${EXTERNAL_SOURCES}) + +# Set language properties for different file types +foreach(source_file ${EXTERNAL_SOURCES}) + if(source_file MATCHES "\\.c$") + set_source_files_properties(${source_file} PROPERTIES LANGUAGE C) + endif() +endforeach() + +# Link libraries target_link_libraries(svm_classifier PUBLIC ${TORCH_LIBRARIES} PRIVATE nlohmann_json::nlohmann_json - $<$:svm_external_combined> ) # Set include directories @@ -99,27 +134,11 @@ target_include_directories(svm_classifier $ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src + ${libsvm_SOURCE_DIR} + ${liblinear_SOURCE_DIR} + ${liblinear_SOURCE_DIR}/blas ) -# Add include directories from external libraries using variables set by external/CMakeLists.txt -if(LIBSVM_INCLUDE_DIR) - target_include_directories(svm_classifier - PRIVATE ${LIBSVM_INCLUDE_DIR} - ) -endif() - -if(LIBLINEAR_INCLUDE_DIR) - target_include_directories(svm_classifier - PRIVATE ${LIBLINEAR_INCLUDE_DIR} - ) -endif() - -if(LIBLINEAR_BLAS_INCLUDE_DIR) - target_include_directories(svm_classifier - PRIVATE ${LIBLINEAR_BLAS_INCLUDE_DIR} - ) -endif() - # Compiler-specific options target_compile_features(svm_classifier PUBLIC cxx_std_17) @@ -227,7 +246,7 @@ add_subdirectory(tests) # Add examples add_subdirectory(examples) -# Installation - Fixed version +# Installation install(TARGETS svm_classifier EXPORT SVMClassifierTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -287,4 +306,4 @@ else() set(CPACK_RPM_PACKAGE_REQUIRES "glibc, libstdc++, blas, lapack") endif() -include(CPack) \ No newline at end of file +include(CPack) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index a7cf5d9..73a96f2 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,210 +1,2 @@ -# External dependencies CMakeLists.txt - Fixed version with proper BLAS handling - -include(FetchContent) - -# Set policies for FetchContent -if(POLICY CMP0135) - cmake_policy(SET CMP0135 NEW) -endif() - -# Fetch libsvm -FetchContent_Declare( - libsvm - GIT_REPOSITORY https://github.com/cjlin1/libsvm.git - GIT_TAG v332 -) -FetchContent_MakeAvailable(libsvm) - -# Fetch liblinear -FetchContent_Declare( - liblinear - GIT_REPOSITORY https://github.com/cjlin1/liblinear.git - GIT_TAG v249 -) -FetchContent_MakeAvailable(liblinear) - -# Build libsvm as OBJECT library -if(EXISTS "${libsvm_SOURCE_DIR}/svm.cpp") - set(LIBSVM_SOURCES "${libsvm_SOURCE_DIR}/svm.cpp") - - add_library(libsvm_objects OBJECT ${LIBSVM_SOURCES}) - - # Set properties for the object library - target_include_directories(libsvm_objects - PUBLIC - ${libsvm_SOURCE_DIR} - ) - - # Set C++ standard for libsvm - target_compile_features(libsvm_objects PRIVATE cxx_std_17) - - # Make the include directory available to parent scope - set(LIBSVM_INCLUDE_DIR ${libsvm_SOURCE_DIR} PARENT_SCOPE) - - message(STATUS "libsvm built successfully as object library") -else() - message(WARNING "libsvm source files not found") - # Create empty object library - add_library(libsvm_objects OBJECT) - set(LIBSVM_INCLUDE_DIR "" PARENT_SCOPE) -endif() - -# 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") - list(APPEND LIBLINEAR_SOURCES "${liblinear_SOURCE_DIR}/linear.cpp") -endif() - -# Check for optimization files (tron.cpp, newton.cpp, etc.) -if(EXISTS "${liblinear_SOURCE_DIR}/tron.cpp") - list(APPEND LIBLINEAR_SOURCES "${liblinear_SOURCE_DIR}/tron.cpp") -elseif(EXISTS "${liblinear_SOURCE_DIR}/newton.cpp") - list(APPEND LIBLINEAR_SOURCES "${liblinear_SOURCE_DIR}/newton.cpp") -endif() - -# Check for BLAS files in blas directory -if(EXISTS "${liblinear_SOURCE_DIR}/blas") - # Explicitly add the required BLAS source files - set(BLAS_FILES - "${liblinear_SOURCE_DIR}/blas/daxpy.c" - "${liblinear_SOURCE_DIR}/blas/ddot.c" - "${liblinear_SOURCE_DIR}/blas/dnrm2.c" - "${liblinear_SOURCE_DIR}/blas/dscal.c" - ) - - # Check which BLAS files actually exist and add them - foreach(blas_file ${BLAS_FILES}) - if(EXISTS ${blas_file}) - list(APPEND BLAS_SOURCES ${blas_file}) - message(STATUS "Adding BLAS file: ${blas_file}") - endif() - endforeach() -else() - message(WARNING "BLAS directory not found in liblinear source") -endif() - -# 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 - PUBLIC - ${liblinear_SOURCE_DIR} - ) - - # Add blas directory if it exists - if(EXISTS "${liblinear_SOURCE_DIR}/blas") - target_include_directories(liblinear_objects - PUBLIC ${liblinear_SOURCE_DIR}/blas - ) - endif() - - # Set C++ standard for liblinear - target_compile_features(liblinear_objects PRIVATE cxx_std_17) - - # Compiler specific flags - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_compile_options(liblinear_objects PRIVATE -w) # Suppress warnings - endif() - - # Make the include directories available to parent scope - set(LIBLINEAR_INCLUDE_DIR ${liblinear_SOURCE_DIR} PARENT_SCOPE) - if(EXISTS "${liblinear_SOURCE_DIR}/blas") - 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") - - # Create a minimal linear.cpp file - set(MINIMAL_LIBLINEAR_DIR "${CMAKE_CURRENT_BINARY_DIR}/minimal_liblinear") - file(MAKE_DIRECTORY ${MINIMAL_LIBLINEAR_DIR}) - - # Create minimal header - file(WRITE "${MINIMAL_LIBLINEAR_DIR}/linear.h" - "#pragma once\n" - "extern \"C\" {\n" - "struct feature_node { int index; double value; };\n" - "struct problem { int l, n; double *y; struct feature_node **x; double bias; };\n" - "struct parameter { int solver_type; double eps, C; };\n" - "struct model { struct parameter param; int nr_class, nr_feature; double *w; int *label; double bias; };\n" - "struct model* train(const struct problem *prob, const struct parameter *param);\n" - "double predict(const struct model *model_, const struct feature_node *x);\n" - "void free_and_destroy_model(struct model **model_ptr_ptr);\n" - "}\n" - ) - - # Create minimal implementation - file(WRITE "${MINIMAL_LIBLINEAR_DIR}/linear.cpp" - "#include \"linear.h\"\n" - "#include \n" - "#include \n" - "struct model* train(const struct problem *prob, const struct parameter *param) {\n" - " auto model = (struct model*)malloc(sizeof(struct model));\n" - " memset(model, 0, sizeof(struct model));\n" - " model->nr_feature = prob->n;\n" - " model->nr_class = 2;\n" - " model->w = (double*)calloc(prob->n, sizeof(double));\n" - " return model;\n" - "}\n" - "double predict(const struct model *model_, const struct feature_node *x) {\n" - " return 1.0; // Dummy prediction\n" - "}\n" - "void free_and_destroy_model(struct model **model_ptr_ptr) {\n" - " if (*model_ptr_ptr) {\n" - " free((*model_ptr_ptr)->w);\n" - " free(*model_ptr_ptr);\n" - " *model_ptr_ptr = nullptr;\n" - " }\n" - "}\n" - ) - - add_library(liblinear_objects OBJECT "${MINIMAL_LIBLINEAR_DIR}/linear.cpp") - 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) -endif() - -# Print summary -message(STATUS "External libraries configured:") -message(STATUS " - libsvm: ${libsvm_SOURCE_DIR}") -message(STATUS " - liblinear: ${liblinear_SOURCE_DIR}") -if(TARGET blas_functions) - message(STATUS " - BLAS functions built as separate static library") -endif() -message(STATUS " - Using combination of OBJECT and STATIC libraries") +# External dependencies are now handled directly in the main CMakeLists.txt +# This file is kept for compatibility diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a93eb7b..ca68c41 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,7 +24,7 @@ target_link_libraries(svm_classifier_tests svm_classifier Catch2::Catch2WithMain nlohmann_json::nlohmann_json - $<$:blas_functions> + # No need to link external libraries as they're already in svm_classifier ) # Set include directories - Handle external libraries dynamically