diff --git a/CMakeLists.txt b/CMakeLists.txt index 97886dc..2417019 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ project(SVMClassifier HOMEPAGE_URL "https://gitea.rmontanana.es/rmontanana/SVMClassifier" ) set(PROJECT_AUTHOR "Ricardo Montañana Gómez") + # Set C++ standard set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -32,6 +33,7 @@ endif() include(FetchContent) # Fetch nlohmann/json +set(JSON_Install ON CACHE BOOL "Install nlohmann-json when my project is installed" FORCE) FetchContent_Declare( nlohmann_json GIT_REPOSITORY https://github.com/nlohmann/json.git @@ -52,8 +54,6 @@ add_subdirectory(external) # Include directories include_directories(${CMAKE_SOURCE_DIR}/include) -include_directories(${CMAKE_SOURCE_DIR}/external/libsvm) -include_directories(${CMAKE_SOURCE_DIR}/external/liblinear) # Create the main library set(SOURCES @@ -74,14 +74,14 @@ set(HEADERS # Create library add_library(svm_classifier STATIC ${SOURCES} ${HEADERS}) -# Link libraries with PRIVATE linkage to avoid export issues +# Link libraries - Updated to use object libraries instead of static libraries target_link_libraries(svm_classifier PUBLIC ${TORCH_LIBRARIES} PRIVATE nlohmann_json::nlohmann_json - libsvm_static - liblinear_static + $ + $ ) # Set include directories @@ -90,10 +90,28 @@ target_include_directories(svm_classifier $ $ PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/external/libsvm - ${CMAKE_CURRENT_SOURCE_DIR}/external/liblinear + ${CMAKE_CURRENT_SOURCE_DIR}/src ) +# 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) diff --git a/cmake/SVMClassifierConfig.cmake.in b/cmake/SVMClassifierConfig.cmake.in index e2e3b9c..4dcff6a 100644 --- a/cmake/SVMClassifierConfig.cmake.in +++ b/cmake/SVMClassifierConfig.cmake.in @@ -1,39 +1,42 @@ -# SVMClassifierConfig.cmake.in -# CMake configuration file for SVMClassifier package - @PACKAGE_INIT@ -# Set the version -set(SVMClassifier_VERSION @PACKAGE_VERSION@) +# SVMClassifier package configuration file -# Find required dependencies +# Check if components are specified +set(_supported_components ) + +# Handle components +foreach(_comp ${SVMClassifier_FIND_COMPONENTS}) + if(NOT _comp IN_LIST _supported_components) + set(SVMClassifier_FOUND FALSE) + set(SVMClassifier_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}") + endif() +endforeach() + +# Include dependencies that are required for using SVMClassifier +include(CMakeFindDependencyMacro) + +# Find Torch dependency find_dependency(Torch REQUIRED) -find_dependency(PkgConfig REQUIRED) -# Include nlohmann_json -if(NOT TARGET nlohmann_json::nlohmann_json) - find_package(nlohmann_json 3.11.0 REQUIRED) -endif() +# Note: nlohmann_json, libsvm, and liblinear are linked privately +# so they don't need to be found here # Include the targets file include("${CMAKE_CURRENT_LIST_DIR}/SVMClassifierTargets.cmake") -# Set variables for backward compatibility +# Set variables for compatibility set(SVMClassifier_LIBRARIES SVMClassifier::svm_classifier) -set(SVMClassifier_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include") +set(SVMClassifier_INCLUDE_DIRS) -# Verify that the targets were imported -if(NOT TARGET SVMClassifier::svm_classifier) - message(FATAL_ERROR "SVMClassifier::svm_classifier target not found") +# Get the include directories from the target +get_target_property(_inc_dirs SVMClassifier::svm_classifier INTERFACE_INCLUDE_DIRECTORIES) +if(_inc_dirs) + set(SVMClassifier_INCLUDE_DIRS ${_inc_dirs}) endif() +# Check that all required components have been found +check_required_components(SVMClassifier) + # Set found flag -set(SVMClassifier_FOUND TRUE) - -# Print status message -if(NOT SVMClassifier_FIND_QUIETLY) - message(STATUS "Found SVMClassifier: ${PACKAGE_PREFIX_DIR} (found version \"${SVMClassifier_VERSION}\")") -endif() - -# Check version compatibility -check_required_components(SVMClassifier) \ No newline at end of file +set(SVMClassifier_FOUND TRUE) \ No newline at end of file diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 33db4aa..4446312 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,3 +1,5 @@ +# External dependencies CMakeLists.txt - Fixed version with OBJECT libraries + include(FetchContent) # Set policies for FetchContent @@ -21,23 +23,33 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(liblinear) -# Build libsvm as static library +# Build libsvm as OBJECT library to avoid export issues if(EXISTS "${libsvm_SOURCE_DIR}/svm.cpp") set(LIBSVM_SOURCES "${libsvm_SOURCE_DIR}/svm.cpp") - add_library(libsvm_static STATIC ${LIBSVM_SOURCES}) - target_include_directories(libsvm_static PUBLIC ${libsvm_SOURCE_DIR}) + add_library(libsvm_objects OBJECT ${LIBSVM_SOURCES}) + + # Set properties for the object library + target_include_directories(libsvm_objects + PRIVATE + ${libsvm_SOURCE_DIR} + ) # Set C++ standard for libsvm - target_compile_features(libsvm_static PUBLIC cxx_std_17) + target_compile_features(libsvm_objects PRIVATE cxx_std_17) - message(STATUS "libsvm built successfully") + # 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, creating dummy target") - add_library(libsvm_static INTERFACE) + 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 as static library +# Build liblinear as OBJECT library set(LIBLINEAR_SOURCES) # Check for main liblinear source files @@ -67,33 +79,40 @@ else() endforeach() endif() -# Create liblinear library if we have source files +# Create liblinear object library if we have source files if(LIBLINEAR_SOURCES) - add_library(liblinear_static STATIC ${LIBLINEAR_SOURCES}) + add_library(liblinear_objects OBJECT ${LIBLINEAR_SOURCES}) - target_include_directories(liblinear_static - PUBLIC + # Set properties for the object library + target_include_directories(liblinear_objects + PRIVATE ${liblinear_SOURCE_DIR} ) # Add blas directory if it exists if(EXISTS "${liblinear_SOURCE_DIR}/blas") - target_include_directories(liblinear_static - PUBLIC ${liblinear_SOURCE_DIR}/blas + target_include_directories(liblinear_objects + PRIVATE ${liblinear_SOURCE_DIR}/blas ) endif() # Set C++ standard for liblinear - target_compile_features(liblinear_static PUBLIC cxx_std_17) + target_compile_features(liblinear_objects PRIVATE cxx_std_17) # Compiler specific flags if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_compile_options(liblinear_static PRIVATE -w) # Suppress warnings + 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() message(STATUS "liblinear built with sources: ${LIBLINEAR_SOURCES}") else() - # Create minimal liblinear implementation + # Create minimal liblinear implementation as object library message(WARNING "liblinear source files not found, creating minimal implementation") # Create a minimal linear.cpp file @@ -139,12 +158,15 @@ else() "}\n" ) - add_library(liblinear_static STATIC "${MINIMAL_LIBLINEAR_DIR}/linear.cpp") - target_include_directories(liblinear_static PUBLIC ${MINIMAL_LIBLINEAR_DIR}) - target_compile_features(liblinear_static PUBLIC cxx_std_17) + add_library(liblinear_objects OBJECT "${MINIMAL_LIBLINEAR_DIR}/linear.cpp") + target_include_directories(liblinear_objects PRIVATE ${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}") +message(STATUS " - Using OBJECT libraries to avoid export issues") \ No newline at end of file diff --git a/include/svm_classifier/types.hpp b/include/svm_classifier/types.hpp index db16b62..56d4cff 100644 --- a/include/svm_classifier/types.hpp +++ b/include/svm_classifier/types.hpp @@ -3,6 +3,8 @@ #include #include #include +#include + namespace svm_classifier {