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