Update CMakeLists and conanfile
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,3 +38,4 @@ cmake-build*/**
|
|||||||
.idea
|
.idea
|
||||||
puml/**
|
puml/**
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
|
CMakeUserPresets.json
|
||||||
|
@@ -35,7 +35,7 @@ make help # Show all available targets
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
- Requires `VCPKG_ROOT` environment variable set
|
- Requires Conan package manager (`pip install conan`)
|
||||||
- Miniconda installation required for Python classifiers
|
- Miniconda installation required for Python classifiers
|
||||||
- Boost library (preferably system package: `sudo dnf install boost-devel`)
|
- Boost library (preferably system package: `sudo dnf install boost-devel`)
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ make help # Show all available targets
|
|||||||
- `pyclfs/PyClassifier.h` - Base classifier interface
|
- `pyclfs/PyClassifier.h` - Base classifier interface
|
||||||
- `CMakeLists.txt` - Main build configuration
|
- `CMakeLists.txt` - Main build configuration
|
||||||
- `Makefile` - Build automation and common tasks
|
- `Makefile` - Build automation and common tasks
|
||||||
- `vcpkg.json` - Package dependencies
|
- `conanfile.py` - Package dependencies
|
||||||
- `tests/TestPythonClassifiers.cc` - Main test suite
|
- `tests/TestPythonClassifiers.cc` - Main test suite
|
||||||
|
|
||||||
## Technical Requirements
|
## Technical Requirements
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
project(PyClassifiers
|
project(PyClassifiers
|
||||||
VERSION 1.0.3
|
VERSION 1.0.3
|
||||||
DESCRIPTION "Python Classifiers Wrapper."
|
DESCRIPTION "Python Classifiers Wrapper."
|
||||||
@@ -6,15 +7,7 @@ project(PyClassifiers
|
|||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
if (CODE_COVERAGE AND NOT ENABLE_TESTING)
|
cmake_policy(SET CMP0135 NEW)
|
||||||
MESSAGE(FATAL_ERROR "Code coverage requires testing enabled")
|
|
||||||
endif (CODE_COVERAGE AND NOT ENABLE_TESTING)
|
|
||||||
|
|
||||||
find_package(Torch REQUIRED)
|
|
||||||
|
|
||||||
if (POLICY CMP0135)
|
|
||||||
cmake_policy(SET CMP0135 NEW)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Global CMake variables
|
# Global CMake variables
|
||||||
# ----------------------
|
# ----------------------
|
||||||
@@ -22,14 +15,23 @@ set(CMAKE_CXX_STANDARD 17)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
|
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
MESSAGE("Debug mode")
|
||||||
|
else(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
MESSAGE("Release mode")
|
||||||
|
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
# -------
|
# -------
|
||||||
option(ENABLE_TESTING "Unit testing build" OFF)
|
option(ENABLE_TESTING "Unit testing build" OFF)
|
||||||
option(CODE_COVERAGE "Collect coverage from test library" OFF)
|
|
||||||
option(INSTALL_GTEST "Enable installation of googletest." OFF)
|
# External libraries
|
||||||
|
# ------------------
|
||||||
|
find_package(Torch REQUIRED)
|
||||||
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
|
find_package(bayesnet CONFIG REQUIRED)
|
||||||
|
|
||||||
# Boost Library
|
# Boost Library
|
||||||
set(Boost_USE_STATIC_LIBS OFF)
|
set(Boost_USE_STATIC_LIBS OFF)
|
||||||
@@ -45,36 +47,8 @@ endif()
|
|||||||
find_package(Python3 3.11 COMPONENTS Interpreter Development REQUIRED)
|
find_package(Python3 3.11 COMPONENTS Interpreter Development REQUIRED)
|
||||||
message("Python3_LIBRARIES=${Python3_LIBRARIES}")
|
message("Python3_LIBRARIES=${Python3_LIBRARIES}")
|
||||||
|
|
||||||
find_package(nlohmann_json CONFIG REQUIRED)
|
# Add the library
|
||||||
|
# ---------------
|
||||||
# CMakes modules
|
|
||||||
# --------------
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
|
|
||||||
include(AddGitSubmodule)
|
|
||||||
|
|
||||||
if (CODE_COVERAGE)
|
|
||||||
enable_testing()
|
|
||||||
include(CodeCoverage)
|
|
||||||
MESSAGE("Code coverage enabled")
|
|
||||||
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0 -g")
|
|
||||||
SET(GCC_COVERAGE_LINK_FLAGS " ${GCC_COVERAGE_LINK_FLAGS} -lgcov --coverage")
|
|
||||||
endif (CODE_COVERAGE)
|
|
||||||
|
|
||||||
if (ENABLE_CLANG_TIDY)
|
|
||||||
include(StaticAnalyzers) # clang-tidy
|
|
||||||
endif (ENABLE_CLANG_TIDY)
|
|
||||||
|
|
||||||
# External libraries - dependencies of PyClassifiers
|
|
||||||
# --------------------------------------------------
|
|
||||||
find_library(bayesnet NAMES libbayesnet bayesnet libbayesnet.a PATHS ${PyClassifiers_SOURCE_DIR}/../lib/lib REQUIRED)
|
|
||||||
find_path(Bayesnet_INCLUDE_DIRS REQUIRED NAMES bayesnet PATHS ../lib/include)
|
|
||||||
|
|
||||||
message(STATUS "BayesNet=${bayesnet}")
|
|
||||||
message(STATUS "Bayesnet_INCLUDE_DIRS=${Bayesnet_INCLUDE_DIRS}")
|
|
||||||
|
|
||||||
|
|
||||||
# Subdirectories
|
|
||||||
# --------------
|
|
||||||
add_subdirectory(pyclfs)
|
add_subdirectory(pyclfs)
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
@@ -83,6 +57,14 @@ if (ENABLE_TESTING)
|
|||||||
MESSAGE("Testing enabled")
|
MESSAGE("Testing enabled")
|
||||||
find_package(Catch2 CONFIG REQUIRED)
|
find_package(Catch2 CONFIG REQUIRED)
|
||||||
find_package(arff-files CONFIG REQUIRED)
|
find_package(arff-files CONFIG REQUIRED)
|
||||||
|
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0 -g")
|
||||||
|
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-default-inline")
|
||||||
|
endif()
|
||||||
|
## Configure test data path
|
||||||
|
cmake_path(SET TEST_DATA_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests/data")
|
||||||
|
configure_file(tests/config/SourceData.h.in "${CMAKE_BINARY_DIR}/configured_files/include/SourceData.h")
|
||||||
|
enable_testing()
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif (ENABLE_TESTING)
|
endif (ENABLE_TESTING)
|
||||||
@@ -92,6 +74,6 @@ endif (ENABLE_TESTING)
|
|||||||
install(TARGETS PyClassifiers
|
install(TARGETS PyClassifiers
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
CONFIGURATIONS Release)
|
)
|
||||||
install(DIRECTORY pyclfs/ DESTINATION include/pyclassifiers FILES_MATCHING CONFIGURATIONS Release PATTERN "*.h" PATTERN "*.hpp")
|
install(DIRECTORY pyclfs/ DESTINATION include/pyclassifiers FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp")
|
||||||
install(FILES ${Bayesnet_INCLUDE_DIRS}/bayesnet/config.h DESTINATION include/pyclassifiers CONFIGURATIONS Release)
|
|
||||||
|
65
Makefile
65
Makefile
@@ -3,6 +3,14 @@ f_debug = build_debug
|
|||||||
app_targets = PyClassifiers
|
app_targets = PyClassifiers
|
||||||
test_targets = unit_tests_pyclassifiers
|
test_targets = unit_tests_pyclassifiers
|
||||||
|
|
||||||
|
# Set the number of parallel jobs to the number of available processors minus 7
|
||||||
|
CPUS := $(shell getconf _NPROCESSORS_ONLN 2>/dev/null \
|
||||||
|
|| nproc --all 2>/dev/null \
|
||||||
|
|| sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
# --- Your desired job count: CPUs – 7, but never less than 1 --------------
|
||||||
|
JOBS := $(shell n=$(CPUS); [ $${n} -gt 7 ] && echo $$((n-7)) || echo 1)
|
||||||
|
|
||||||
define ClearTests
|
define ClearTests
|
||||||
@for t in $(test_targets); do \
|
@for t in $(test_targets); do \
|
||||||
if [ -f $(f_debug)/tests/$$t ]; then \
|
if [ -f $(f_debug)/tests/$$t ]; then \
|
||||||
@@ -16,6 +24,25 @@ define ClearTests
|
|||||||
fi ;
|
fi ;
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define build_target
|
||||||
|
@echo ">>> Building the project for $(1)..."
|
||||||
|
@if [ -d $(2) ]; then rm -fr $(2); fi
|
||||||
|
@conan install . --build=missing -of $(2) -s build_type=$(1)
|
||||||
|
@cmake -S . -B $(2) -DCMAKE_TOOLCHAIN_FILE=$(2)/build/$(1)/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=$(1) -D$(3)
|
||||||
|
@echo ">>> Will build using $(JOBS) parallel jobs"
|
||||||
|
echo ">>> Done"
|
||||||
|
endef
|
||||||
|
|
||||||
|
define compile_target
|
||||||
|
@echo ">>> Compiling for $(1)..."
|
||||||
|
if [ "$(3)" != "" ]; then \
|
||||||
|
target="-t$(3)"; \
|
||||||
|
else \
|
||||||
|
target=""; \
|
||||||
|
fi
|
||||||
|
@cmake --build $(2) --config $(1) --parallel $(JOBS) $(target)
|
||||||
|
@echo ">>> Done"
|
||||||
|
endef
|
||||||
|
|
||||||
setup: ## Install dependencies for tests and coverage
|
setup: ## Install dependencies for tests and coverage
|
||||||
@if [ "$(shell uname)" = "Darwin" ]; then \
|
@if [ "$(shell uname)" = "Darwin" ]; then \
|
||||||
@@ -32,10 +59,10 @@ dependency: ## Create a dependency graph diagram of the project (build/dependenc
|
|||||||
cd $(f_debug) && cmake .. --graphviz=dependency.dot && dot -Tpng dependency.dot -o dependency.png
|
cd $(f_debug) && cmake .. --graphviz=dependency.dot && dot -Tpng dependency.dot -o dependency.png
|
||||||
|
|
||||||
buildd: ## Build the debug targets
|
buildd: ## Build the debug targets
|
||||||
cmake --build $(f_debug) -t $(app_targets) --parallel
|
@$(call compile_target,"Debug","$(f_debug)")
|
||||||
|
|
||||||
buildr: ## Build the release targets
|
buildr: ## Build the release targets
|
||||||
cmake --build $(f_release) -t $(app_targets) --parallel
|
@$(call compile_target,"Release","$(f_release)")
|
||||||
|
|
||||||
clean: ## Clean the tests info
|
clean: ## Clean the tests info
|
||||||
@echo ">>> Cleaning Debug PyClassifiers tests...";
|
@echo ">>> Cleaning Debug PyClassifiers tests...";
|
||||||
@@ -48,19 +75,11 @@ install: ## Install library
|
|||||||
@cmake --install $(f_release) --prefix $(prefix)
|
@cmake --install $(f_release) --prefix $(prefix)
|
||||||
@echo ">>> Done";
|
@echo ">>> Done";
|
||||||
|
|
||||||
debug: ## Build a debug version of the project
|
debug: ## Build a debug version of the project with Conan
|
||||||
@echo ">>> Building Debug PyClassifiers...";
|
@$(call build_target,"Debug","$(f_debug)", "ENABLE_TESTING=ON")
|
||||||
@if [ -d ./$(f_debug) ]; then rm -rf ./$(f_debug); fi
|
|
||||||
@mkdir $(f_debug);
|
|
||||||
@cmake -S . -B $(f_debug) -D CMAKE_BUILD_TYPE=Debug -D ENABLE_TESTING=ON -D CODE_COVERAGE=ON -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake
|
|
||||||
@echo ">>> Done";
|
|
||||||
|
|
||||||
release: ## Build a Release version of the project
|
release: ## Build a Release version of the project with Conan
|
||||||
@echo ">>> Building Release PyClassifiers...";
|
@$(call build_target,"Release","$(f_release)", "ENABLE_TESTING=OFF")
|
||||||
@if [ -d ./$(f_release) ]; then rm -rf ./$(f_release); fi
|
|
||||||
@mkdir $(f_release);
|
|
||||||
@cmake -S . -B $(f_release) -D CMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake
|
|
||||||
@echo ">>> Done";
|
|
||||||
|
|
||||||
opt = ""
|
opt = ""
|
||||||
test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section
|
test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section
|
||||||
@@ -81,6 +100,24 @@ coverage: ## Run tests and generate coverage report (build/index.html)
|
|||||||
@gcovr $(f_debug)/tests
|
@gcovr $(f_debug)/tests
|
||||||
@echo ">>> Done";
|
@echo ">>> Done";
|
||||||
|
|
||||||
|
# Conan package manager targets
|
||||||
|
# =============================
|
||||||
|
|
||||||
|
conan-create: ## Create Conan package
|
||||||
|
@echo ">>> Creating Conan package..."
|
||||||
|
@echo ">>> Creating Release build..."
|
||||||
|
@conan create . --build=missing -tf "" -s:a build_type=Release
|
||||||
|
@echo ">>> Creating Debug build..."
|
||||||
|
@conan create . --build=missing -tf "" -s:a build_type=Debug -o "&:enable_testing=False"
|
||||||
|
@echo ">>> Done"
|
||||||
|
|
||||||
|
conan-clean: ## Clean Conan cache and build folders
|
||||||
|
@echo ">>> Cleaning Conan cache and build folders..."
|
||||||
|
@conan remove "*" --confirm
|
||||||
|
@conan cache clean
|
||||||
|
@if test -d "$(f_release)" ; then rm -rf "$(f_release)"; fi
|
||||||
|
@if test -d "$(f_debug)" ; then rm -rf "$(f_debug)"; fi
|
||||||
|
@echo ">>> Done"
|
||||||
|
|
||||||
help: ## Show help message
|
help: ## Show help message
|
||||||
@IFS=$$'\n' ; \
|
@IFS=$$'\n' ; \
|
||||||
|
10
README.md
10
README.md
@@ -52,6 +52,16 @@ Don't forget to add the export BOOST_ROOT statement to .bashrc or wherever it is
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Install Conan package manager:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install conan
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build and Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make release
|
make release
|
||||||
make buildr
|
make buildr
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
|
|
||||||
function(add_git_submodule dir)
|
|
||||||
find_package(Git REQUIRED)
|
|
||||||
|
|
||||||
if(NOT EXISTS ${dir}/CMakeLists.txt)
|
|
||||||
message(STATUS "🚨 Adding git submodule => ${dir}")
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE}
|
|
||||||
submodule update --init --recursive -- ${dir}
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
add_subdirectory(${dir})
|
|
||||||
endfunction(add_git_submodule)
|
|
@@ -1,746 +0,0 @@
|
|||||||
# Copyright (c) 2012 - 2017, Lars Bilke
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
# list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software without
|
|
||||||
# specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# CHANGES:
|
|
||||||
#
|
|
||||||
# 2012-01-31, Lars Bilke
|
|
||||||
# - Enable Code Coverage
|
|
||||||
#
|
|
||||||
# 2013-09-17, Joakim Söderberg
|
|
||||||
# - Added support for Clang.
|
|
||||||
# - Some additional usage instructions.
|
|
||||||
#
|
|
||||||
# 2016-02-03, Lars Bilke
|
|
||||||
# - Refactored functions to use named parameters
|
|
||||||
#
|
|
||||||
# 2017-06-02, Lars Bilke
|
|
||||||
# - Merged with modified version from github.com/ufz/ogs
|
|
||||||
#
|
|
||||||
# 2019-05-06, Anatolii Kurotych
|
|
||||||
# - Remove unnecessary --coverage flag
|
|
||||||
#
|
|
||||||
# 2019-12-13, FeRD (Frank Dana)
|
|
||||||
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
|
|
||||||
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
|
|
||||||
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
|
|
||||||
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
|
|
||||||
# - Set lcov basedir with -b argument
|
|
||||||
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
|
|
||||||
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
|
|
||||||
# - Delete output dir, .info file on 'make clean'
|
|
||||||
# - Remove Python detection, since version mismatches will break gcovr
|
|
||||||
# - Minor cleanup (lowercase function names, update examples...)
|
|
||||||
#
|
|
||||||
# 2019-12-19, FeRD (Frank Dana)
|
|
||||||
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
|
|
||||||
#
|
|
||||||
# 2020-01-19, Bob Apthorpe
|
|
||||||
# - Added gfortran support
|
|
||||||
#
|
|
||||||
# 2020-02-17, FeRD (Frank Dana)
|
|
||||||
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
|
|
||||||
# in EXCLUDEs, and remove manual escaping from gcovr targets
|
|
||||||
#
|
|
||||||
# 2021-01-19, Robin Mueller
|
|
||||||
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
|
|
||||||
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
|
|
||||||
# flags to the gcovr command
|
|
||||||
#
|
|
||||||
# 2020-05-04, Mihchael Davis
|
|
||||||
# - Add -fprofile-abs-path to make gcno files contain absolute paths
|
|
||||||
# - Fix BASE_DIRECTORY not working when defined
|
|
||||||
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
|
|
||||||
#
|
|
||||||
# 2021-05-10, Martin Stump
|
|
||||||
# - Check if the generator is multi-config before warning about non-Debug builds
|
|
||||||
#
|
|
||||||
# 2022-02-22, Marko Wehle
|
|
||||||
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
|
|
||||||
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
|
|
||||||
#
|
|
||||||
# 2022-09-28, Sebastian Mueller
|
|
||||||
# - fix append_coverage_compiler_flags_to_target to correctly add flags
|
|
||||||
# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
|
|
||||||
#
|
|
||||||
# USAGE:
|
|
||||||
#
|
|
||||||
# 1. Copy this file into your cmake modules path.
|
|
||||||
#
|
|
||||||
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
|
|
||||||
# using a CMake option() to enable it just optionally):
|
|
||||||
# include(CodeCoverage)
|
|
||||||
#
|
|
||||||
# 3. Append necessary compiler flags for all supported source files:
|
|
||||||
# append_coverage_compiler_flags()
|
|
||||||
# Or for specific target:
|
|
||||||
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
|
|
||||||
#
|
|
||||||
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
|
||||||
#
|
|
||||||
# 4. If you need to exclude additional directories from the report, specify them
|
|
||||||
# using full paths in the COVERAGE_EXCLUDES variable before calling
|
|
||||||
# setup_target_for_coverage_*().
|
|
||||||
# Example:
|
|
||||||
# set(COVERAGE_EXCLUDES
|
|
||||||
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
|
|
||||||
# '/path/to/my/src/dir2/*')
|
|
||||||
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
|
|
||||||
# Example:
|
|
||||||
# setup_target_for_coverage_lcov(
|
|
||||||
# NAME coverage
|
|
||||||
# EXECUTABLE testrunner
|
|
||||||
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
|
|
||||||
#
|
|
||||||
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
|
|
||||||
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
|
|
||||||
# Example:
|
|
||||||
# set(COVERAGE_EXCLUDES "dir1/*")
|
|
||||||
# setup_target_for_coverage_gcovr_html(
|
|
||||||
# NAME coverage
|
|
||||||
# EXECUTABLE testrunner
|
|
||||||
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
|
|
||||||
# EXCLUDE "dir2/*")
|
|
||||||
#
|
|
||||||
# 5. Use the functions described below to create a custom make target which
|
|
||||||
# runs your test executable and produces a code coverage report.
|
|
||||||
#
|
|
||||||
# 6. Build a Debug build:
|
|
||||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
|
||||||
# make
|
|
||||||
# make my_coverage_target
|
|
||||||
#
|
|
||||||
|
|
||||||
include(CMakeParseArguments)
|
|
||||||
|
|
||||||
option(CODE_COVERAGE_VERBOSE "Verbose information" TRUE)
|
|
||||||
|
|
||||||
# Check prereqs
|
|
||||||
find_program( GCOV_PATH gcov )
|
|
||||||
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
|
||||||
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
|
|
||||||
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
|
||||||
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
|
||||||
find_program( CPPFILT_PATH NAMES c++filt )
|
|
||||||
|
|
||||||
if(NOT GCOV_PATH)
|
|
||||||
message(FATAL_ERROR "gcov not found! Aborting...")
|
|
||||||
endif() # NOT GCOV_PATH
|
|
||||||
|
|
||||||
# Check supported compiler (Clang, GNU and Flang)
|
|
||||||
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
|
||||||
foreach(LANG ${LANGUAGES})
|
|
||||||
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
|
||||||
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
|
|
||||||
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
|
||||||
endif()
|
|
||||||
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
|
||||||
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
|
|
||||||
if ("${LANG}" MATCHES "CUDA")
|
|
||||||
message(STATUS "Ignoring CUDA")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
|
|
||||||
CACHE INTERNAL "")
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path)
|
|
||||||
if(HAVE_fprofile_abs_path)
|
|
||||||
set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_Fortran_FLAGS_COVERAGE
|
|
||||||
${COVERAGE_COMPILER_FLAGS}
|
|
||||||
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
|
|
||||||
FORCE )
|
|
||||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
|
||||||
${COVERAGE_COMPILER_FLAGS}
|
|
||||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
|
||||||
FORCE )
|
|
||||||
set(CMAKE_C_FLAGS_COVERAGE
|
|
||||||
${COVERAGE_COMPILER_FLAGS}
|
|
||||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
|
||||||
FORCE )
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
|
||||||
""
|
|
||||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
|
||||||
FORCE )
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
|
||||||
""
|
|
||||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
|
||||||
FORCE )
|
|
||||||
mark_as_advanced(
|
|
||||||
CMAKE_Fortran_FLAGS_COVERAGE
|
|
||||||
CMAKE_CXX_FLAGS_COVERAGE
|
|
||||||
CMAKE_C_FLAGS_COVERAGE
|
|
||||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
|
||||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
|
||||||
|
|
||||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
||||||
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
|
||||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
|
||||||
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
|
||||||
|
|
||||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
|
||||||
link_libraries(gcov)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Defines a target for running and collection code coverage information
|
|
||||||
# Builds dependencies, runs the given executable and outputs reports.
|
|
||||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
|
||||||
# the coverage generation will not complete.
|
|
||||||
#
|
|
||||||
# setup_target_for_coverage_lcov(
|
|
||||||
# NAME testrunner_coverage # New target name
|
|
||||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
|
||||||
# DEPENDENCIES testrunner # Dependencies to build first
|
|
||||||
# BASE_DIRECTORY "../" # Base directory for report
|
|
||||||
# # (defaults to PROJECT_SOURCE_DIR)
|
|
||||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
|
||||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
|
||||||
# NO_DEMANGLE # Don't demangle C++ symbols
|
|
||||||
# # even if c++filt is found
|
|
||||||
# )
|
|
||||||
function(setup_target_for_coverage_lcov)
|
|
||||||
|
|
||||||
set(options NO_DEMANGLE SONARQUBE)
|
|
||||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
|
||||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
|
|
||||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(NOT LCOV_PATH)
|
|
||||||
message(FATAL_ERROR "lcov not found! Aborting...")
|
|
||||||
endif() # NOT LCOV_PATH
|
|
||||||
|
|
||||||
if(NOT GENHTML_PATH)
|
|
||||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
|
||||||
endif() # NOT GENHTML_PATH
|
|
||||||
|
|
||||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
|
||||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
|
||||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
|
||||||
else()
|
|
||||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
|
||||||
set(LCOV_EXCLUDES "")
|
|
||||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
|
||||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
|
||||||
endif()
|
|
||||||
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
|
|
||||||
endforeach()
|
|
||||||
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
|
|
||||||
|
|
||||||
# Conditional arguments
|
|
||||||
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
|
||||||
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Setting up commands which will be run to generate coverage data.
|
|
||||||
# Cleanup lcov
|
|
||||||
set(LCOV_CLEAN_CMD
|
|
||||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory .
|
|
||||||
-b ${BASEDIR} --zerocounters
|
|
||||||
)
|
|
||||||
# Create baseline to make sure untouched files show up in the report
|
|
||||||
set(LCOV_BASELINE_CMD
|
|
||||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
|
|
||||||
${BASEDIR} -o ${Coverage_NAME}.base
|
|
||||||
)
|
|
||||||
# Run tests
|
|
||||||
set(LCOV_EXEC_TESTS_CMD
|
|
||||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
|
||||||
)
|
|
||||||
# Capturing lcov counters and generating report
|
|
||||||
set(LCOV_CAPTURE_CMD
|
|
||||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
|
|
||||||
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
|
|
||||||
)
|
|
||||||
# add baseline counters
|
|
||||||
set(LCOV_BASELINE_COUNT_CMD
|
|
||||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
|
|
||||||
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
|
|
||||||
)
|
|
||||||
# filter collected data to final coverage report
|
|
||||||
set(LCOV_FILTER_CMD
|
|
||||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
|
|
||||||
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
|
|
||||||
)
|
|
||||||
# Generate HTML output
|
|
||||||
set(LCOV_GEN_HTML_CMD
|
|
||||||
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
|
|
||||||
${Coverage_NAME} ${Coverage_NAME}.info
|
|
||||||
)
|
|
||||||
if(${Coverage_SONARQUBE})
|
|
||||||
# Generate SonarQube output
|
|
||||||
set(GCOVR_XML_CMD
|
|
||||||
${GCOVR_PATH} --sonarqube ${Coverage_NAME}_sonarqube.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
|
||||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
set(GCOVR_XML_CMD_COMMAND
|
|
||||||
COMMAND ${GCOVR_XML_CMD}
|
|
||||||
)
|
|
||||||
set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml)
|
|
||||||
set(GCOVR_XML_CMD_COMMENT COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if(CODE_COVERAGE_VERBOSE)
|
|
||||||
message(STATUS "Executed command report")
|
|
||||||
message(STATUS "Command to clean up lcov: ")
|
|
||||||
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
|
|
||||||
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to create baseline: ")
|
|
||||||
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
|
|
||||||
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to run the tests: ")
|
|
||||||
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
|
|
||||||
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to capture counters and generate report: ")
|
|
||||||
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
|
|
||||||
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to add baseline counters: ")
|
|
||||||
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
|
|
||||||
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to filter collected data: ")
|
|
||||||
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
|
|
||||||
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to generate lcov HTML output: ")
|
|
||||||
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
|
|
||||||
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
|
|
||||||
|
|
||||||
if(${Coverage_SONARQUBE})
|
|
||||||
message(STATUS "Command to generate SonarQube XML output: ")
|
|
||||||
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
|
||||||
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Setup target
|
|
||||||
add_custom_target(${Coverage_NAME}
|
|
||||||
COMMAND ${LCOV_CLEAN_CMD}
|
|
||||||
COMMAND ${LCOV_BASELINE_CMD}
|
|
||||||
COMMAND ${LCOV_EXEC_TESTS_CMD}
|
|
||||||
COMMAND ${LCOV_CAPTURE_CMD}
|
|
||||||
COMMAND ${LCOV_BASELINE_COUNT_CMD}
|
|
||||||
COMMAND ${LCOV_FILTER_CMD}
|
|
||||||
COMMAND ${LCOV_GEN_HTML_CMD}
|
|
||||||
${GCOVR_XML_CMD_COMMAND}
|
|
||||||
|
|
||||||
# Set output files as GENERATED (will be removed on 'make clean')
|
|
||||||
BYPRODUCTS
|
|
||||||
${Coverage_NAME}.base
|
|
||||||
${Coverage_NAME}.capture
|
|
||||||
${Coverage_NAME}.total
|
|
||||||
${Coverage_NAME}.info
|
|
||||||
${GCOVR_XML_CMD_BYPRODUCTS}
|
|
||||||
${Coverage_NAME}/index.html
|
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
||||||
DEPENDS ${Coverage_DEPENDENCIES}
|
|
||||||
VERBATIM # Protect arguments to commands
|
|
||||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Show where to find the lcov info report
|
|
||||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
|
||||||
COMMAND ;
|
|
||||||
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
|
|
||||||
${GCOVR_XML_CMD_COMMENT}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Show info where to find the report
|
|
||||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
|
||||||
COMMAND ;
|
|
||||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
|
||||||
)
|
|
||||||
|
|
||||||
endfunction() # setup_target_for_coverage_lcov
|
|
||||||
|
|
||||||
# Defines a target for running and collection code coverage information
|
|
||||||
# Builds dependencies, runs the given executable and outputs reports.
|
|
||||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
|
||||||
# the coverage generation will not complete.
|
|
||||||
#
|
|
||||||
# setup_target_for_coverage_gcovr_xml(
|
|
||||||
# NAME ctest_coverage # New target name
|
|
||||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
|
||||||
# DEPENDENCIES executable_target # Dependencies to build first
|
|
||||||
# BASE_DIRECTORY "../" # Base directory for report
|
|
||||||
# # (defaults to PROJECT_SOURCE_DIR)
|
|
||||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
|
||||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
|
||||||
# )
|
|
||||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
|
||||||
# GCVOR command.
|
|
||||||
function(setup_target_for_coverage_gcovr_xml)
|
|
||||||
|
|
||||||
set(options NONE)
|
|
||||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
|
||||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
|
||||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(NOT GCOVR_PATH)
|
|
||||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
|
||||||
endif() # NOT GCOVR_PATH
|
|
||||||
|
|
||||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
|
||||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
|
||||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
|
||||||
else()
|
|
||||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
|
||||||
set(GCOVR_EXCLUDES "")
|
|
||||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
|
||||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
|
||||||
endif()
|
|
||||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
|
||||||
endforeach()
|
|
||||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
|
||||||
|
|
||||||
# Combine excludes to several -e arguments
|
|
||||||
set(GCOVR_EXCLUDE_ARGS "")
|
|
||||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
|
||||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
|
||||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Set up commands which will be run to generate coverage data
|
|
||||||
# Run tests
|
|
||||||
set(GCOVR_XML_EXEC_TESTS_CMD
|
|
||||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
|
||||||
)
|
|
||||||
# Running gcovr
|
|
||||||
set(GCOVR_XML_CMD
|
|
||||||
${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
|
||||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CODE_COVERAGE_VERBOSE)
|
|
||||||
message(STATUS "Executed command report")
|
|
||||||
|
|
||||||
message(STATUS "Command to run tests: ")
|
|
||||||
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
|
|
||||||
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to generate gcovr XML coverage data: ")
|
|
||||||
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
|
||||||
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_target(${Coverage_NAME}
|
|
||||||
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
|
|
||||||
COMMAND ${GCOVR_XML_CMD}
|
|
||||||
|
|
||||||
BYPRODUCTS ${Coverage_NAME}.xml
|
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
||||||
DEPENDS ${Coverage_DEPENDENCIES}
|
|
||||||
VERBATIM # Protect arguments to commands
|
|
||||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Show info where to find the report
|
|
||||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
|
||||||
COMMAND ;
|
|
||||||
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
|
|
||||||
)
|
|
||||||
endfunction() # setup_target_for_coverage_gcovr_xml
|
|
||||||
|
|
||||||
# Defines a target for running and collection code coverage information
|
|
||||||
# Builds dependencies, runs the given executable and outputs reports.
|
|
||||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
|
||||||
# the coverage generation will not complete.
|
|
||||||
#
|
|
||||||
# setup_target_for_coverage_gcovr_html(
|
|
||||||
# NAME ctest_coverage # New target name
|
|
||||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
|
||||||
# DEPENDENCIES executable_target # Dependencies to build first
|
|
||||||
# BASE_DIRECTORY "../" # Base directory for report
|
|
||||||
# # (defaults to PROJECT_SOURCE_DIR)
|
|
||||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
|
||||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
|
||||||
# )
|
|
||||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
|
||||||
# GCVOR command.
|
|
||||||
function(setup_target_for_coverage_gcovr_html)
|
|
||||||
|
|
||||||
set(options NONE)
|
|
||||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
|
||||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
|
||||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(NOT GCOVR_PATH)
|
|
||||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
|
||||||
endif() # NOT GCOVR_PATH
|
|
||||||
|
|
||||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
|
||||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
|
||||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
|
||||||
else()
|
|
||||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
|
||||||
set(GCOVR_EXCLUDES "")
|
|
||||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
|
||||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
|
||||||
endif()
|
|
||||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
|
||||||
endforeach()
|
|
||||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
|
||||||
|
|
||||||
# Combine excludes to several -e arguments
|
|
||||||
set(GCOVR_EXCLUDE_ARGS "")
|
|
||||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
|
||||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
|
||||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Set up commands which will be run to generate coverage data
|
|
||||||
# Run tests
|
|
||||||
set(GCOVR_HTML_EXEC_TESTS_CMD
|
|
||||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
|
||||||
)
|
|
||||||
# Create folder
|
|
||||||
set(GCOVR_HTML_FOLDER_CMD
|
|
||||||
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
|
|
||||||
)
|
|
||||||
# Running gcovr
|
|
||||||
set(GCOVR_HTML_CMD
|
|
||||||
${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
|
||||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CODE_COVERAGE_VERBOSE)
|
|
||||||
message(STATUS "Executed command report")
|
|
||||||
|
|
||||||
message(STATUS "Command to run tests: ")
|
|
||||||
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
|
|
||||||
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to create a folder: ")
|
|
||||||
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
|
|
||||||
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(STATUS "Command to generate gcovr HTML coverage data: ")
|
|
||||||
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
|
|
||||||
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_target(${Coverage_NAME}
|
|
||||||
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
|
|
||||||
COMMAND ${GCOVR_HTML_FOLDER_CMD}
|
|
||||||
COMMAND ${GCOVR_HTML_CMD}
|
|
||||||
|
|
||||||
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
|
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
||||||
DEPENDS ${Coverage_DEPENDENCIES}
|
|
||||||
VERBATIM # Protect arguments to commands
|
|
||||||
COMMENT "Running gcovr to produce HTML code coverage report."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Show info where to find the report
|
|
||||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
|
||||||
COMMAND ;
|
|
||||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
|
||||||
)
|
|
||||||
|
|
||||||
endfunction() # setup_target_for_coverage_gcovr_html
|
|
||||||
|
|
||||||
# Defines a target for running and collection code coverage information
|
|
||||||
# Builds dependencies, runs the given executable and outputs reports.
|
|
||||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
|
||||||
# the coverage generation will not complete.
|
|
||||||
#
|
|
||||||
# setup_target_for_coverage_fastcov(
|
|
||||||
# NAME testrunner_coverage # New target name
|
|
||||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
|
||||||
# DEPENDENCIES testrunner # Dependencies to build first
|
|
||||||
# BASE_DIRECTORY "../" # Base directory for report
|
|
||||||
# # (defaults to PROJECT_SOURCE_DIR)
|
|
||||||
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
|
|
||||||
# NO_DEMANGLE # Don't demangle C++ symbols
|
|
||||||
# # even if c++filt is found
|
|
||||||
# SKIP_HTML # Don't create html report
|
|
||||||
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
|
|
||||||
# )
|
|
||||||
function(setup_target_for_coverage_fastcov)
|
|
||||||
|
|
||||||
set(options NO_DEMANGLE SKIP_HTML)
|
|
||||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
|
||||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
|
|
||||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(NOT FASTCOV_PATH)
|
|
||||||
message(FATAL_ERROR "fastcov not found! Aborting...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
|
|
||||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
|
||||||
if(Coverage_BASE_DIRECTORY)
|
|
||||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
|
||||||
else()
|
|
||||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Collect excludes (Patterns, not paths, for fastcov)
|
|
||||||
set(FASTCOV_EXCLUDES "")
|
|
||||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
|
|
||||||
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
|
|
||||||
endforeach()
|
|
||||||
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
|
|
||||||
|
|
||||||
# Conditional arguments
|
|
||||||
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
|
||||||
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set up commands which will be run to generate coverage data
|
|
||||||
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
|
||||||
|
|
||||||
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
|
||||||
--search-directory ${BASEDIR}
|
|
||||||
--process-gcno
|
|
||||||
--output ${Coverage_NAME}.json
|
|
||||||
--exclude ${FASTCOV_EXCLUDES}
|
|
||||||
)
|
|
||||||
|
|
||||||
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
|
|
||||||
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
|
|
||||||
)
|
|
||||||
|
|
||||||
if(Coverage_SKIP_HTML)
|
|
||||||
set(FASTCOV_HTML_CMD ";")
|
|
||||||
else()
|
|
||||||
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
|
|
||||||
-o ${Coverage_NAME} ${Coverage_NAME}.info
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(FASTCOV_POST_CMD ";")
|
|
||||||
if(Coverage_POST_CMD)
|
|
||||||
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CODE_COVERAGE_VERBOSE)
|
|
||||||
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
|
|
||||||
|
|
||||||
message(" Running tests:")
|
|
||||||
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
|
|
||||||
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(" Capturing fastcov counters and generating report:")
|
|
||||||
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
|
|
||||||
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
|
|
||||||
|
|
||||||
message(" Converting fastcov .json to lcov .info:")
|
|
||||||
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
|
|
||||||
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
|
|
||||||
|
|
||||||
if(NOT Coverage_SKIP_HTML)
|
|
||||||
message(" Generating HTML report: ")
|
|
||||||
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
|
|
||||||
message(" ${FASTCOV_HTML_CMD_SPACED}")
|
|
||||||
endif()
|
|
||||||
if(Coverage_POST_CMD)
|
|
||||||
message(" Running post command: ")
|
|
||||||
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
|
|
||||||
message(" ${FASTCOV_POST_CMD_SPACED}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Setup target
|
|
||||||
add_custom_target(${Coverage_NAME}
|
|
||||||
|
|
||||||
# Cleanup fastcov
|
|
||||||
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
|
||||||
--search-directory ${BASEDIR}
|
|
||||||
--zerocounters
|
|
||||||
|
|
||||||
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
|
|
||||||
COMMAND ${FASTCOV_CAPTURE_CMD}
|
|
||||||
COMMAND ${FASTCOV_CONVERT_CMD}
|
|
||||||
COMMAND ${FASTCOV_HTML_CMD}
|
|
||||||
COMMAND ${FASTCOV_POST_CMD}
|
|
||||||
|
|
||||||
# Set output files as GENERATED (will be removed on 'make clean')
|
|
||||||
BYPRODUCTS
|
|
||||||
${Coverage_NAME}.info
|
|
||||||
${Coverage_NAME}.json
|
|
||||||
${Coverage_NAME}/index.html # report directory
|
|
||||||
|
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
||||||
DEPENDS ${Coverage_DEPENDENCIES}
|
|
||||||
VERBATIM # Protect arguments to commands
|
|
||||||
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
|
|
||||||
)
|
|
||||||
|
|
||||||
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
|
|
||||||
if(NOT Coverage_SKIP_HTML)
|
|
||||||
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
|
|
||||||
endif()
|
|
||||||
# Show where to find the fastcov info report
|
|
||||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
|
|
||||||
)
|
|
||||||
|
|
||||||
endfunction() # setup_target_for_coverage_fastcov
|
|
||||||
|
|
||||||
function(append_coverage_compiler_flags)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
|
||||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
|
||||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
|
||||||
endfunction() # append_coverage_compiler_flags
|
|
||||||
|
|
||||||
# Setup coverage for specific library
|
|
||||||
function(append_coverage_compiler_flags_to_target name)
|
|
||||||
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
|
||||||
target_compile_options(${name} PRIVATE ${_flag_list})
|
|
||||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
|
||||||
target_link_libraries(${name} PRIVATE gcov)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
@@ -1,22 +0,0 @@
|
|||||||
if(ENABLE_CLANG_TIDY)
|
|
||||||
find_program(CLANG_TIDY_COMMAND NAMES clang-tidy)
|
|
||||||
|
|
||||||
if(NOT CLANG_TIDY_COMMAND)
|
|
||||||
message(WARNING "🔴 CMake_RUN_CLANG_TIDY is ON but clang-tidy is not found!")
|
|
||||||
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE)
|
|
||||||
else()
|
|
||||||
|
|
||||||
message(STATUS "🟢 CMake_RUN_CLANG_TIDY is ON")
|
|
||||||
set(CLANGTIDY_EXTRA_ARGS
|
|
||||||
"-extra-arg=-Wno-unknown-warning-option"
|
|
||||||
)
|
|
||||||
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};-p=${CMAKE_BINARY_DIR};${CLANGTIDY_EXTRA_ARGS}" CACHE STRING "" FORCE)
|
|
||||||
|
|
||||||
add_custom_target(clang-tidy
|
|
||||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${CMAKE_PROJECT_NAME}
|
|
||||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target clang-tidy
|
|
||||||
COMMENT "Running clang-tidy..."
|
|
||||||
)
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
||||||
endif()
|
|
||||||
endif(ENABLE_CLANG_TIDY)
|
|
82
conanfile.py
Normal file
82
conanfile.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import os, re, pathlib
|
||||||
|
from conan import ConanFile
|
||||||
|
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
|
||||||
|
from conan.tools.files import copy
|
||||||
|
|
||||||
|
|
||||||
|
class PlatformConan(ConanFile):
|
||||||
|
name = "pyclassifiers"
|
||||||
|
version = "1.0.3"
|
||||||
|
|
||||||
|
# Binary configuration
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
options = {
|
||||||
|
"enable_testing": [True, False],
|
||||||
|
}
|
||||||
|
default_options = {
|
||||||
|
"enable_testing": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Sources are located in the same place as this recipe, copy them to the recipe
|
||||||
|
exports_sources = "CMakeLists.txt", "pyclfs/*", "tests/*", "LICENSE"
|
||||||
|
|
||||||
|
def set_version(self) -> None:
|
||||||
|
cmake = pathlib.Path(self.recipe_folder) / "CMakeLists.txt"
|
||||||
|
text = cmake.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
match = re.search(
|
||||||
|
r"""project\s*\([^\)]*VERSION\s+([0-9]+\.[0-9]+\.[0-9]+)""",
|
||||||
|
text, re.IGNORECASE | re.VERBOSE
|
||||||
|
)
|
||||||
|
if match:
|
||||||
|
self.version = match.group(1)
|
||||||
|
else:
|
||||||
|
raise Exception("Version not found in CMakeLists.txt")
|
||||||
|
self.version = match.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
self.requires("libtorch/2.7.0")
|
||||||
|
self.requires("nlohmann_json/3.11.3")
|
||||||
|
self.requires("folding/1.1.1")
|
||||||
|
self.requires("fimdlp/2.1.0")
|
||||||
|
self.requires("bayesnet/1.2.0")
|
||||||
|
|
||||||
|
def build_requirements(self):
|
||||||
|
self.tool_requires("cmake/[>=3.30]")
|
||||||
|
self.test_requires("catch2/3.8.1")
|
||||||
|
self.test_requires("arff-files/1.2.0")
|
||||||
|
|
||||||
|
def layout(self):
|
||||||
|
cmake_layout(self)
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
deps = CMakeDeps(self)
|
||||||
|
deps.generate()
|
||||||
|
tc = CMakeToolchain(self)
|
||||||
|
tc.generate()
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.configure()
|
||||||
|
cmake.build()
|
||||||
|
|
||||||
|
if self.options.enable_testing:
|
||||||
|
# Run tests only if we're building with testing enabled
|
||||||
|
self.run("ctest --output-on-failure", cwd=self.build_folder)
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.install()
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
self.cpp_info.libs = ["pyclassifiers"]
|
||||||
|
self.cpp_info.includedirs = ["include"]
|
||||||
|
self.cpp_info.set_property("cmake_find_mode", "both")
|
||||||
|
self.cpp_info.set_property("cmake_target_name", "pyclassifiers::pyclassifiers")
|
||||||
|
|
||||||
|
# Add compiler flags that might be needed
|
||||||
|
if self.settings.os == "Linux":
|
||||||
|
self.cpp_info.system_libs = ["pthread"]
|
@@ -1,8 +1,10 @@
|
|||||||
include_directories(
|
include_directories(
|
||||||
${Python3_INCLUDE_DIRS}
|
${Python3_INCLUDE_DIRS}
|
||||||
${TORCH_INCLUDE_DIRS}
|
|
||||||
${PyClassifiers_SOURCE_DIR}/lib/json/include
|
${PyClassifiers_SOURCE_DIR}/lib/json/include
|
||||||
${Bayesnet_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
add_library(PyClassifiers ODTE.cc STree.cc SVC.cc RandomForest.cc XGBoost.cc AdaBoostPy.cc PyClassifier.cc PyWrap.cc)
|
add_library(PyClassifiers ODTE.cc STree.cc SVC.cc RandomForest.cc XGBoost.cc AdaBoostPy.cc PyClassifier.cc PyWrap.cc)
|
||||||
target_link_libraries(PyClassifiers nlohmann_json::nlohmann_json ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy)
|
target_link_libraries(PyClassifiers PRIVATE
|
||||||
|
nlohmann_json::nlohmann_json torch::torch
|
||||||
|
Boost::boost Boost::python Boost::numpy
|
||||||
|
bayesnet::bayesnet
|
||||||
|
)
|
||||||
|
@@ -3,12 +3,15 @@ if(ENABLE_TESTING)
|
|||||||
include_directories(
|
include_directories(
|
||||||
${PyClassifiers_SOURCE_DIR}
|
${PyClassifiers_SOURCE_DIR}
|
||||||
${Python3_INCLUDE_DIRS}
|
${Python3_INCLUDE_DIRS}
|
||||||
${TORCH_INCLUDE_DIRS}
|
|
||||||
${CMAKE_BINARY_DIR}/configured_files/include
|
${CMAKE_BINARY_DIR}/configured_files/include
|
||||||
/usr/local/include
|
|
||||||
)
|
)
|
||||||
file(GLOB_RECURSE PyClassifiers_SOURCES "${PyClassifiers_SOURCE_DIR}/pyclfs/*.cc")
|
file(GLOB_RECURSE PyClassifiers_SOURCES "${PyClassifiers_SOURCE_DIR}/pyclfs/*.cc")
|
||||||
set(TEST_SOURCES_PYCLASSIFIERS TestPythonClassifiers.cc TestUtils.cc ${PyClassifiers_SOURCES})
|
set(TEST_SOURCES_PYCLASSIFIERS TestPythonClassifiers.cc TestUtils.cc ${PyClassifiers_SOURCES})
|
||||||
add_executable(${TEST_PYCLASSIFIERS} ${TEST_SOURCES_PYCLASSIFIERS})
|
add_executable(${TEST_PYCLASSIFIERS} ${TEST_SOURCES_PYCLASSIFIERS})
|
||||||
target_link_libraries(${TEST_PYCLASSIFIERS} PUBLIC "${TORCH_LIBRARIES}" ${Python3_LIBRARIES} ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy fimdlp Catch2::Catch2WithMain)
|
target_link_libraries(${TEST_PYCLASSIFIERS} PUBLIC
|
||||||
endif(ENABLE_TESTING)
|
torch::torch ${Python3_LIBRARIES} ${LIBTORCH_PYTHON}
|
||||||
|
Boost::boost Boost::python Boost::numpy fimdlp::fimdlp
|
||||||
|
Catch2::Catch2WithMain nlohmann_json::nlohmann_json
|
||||||
|
bayesnet::bayesnet
|
||||||
|
)
|
||||||
|
endif(ENABLE_TESTING)
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
#include "TestUtils.h"
|
#include "TestUtils.h"
|
||||||
#include "bayesnet/config.h"
|
#include "SourceData.h"
|
||||||
|
|
||||||
class Paths {
|
class Paths {
|
||||||
public:
|
public:
|
||||||
static std::string datasets()
|
static std::string datasets()
|
||||||
{
|
{
|
||||||
return { data_path.begin(), data_path.end() };
|
return pywrap::SourceData("Test").getPath();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "ArffFiles/ArffFiles.hpp"
|
#include "ArffFiles.hpp"
|
||||||
#include "fimdlp/CPPFImdlp.h"
|
#include "fimdlp/CPPFImdlp.h"
|
||||||
|
|
||||||
bool file_exists(const std::string& name);
|
bool file_exists(const std::string& name);
|
||||||
@@ -40,4 +40,4 @@ public:
|
|||||||
double epsilon = 1e-5;
|
double epsilon = 1e-5;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //TEST_UTILS_H
|
#endif //TEST_UTILS_H
|
||||||
|
38
tests/config/SourceData.h.in
Normal file
38
tests/config/SourceData.h.in
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef SOURCEDATA_H
|
||||||
|
#define SOURCEDATA_H
|
||||||
|
namespace pywrap {
|
||||||
|
enum fileType_t { CSV, ARFF, RDATA };
|
||||||
|
class SourceData {
|
||||||
|
public:
|
||||||
|
SourceData(std::string source)
|
||||||
|
{
|
||||||
|
if (source == "Surcov") {
|
||||||
|
path = "datasets/";
|
||||||
|
fileType = CSV;
|
||||||
|
} else if (source == "Arff") {
|
||||||
|
path = "datasets/";
|
||||||
|
fileType = ARFF;
|
||||||
|
} else if (source == "Tanveer") {
|
||||||
|
path = "data/";
|
||||||
|
fileType = RDATA;
|
||||||
|
} else if (source == "Test") {
|
||||||
|
path = "@TEST_DATA_PATH@/";
|
||||||
|
fileType = ARFF;
|
||||||
|
} else {
|
||||||
|
throw std::invalid_argument("Unknown source.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string getPath()
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
fileType_t getFileType()
|
||||||
|
{
|
||||||
|
return fileType;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string path;
|
||||||
|
fileType_t fileType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
47
vcpkg.json
47
vcpkg.json
@@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "platform",
|
|
||||||
"version-string": "1.1.0",
|
|
||||||
"dependencies": [
|
|
||||||
"arff-files",
|
|
||||||
"nlohmann-json",
|
|
||||||
"fimdlp",
|
|
||||||
"libtorch-bin",
|
|
||||||
"folding",
|
|
||||||
"argparse",
|
|
||||||
"catch2"
|
|
||||||
],
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"name": "arff-files",
|
|
||||||
"version": "1.1.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fimdlp",
|
|
||||||
"version": "2.0.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "libtorch-bin",
|
|
||||||
"version": "2.7.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "bayesnet",
|
|
||||||
"version": "1.1.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "folding",
|
|
||||||
"version": "1.1.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "argpase",
|
|
||||||
"version": "3.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "catch2",
|
|
||||||
"version": "3.8.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "nlohmann-json",
|
|
||||||
"version": "3.11.3"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Reference in New Issue
Block a user