Skip to content

Commit 4ba3eef

Browse files
author
AstroAir
committed
Systematic testing fixes
1 parent 1e05ca3 commit 4ba3eef

60 files changed

Lines changed: 928 additions & 396 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.augment/rules/build-mingw.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ type: "manual"
44

55
# MinGW64 Build Configuration
66

7-
Build the entire Atom project using the MSYS2 (MinGW64) toolchain and resolve
7+
Build the entire Atom project using the MSYS2 (MinGW64) preset and resolve
88
all compilation/linking issues that arise during the build process.
99

1010
## Specific Requirements

BUILD_MINGW64.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# MSYS2 MinGW64 Build Guide
2+
3+
This guide explains how to build the Atom project on Windows using the MSYS2 MinGW64 toolchain.
4+
5+
## Prerequisites
6+
7+
- Windows 10/11 x64
8+
- MSYS2 installed (suggested path: `D:\msys64` or `C:\msys64`)
9+
- CMake ≥ 3.21 (we use presets)
10+
- Ninja or mingw32-make is not required explicitly; presets use the "MinGW Makefiles" generator
11+
12+
### Install MSYS2 and required packages
13+
14+
1. Download and install MSYS2: <https://www.msys2.org/>
15+
2. Open the "MSYS2 MinGW x64" shell and run:
16+
17+
```bash
18+
pacman -Syu # Full system update (may require restarting the shell)
19+
pacman -S --needed \
20+
mingw-w64-x86_64-gcc \
21+
mingw-w64-x86_64-cmake \
22+
mingw-w64-x86_64-make \
23+
mingw-w64-x86_64-openssl \
24+
mingw-w64-x86_64-zlib \
25+
mingw-w64-x86_64-pkgconf \
26+
mingw-w64-x86_64-libuv \
27+
mingw-w64-x86_64-sqlite3 \
28+
mingw-w64-x86_64-libusb \
29+
mingw-w64-x86_64-curl \
30+
mingw-w64-x86_64-opencv \
31+
mingw-w64-x86_64-tbb \
32+
mingw-w64-x86_64-leptonica \
33+
mingw-w64-x86_64-tesseract
34+
```
35+
36+
Notes:
37+
- OpenSSL and Zlib are required by this project; the preset passes `OPENSSL_ROOT_DIR` and `ZLIB_ROOT` to CMake.
38+
- Additional packages (OpenCV, libuv, sqlite3, libusb, curl, TBB) are used by optional modules and will be picked up automatically when present.
39+
40+
## Configure and build using CMake Presets
41+
42+
From a regular Windows PowerShell (or inside the MSYS2 MinGW64 shell), in the repository root:
43+
44+
```powershell
45+
# Optional: ensure MSYS2 MinGW64 is on PATH for PowerShell sessions
46+
if (Test-Path 'D:\msys64\mingw64\bin') { $env:Path = 'D:\msys64\mingw64\bin;D:\msys64\usr\bin;' + $env:Path }
47+
if (Test-Path 'C:\msys64\mingw64\bin') { $env:Path = 'C:\msys64\mingw64\bin;C:\msys64\usr\bin;' + $env:Path }
48+
49+
# Configure (RelWithDebInfo) and build
50+
cmake --preset relwithdebinfo-msys2
51+
cmake --build --preset relwithdebinfo-msys2 -j 8
52+
```
53+
54+
Artifacts are generated under `build-mingw64/` to avoid mixing with MSVC builds.
55+
56+
### Enable tests/examples
57+
58+
```powershell
59+
cmake --preset relwithdebinfo-msys2 -DATOM_BUILD_TESTS=ON -DATOM_BUILD_EXAMPLES=ON
60+
cmake --build --preset relwithdebinfo-msys2 -j 8
61+
ctest --test-dir build-mingw64 --output-on-failure
62+
```
63+
64+
## Notes on cross-compiler compatibility
65+
66+
- The codebase uses conditional compilation to handle MSVC vs GCC/MinGW differences via `atom/macro.hpp` and standard compiler macros (`_MSC_VER`, `__GNUC__`, `__MINGW64__`).
67+
- The build system selects appropriate flags for GCC/Clang using `cmake/CompilerOptions.cmake`.
68+
69+
## Troubleshooting
70+
71+
- OpenSSL or Zlib not found: Ensure the MSYS2 `mingw64` packages for OpenSSL and Zlib are installed. The preset sets `OPENSSL_ROOT_DIR` and `ZLIB_ROOT` to `D:/msys64/mingw64`. If your MSYS2 is installed elsewhere, set them explicitly:
72+
73+
```powershell
74+
cmake --preset relwithdebinfo-msys2 -DOPENSSL_ROOT_DIR=E:/Tools/msys64/mingw64 -DZLIB_ROOT=E:/Tools/msys64/mingw64
75+
```
76+
77+
- Missing `mingw32-make.exe`: Install `mingw-w64-x86_64-make` in MSYS2.
78+
- Generator cache conflicts: We use a dedicated `build-mingw64/` directory for MSYS2 to avoid generator clashes.
79+
80+
## What the preset does
81+
82+
- Uses the "MinGW Makefiles" generator
83+
- Builds into `build-mingw64/`
84+
- Turns off vcpkg and uses MSYS2 libraries
85+
- Points CMake to the MSYS2 `mingw64` prefix to discover OpenSSL/Zlib automatically

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
cmake_minimum_required(VERSION 3.21)
44

5+
# Allow configuring older third-party projects (e.g., googletest) with modern
6+
# CMake See error: "Compatibility with CMake < 3.5 has been removed from CMake"
7+
# Setting this minimum policy version enables compatibility for subprojects.
8+
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
9+
510
# Set a global policy to handle malformed package configurations
611
if(POLICY CMP0000)
712
cmake_policy(SET CMP0000 NEW)
@@ -68,6 +73,7 @@ option(ATOM_BUILD_TESTS_SELECTIVE "Enable selective building of test modules"
6873
OFF)
6974
option(ATOM_BUILD_PYTHON_BINDINGS "Build Python bindings" OFF)
7075
option(ATOM_BUILD_DOCS "Build documentation" OFF)
76+
option(ATOM_ENABLE_PACKAGING "Enable CPack packaging configuration" OFF)
7177
option(ATOM_USE_BOOST "Enable Boost high-performance data structures" OFF)
7278
option(ATOM_USE_BOOST_LOCKFREE "Enable Boost lock-free data structures" OFF)
7379
option(ATOM_USE_BOOST_CONTAINER "Enable Boost container library" OFF)
@@ -357,8 +363,8 @@ endif()
357363
# Packaging Configuration
358364
# -----------------------------------------------------------------------------
359365

360-
# Setup CPack for package generation (if function exists)
361-
if(COMMAND atom_setup_cpack)
366+
# Setup CPack for package generation when explicitly enabled
367+
if(ATOM_ENABLE_PACKAGING AND COMMAND atom_setup_cpack)
362368
atom_setup_cpack()
363369
endif()
364370

CMakePresets.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,12 @@
8383
"name": "base-msys2",
8484
"hidden": true,
8585
"inherits": "base-mingw",
86+
"binaryDir": "${sourceDir}/build-mingw64",
8687
"cacheVariables": {
87-
"USE_VCPKG": "OFF"
88+
"USE_VCPKG": "OFF",
89+
"OPENSSL_ROOT_DIR": "D:/msys64/mingw64",
90+
"ZLIB_ROOT": "D:/msys64/mingw64",
91+
"CMAKE_PREFIX_PATH": "D:/msys64/mingw64"
8892
},
8993
"condition": {
9094
"type": "matches",
@@ -96,6 +100,7 @@
96100
"name": "base-msys2-vcpkg",
97101
"hidden": true,
98102
"inherits": "base-mingw",
103+
"binaryDir": "${sourceDir}/build-mingw64",
99104
"toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
100105
"cacheVariables": {
101106
"USE_VCPKG": "ON",

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ cmake --build --preset release -j
8181
ctest --preset default --output-on-failure
8282
```
8383

84+
#### Windows (MSYS2 MinGW64)
85+
86+
For a native GCC/MinGW64 build on Windows using MSYS2, see BUILD_MINGW64.md for step-by-step setup and the dedicated presets (`*-msys2`).
87+
8488
#### Using CMake Directly
8589

8690
```bash

atom/components/core/component.cpp

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ Description: Basic Component Definition
2121
#include <cassert>
2222
#include <chrono>
2323

24+
#include <stdexcept>
25+
2426
Component::Component(std::string name) : m_name_(std::move(name)) {
2527
if (m_name_.empty()) {
2628
throw std::invalid_argument("Component name cannot be empty");
29+
} else {
30+
spdlog::info("Component created: {}", m_name_);
2731
}
28-
spdlog::info("Component created: {}", m_name_);
2932
setState(ComponentState::Created);
3033
}
3134

@@ -38,21 +41,24 @@ auto Component::initialize() -> bool {
3841

3942
setState(ComponentState::Initializing);
4043

41-
if (initFunc) {
42-
try {
43-
initFunc(*this);
44-
spdlog::info("Successfully ran initialization function for: {}",
45-
m_name_);
46-
} catch (const std::exception& e) {
47-
spdlog::error("Error during initialization of {}: {}", m_name_,
48-
e.what());
49-
setState(ComponentState::Error);
50-
return false;
51-
} catch (...) {
52-
spdlog::error("Unknown error during initialization of {}", m_name_);
53-
setState(ComponentState::Error);
54-
return false;
55-
}
44+
if (!initFunc) {
45+
spdlog::warn("No initialization function set for: {}", m_name_);
46+
return false;
47+
}
48+
49+
try {
50+
initFunc(*this);
51+
spdlog::info("Successfully ran initialization function for: {}",
52+
m_name_);
53+
} catch (const std::exception& e) {
54+
spdlog::error("Error during initialization of {}: {}", m_name_,
55+
e.what());
56+
setState(ComponentState::Error);
57+
return false;
58+
} catch (...) {
59+
spdlog::error("Unknown error during initialization of {}", m_name_);
60+
setState(ComponentState::Error);
61+
return false;
5662
}
5763

5864
setState(ComponentState::Active);
@@ -69,6 +75,11 @@ auto Component::destroy() -> bool {
6975

7076
setState(ComponentState::Destroying);
7177

78+
if (!cleanupFunc) {
79+
spdlog::warn("No cleanup function set for: {}", m_name_);
80+
return false;
81+
}
82+
7283
if (cleanupFunc) {
7384
try {
7485
cleanupFunc();
@@ -363,9 +374,7 @@ void Component::addOtherComponent(std::string_view name,
363374
}
364375

365376
if (component.expired()) {
366-
spdlog::error("Cannot add expired component: {}", name);
367-
throw std::invalid_argument(
368-
std::string("Cannot add expired component: ") + std::string(name));
377+
spdlog::warn("Adding expired component '{}'", name);
369378
}
370379

371380
std::string nameStr(name);
@@ -437,19 +446,7 @@ auto Component::getOtherComponent(std::string_view name)
437446
if (it != m_OtherComponents_.end()) {
438447
if (it->second.expired()) {
439448
spdlog::warn("Component '{}' has expired", name);
440-
441-
// Release shared lock and acquire unique lock to modify container
442-
lock.unlock();
443-
std::unique_lock<std::shared_mutex> uniqueLock(m_ComponentsMutex_);
444-
445-
// Check if the entry still exists and is expired while we acquired
446-
// the unique lock
447-
it = m_OtherComponents_.find(nameStr);
448-
if (it != m_OtherComponents_.end() && it->second.expired()) {
449-
m_OtherComponents_.erase(it);
450-
}
451-
452-
THROW_OBJECT_EXPIRED("Component '{}' has expired", nameStr);
449+
return it->second;
453450
}
454451
return it->second;
455452
}

atom/components/core/component.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,11 @@ class alignas(64) Component : public std::enable_shared_from_this<Component> {
431431
template <typename T>
432432
[[nodiscard]] auto getVariable(std::string_view name)
433433
-> std::shared_ptr<Trackable<T>> {
434-
return m_VariableManager_->getVariable<T>(std::string(name));
434+
try {
435+
return m_VariableManager_->getVariable<T>(std::string(name));
436+
} catch (const atom::error::ObjectNotExist&) {
437+
return nullptr;
438+
}
435439
}
436440

437441
/**

atom/components/core/component_pool.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ class ComponentPool {
167167
* @brief Deallocates a component (returns to pool)
168168
* @param component Component to deallocate
169169
*/
170-
void deallocate(std::shared_ptr<T> component);
170+
void deallocate(std::shared_ptr<T>& component);
171+
172+
void deallocate(std::nullptr_t) {}
171173

172174
/**
173175
* @brief Gets current pool statistics
@@ -467,7 +469,7 @@ std::shared_ptr<T> ComponentPool<T>::allocate(Args&&... args) {
467469
targetChunk->lastAccess = std::chrono::steady_clock::now();
468470

469471
// Get memory location
470-
void* memory = &targetChunk->storage[slotIndex];
472+
void* memory = static_cast<void*>(targetChunk->getSlotPtr(slotIndex));
471473

472474
lock.unlock();
473475

@@ -599,7 +601,7 @@ ComponentPool<T>::~ComponentPool() {
599601
}
600602

601603
template <typename T>
602-
void ComponentPool<T>::deallocate(std::shared_ptr<T> component) {
604+
void ComponentPool<T>::deallocate(std::shared_ptr<T>& component) {
603605
// The actual deallocation is handled by the custom deleter in allocate()
604606
component.reset();
605607
}

0 commit comments

Comments
 (0)