diff --git a/CMakeLists.txt b/CMakeLists.txt index 80c5ae7a11964a847676e46deb1b80c1e509f2f6..b3c6d459dfaf29f5accbc0be4565a3709e9ffd3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,22 @@ # CMake >= 3.18 is required for good support of FindCUDAToolkit -cmake_minimum_required(VERSION 3.18) # XXX 3.18 -set(CXX_STANDARD 14) +cmake_minimum_required(VERSION 3.18) -file(STRINGS "${CMAKE_SOURCE_DIR}/version.txt" version) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Read project metadata file(STRINGS "${CMAKE_SOURCE_DIR}/project_name.txt" project) +message(STATUS "Project name: ${project}") +file(STRINGS "${CMAKE_SOURCE_DIR}/version.txt" version) # Parse version.txt to retrieve Major, Minor and Path string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" _ MATCHES ${version}) set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) +message(STATUS "Project version: ${version}") + # Retrieve latest git commit execute_process( @@ -19,17 +26,25 @@ execute_process( OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) - -message(STATUS "Project name: ${project}") -message(STATUS "Project version: ${version}") message(STATUS "Latest git commit: ${GIT_COMMIT_HASH}") -message(STATUS "Creating ${CMAKE_CURRENT_SOURCE_DIR}/include/aidge/quantization_version.h") project(${project} VERSION ${version} DESCRIPTION "Quantization methods for the Aidge framework." LANGUAGES CXX) + +if(NOT $ENV{AIDGE_INSTALL} STREQUAL "") + set(CMAKE_INSTALL_PREFIX $ENV{AIDGE_INSTALL}) + list(APPEND CMAKE_PREFIX_PATH $ENV{AIDGE_INSTALL}) + message(WARNING "Env var AIDGE_INSTALL detected : $ENV{AIDGE_INSTALL}. Set CMAKE_INSTALL_PREFIX to AIDGE_INSTALL & added to CMAKE_PREFIX_PATH" + "\n\tCMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}" + "\n\tCMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") +endif() + +message(STATUS "Creating ${CMAKE_CURRENT_SOURCE_DIR}/include/aidge/quantization_version.h") + + # Note: Using configure_file later in the code make so that version variables are lost... # I tried to set in internal cache but it failed. # Current code is working, but there might be a scope issue. @@ -39,21 +54,12 @@ configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/include/aidge/quantization_version.h" ) -# Note : project name is {project} and python module name is also {project} -set(module_name _${project}) # target name -set(pybind_module_name ${CMAKE_PROJECT_NAME}) # name of submodule for python bindings - -set(CXX_STANDARD 14) - -############################################## -# Import utils CMakeLists -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") ############################################## # Define options -option(PYBIND "python binding" ON) +option(PYBIND "python binding" OFF) option(WERROR "Warning as error" OFF) -option(TEST "Enable tests" ON) +option(TEST "Enable tests" OFF) option(COVERAGE "Enable coverage" OFF) option(CUDA "Enable CUDA backend" OFF) # XXX OFF option(ENABLE_ASAN "Enable ASan (AddressSanitizer) for runtime analysis of memory use (over/underflow, memory leak, ...)" OFF) @@ -61,74 +67,55 @@ option(ENABLE_ASAN "Enable ASan (AddressSanitizer) for runtime analysis of memor ############################################## # Import utils CMakeLists set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") -include(PybindModuleCreation) if(CMAKE_COMPILER_IS_GNUCXX AND COVERAGE) Include(CodeCoverage) endif() +# Set variables if(CUDA) enable_language(CUDA) - message(STATUS "Cuda compiler version = ${CMAKE_CUDA_COMPILER_VERSION}") # Define a preprocessor macro with the Cuda compiler version add_definitions(-DCUDA_COMPILER_VERSION="${CMAKE_CUDA_COMPILER_VERSION}") endif() -if(NOT $ENV{AIDGE_INSTALL} STREQUAL "") - set(CMAKE_INSTALL_PREFIX $ENV{AIDGE_INSTALL}) - list(APPEND CMAKE_PREFIX_PATH $ENV{AIDGE_INSTALL}) - message(WARNING "Env var AIDGE_INSTALL detected : $ENV{AIDGE_INSTALL}. Set CMAKE_INSTALL_PREFIX to AIDGE_INSTALL & added to CMAKE_PREFIX_PATH" - "\n\tCMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}" - "\n\tCMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") +# Source files +if(CUDA) + file(GLOB_RECURSE src_files "src/*.cpp" "src/*.cu") +else() + file(GLOB_RECURSE src_files "src/*.cpp") endif() -# ############################################## -# Find system dependencies +# Header files +file(GLOB_RECURSE inc_files "include/*.hpp") -if(CUDA) - find_package(CUDAToolkit REQUIRED) -endif() +# Note: cxx project name is {CMAKE_PROJECT_NAME} and python module name is also {CMAKE_PROJECT_NAME} +set(module_name _${CMAKE_PROJECT_NAME}) # target name +add_library(${module_name} ${src_files} ${inc_files}) +set(pybind_module_name ${CMAKE_PROJECT_NAME}) # name of submodule for python bindings -############################################## -# Find system dependencies +# Dependencies and linking find_package(aidge_core REQUIRED) find_package(aidge_backend_cpu REQUIRED) +target_link_libraries(${module_name} + PUBLIC + _aidge_core + _aidge_backend_cpu +) if(CUDA) + find_package(CUDAToolkit REQUIRED) find_package(aidge_backend_cuda REQUIRED) -endif() - -############################################## -# Create target and set properties - -if(CUDA) - file(GLOB_RECURSE src_files "src/*.cpp" "src/*.cu") - file(GLOB_RECURSE inc_files "include/*.hpp") - - add_library(${module_name} ${src_files} ${inc_files}) target_link_libraries(${module_name} PUBLIC - _aidge_core # _ is added because we link the target not the project - _aidge_backend_cpu - # _aidge_backend_cuda # XXX CUDA::cudart CUDA::cublas cudnn ) -else() - file(GLOB_RECURSE src_files "src/*.cpp") - file(GLOB_RECURSE inc_files "include/*.hpp") - - add_library(${module_name} ${src_files} ${inc_files}) - target_link_libraries(${module_name} - PUBLIC - _aidge_core # _ is added because we link the target not the project - _aidge_backend_cpu - ) endif() -#Set target properties +# Include directories target_include_directories(${module_name} PUBLIC $<INSTALL_INTERFACE:include> @@ -137,6 +124,7 @@ target_include_directories(${module_name} ${CMAKE_CURRENT_SOURCE_DIR}/src ) +# Compilation settings if(CUDA) if(NOT DEFINED CMAKE_CUDA_STANDARD) set(CMAKE_CUDA_STANDARD 14) @@ -157,23 +145,44 @@ if (PYBIND) generate_python_binding(${pybind_module_name} ${module_name}) endif() -# XXX HERE !!! -target_link_libraries(${module_name} PRIVATE fmt::fmt) target_compile_features(${module_name} PRIVATE cxx_std_14) +target_link_libraries(${module_name} PRIVATE fmt::fmt) +#################################### +# Compilation options and warnings target_compile_options(${module_name} PRIVATE + # Options for Clang, AppleClang, and GCC compilers $<$<COMPILE_LANGUAGE:CPP>:$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>: - -Wall -Wextra -Wold-style-cast -Winline -pedantic -Werror=narrowing -Wshadow $<$<BOOL:${WERROR}>:-Werror>>>) + -Wall # Enable all warnings + -Wextra # Enable extra warnings + -Wold-style-cast # Warn about C-style casts + -Winline # Warn if inline expansion fails + -pedantic # Enforce strict ISO C++ standards + -Werror=narrowing # Treat narrowing conversions as errors + -Wshadow # Warn about variable shadowing + $<$<BOOL:${WERROR}>:-Werror> # Optionally treat warnings as errors + >> +) + +# Additional MSVC-specific warning level +target_compile_options(${module_name} PRIVATE + $<$<CXX_COMPILER_ID:MSVC>: + /W4 # Warning level 4 (highest for MSVC) + > +) + +# CUDA-specific compile options if(CUDA) target_compile_options(${module_name} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: - -Wall>) + -Wall # Enable all warnings for CUDA + > + ) endif() -target_compile_options(${module_name} PRIVATE - $<$<CXX_COMPILER_ID:MSVC>: - /W4>) +# Coverage flags for GCC if(CMAKE_COMPILER_IS_GNUCXX AND COVERAGE) + include(CodeCoverage) append_coverage_compiler_flags() endif() @@ -183,29 +192,31 @@ endif() include(GNUInstallDirs) set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${project}) +# Install the library target install(TARGETS ${module_name} EXPORT ${project}-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) +# Install header files install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -#Export the targets to a script - +# Export targets for other projects to use install(EXPORT ${project}-targets - FILE "${project}-targets.cmake" - DESTINATION ${INSTALL_CONFIGDIR} - COMPONENT ${module_name} + FILE "${project}-targets.cmake" + DESTINATION ${INSTALL_CONFIGDIR} + COMPONENT ${module_name} ) -if (PYBIND) +# Python binding installation +if(PYBIND) install(TARGETS ${pybind_module_name} DESTINATION ${PYBIND_INSTALL_PREFIX} ) endif() -#Create a ConfigVersion.cmake file +# Create and install CMake configuration files include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/${project}-config-version.cmake" @@ -218,15 +229,14 @@ configure_package_config_file("${project}-config.cmake.in" INSTALL_DESTINATION ${INSTALL_CONFIGDIR} ) -#Install the config, configversion and custom find modules +# Install CMake configuration files install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${project}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${project}-config-version.cmake" DESTINATION ${INSTALL_CONFIGDIR} ) -############################################## -## Exporting from the build tree +# Export from build tree export(EXPORT ${project}-targets FILE "${CMAKE_CURRENT_BINARY_DIR}/${project}-targets.cmake") @@ -234,10 +244,6 @@ export(EXPORT ${project}-targets ############################################## ## Add test if(TEST) - if (AIDGE_REQUIRES_PYTHON AND NOT AIDGE_PYTHON_HAS_EMBED) - message(WARNING "Skipping compilation of tests: missing Python embedded interpreter") - else() - enable_testing() - add_subdirectory(unit_tests) - endif() + enable_testing() + add_subdirectory(unit_tests) endif() diff --git a/pyproject.toml b/pyproject.toml index deb91c7c87936542ff126f26083a1b87502e19ae..c7cd4c2ac427e7ed71615882e7bb97d081a7dafa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ description="Quantization algorithms to compress aidge networks." dependencies = [ "numpy>=1.21.6", ] -requires-python = ">= 3.7" +requires-python = ">= 3.8" readme = "README.md" license = { file = "LICENSE" } classifiers = [ @@ -56,6 +56,19 @@ test-command = "pytest {package}/aidge_quantization/unit_tests" # "cp39-win_amd64", # "cp310-win_amd64", # ] +# PYLINT +[tool.pylint.main] +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-allow-list = ["aidge_core", "aidge_backend_cpu", "aidge_quantization", "onnx"] +# Files or directories to be skipped. They should be base names, not paths. +ignore = ["CVS"] +# List of module names for which member attributes should not be checked (useful +# for modules/projects where namespaces are manipulated during runtime and thus +# existing member attributes cannot be deduced by static analysis). It supports +# qualified module names, as well as Unix pattern matching. +ignored-modules = ["aidge_core", "aidge_backend_cpu", "aidge_quantization", "onnx"] ## AIDGE DEPENDENCIES DECLARATION [tool.cibuildwheel.environment] AIDGE_DEPENDENCIES = "aidge_core aidge_backend_cpu aidge_onnx" # format => "dep_1 dep_2 ... dep_n" diff --git a/setup.py b/setup.py index 8774d01a4abd69c76319c71b610e98061153d4c2..1bfc0ac515fd8cceeec4cba666addc1e7666fd25 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,7 @@ class AidgePkgBuild(build_ext): # This lists the number of processors available on the machine # The compilation will use half of them max_jobs = str(ceil(multiprocessing.cpu_count() / 2)) + max_jobs = os.environ.get("AIDGE_NB_PROC", max_jobs) cwd = pathlib.Path().absolute() @@ -51,14 +52,20 @@ class AidgePkgBuild(build_ext): package_prefix = build_lib if not self.editable_mode else SETUP_DIR pybind_install_prefix = (package_prefix / PROJECT_NAME).absolute() - os.chdir(str(build_temp)) - - compile_type = os.environ.get("AIDGE_PYTHON_BUILD_TYPE", "Release") install_path = ( os.path.join(sys.prefix, "lib", "libAidge") if "AIDGE_INSTALL" not in os.environ else os.environ["AIDGE_INSTALL"] ) + + # Read environment variables for CMake options + c_compiler = os.environ.get("AIDGE_C_COMPILER", "gcc") + cxx_compiler = os.environ.get("AIDGE_CXX_COMPILER", "g++") + build_type = os.environ.get("AIDGE_BUILD_TYPE", "Release") + asan = os.environ.get("AIDGE_ASAN", "OFF") + with_cuda = os.environ.get("AIDGE_WITH_CUDA", "OFF") + cmake_arch = os.environ.get("AIDGE_CMAKE_ARCH", "") + build_gen = os.environ.get("AIDGE_BUILD_GEN", "") build_gen_opts = ( ["-G", build_gen] @@ -67,26 +74,36 @@ class AidgePkgBuild(build_ext): ) test_onoff = os.environ.get("AIDGE_BUILD_TEST", "OFF") - self.spawn( - [ - "cmake", - *build_gen_opts, - str(cwd), - f"-DTEST={test_onoff}", - f"-DCMAKE_INSTALL_PREFIX:PATH={install_path}", - f"-DCMAKE_BUILD_TYPE={compile_type}", - "-DPYBIND=ON", - f"-DPYBIND_INSTALL_PREFIX:PATH={pybind_install_prefix}", - "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", - "-DCOVERAGE=OFF", - ] - ) + os.chdir(str(build_temp)) + + cmake_cmd = [ + "cmake", + *build_gen_opts, + str(cwd), + f"-DTEST={test_onoff}", + f"-DCMAKE_INSTALL_PREFIX:PATH={install_path}", + f"-DCMAKE_BUILD_TYPE={build_type}", + f"-DCMAKE_C_COMPILER={c_compiler}", + f"-DCMAKE_CXX_COMPILER={cxx_compiler}", + f"-DENABLE_ASAN={asan}", + f"-DCUDA={with_cuda}", + "-DPYBIND=ON", + f"-DPYBIND_INSTALL_PREFIX:PATH={pybind_install_prefix}", + "-DCMAKE_EXPORT_COMPILE_COMMANDS=1", + "-DCOVERAGE=OFF", + ] + + # Append architecture-specific arguments if provided + if cmake_arch: + cmake_cmd.append(cmake_arch) + + self.spawn(cmake_cmd) if not self.dry_run: self.spawn( - ["cmake", "--build", ".", "--config", compile_type, "-j", max_jobs] + ["cmake", "--build", ".", "--config", build_type, "-j", max_jobs] ) - self.spawn(["cmake", "--install", ".", "--config", compile_type]) + self.spawn(["cmake", "--install", ".", "--config", build_type]) os.chdir(str(cwd)) diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt index 9d9f81516b0cd2611484ee9e3e06e838833200db..cfdbf0ad393cca9daa300cddd807a7667523d2a0 100644 --- a/unit_tests/CMakeLists.txt +++ b/unit_tests/CMakeLists.txt @@ -1,12 +1,23 @@ -Include(FetchContent) +# Catch2 configuration +set(CATCH2_MIN_VERSION 3.3.0) -FetchContent_Declare( - Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v3.0.1 # or a later release -) +# Try to find system installed Catch2 +find_package(Catch2 ${CATCH2_MIN_VERSION} QUIET) -FetchContent_MakeAvailable(Catch2) +if(NOT Catch2_FOUND) + message(STATUS "Catch2 not found in system, retrieving from git") + Include(FetchContent) + + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG devel # or a later release + ) + FetchContent_MakeAvailable(Catch2) + message(STATUS "Fetched Catch2 version ${Catch2_VERSION}") +else() + message(STATUS "Using system Catch2 version ${Catch2_VERSION}") +endif() file(GLOB_RECURSE src_files "*.cpp") diff --git a/unit_tests/Test_QuantPTQ.cpp b/unit_tests/Test_QuantPTQ.cpp index 36377e84e27e9de9cc28de323cfba5a44cb80904..e7211ce4092f789c8c6263671ad236b97934ffbb 100644 --- a/unit_tests/Test_QuantPTQ.cpp +++ b/unit_tests/Test_QuantPTQ.cpp @@ -1,21 +1,19 @@ -// #include <catch2/catch_test_macros.hpp> - -// #include "aidge/data/Tensor.hpp" -// #include "aidge/backend/TensorImpl.hpp" -// #include "aidge/backend/cpu.hpp" -// #include "aidge/operator/Conv.hpp" -// #include "aidge/operator/Scaling.hpp" -// #include "aidge/operator/GenericOperator.hpp" -// #include "aidge/graph/GraphView.hpp" -// #include "aidge/QuantPTQ.hpp" -// #include "aidge/scheduler/Scheduler.hpp" -// #include "aidge/hook/OutputRange.hpp" -// #include "aidge/operator/Producer.hpp" - -// #include <unordered_map> - -// using namespace Aidge; -// //using namespace Aidge_HELPER; +/******************************************************************************** + * Copyright (c) 2023 CEA-List + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ + +#include <catch2/catch_test_macros.hpp> + +TEST_CASE("[tmp] basic test") { + REQUIRE(true == true); +} // TEST_CASE("[aidge_module_template/ref_cpp/quantization] PTQ : Quantize Graph") { @@ -79,7 +77,7 @@ // std::shared_ptr<Tensor> myInput = // std::make_shared<Tensor>( -// Array4D<float,2,3,5,5> { +// Array4D<float,2,3,5,5> { // { // { // {{ 0., 1., 2., 3., 4.}, @@ -124,7 +122,7 @@ // ); // auto dataProvider = Producer(myInput, "dataProvider"); -// Tensor myOutput = Array4D<float,2,4,3,3> { +// Tensor myOutput = Array4D<float,2,4,3,3> { // { // { // {{ 15226., 15577., 15928.}, @@ -188,9 +186,9 @@ // "%f" // "\n", // max_output_conv); - + // } - + // float max_output_relu = std::static_pointer_cast<OutputRange>(myReLU1->getOperator()->getHook("output_range"))->getOutput(0); // if(verbose) { // printf("[hook] OutputRange(forward) :: ReLU output max: " @@ -222,10 +220,10 @@ // "\n", // (nodePtr->type()).c_str(), (nodePtr->name()).c_str()); // } -// } - +// } + // SequentialScheduler scheduler_v2(g1); - + // scheduler_v2.forward(); // scheduler_v2.generateScheduling(false); // std::vector<std::shared_ptr<Node>> ordered_graph_view_v2 = scheduler_v2.getStaticScheduling(); @@ -242,7 +240,7 @@ // "\n", // (nodePtr->type()).c_str(), (nodePtr->name()).c_str()); // } -// } +// } // } \ No newline at end of file