Skip to content

Commit 93e911d

Browse files
committed
feat: refactor configuration and installer classes for improved readability and consistency
- Updated namespace formatting for consistency across config and environment files. - Enhanced readability by adjusting indentation and spacing in `config_manager.h` and `software_installer2.cpp`.
1 parent 325cfff commit 93e911d

File tree

12 files changed

+1881
-1499
lines changed

12 files changed

+1881
-1499
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Build directories and artifacts
22
/src/build/
33
**/build/
4+
**/build-mingw/
45
**/Debug/
56
**/Release/
67
**/x64/

AGENTS.md

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
# AGENTS.md - Developer Guide for AI Coding Agents
2+
3+
This document provides essential guidelines for AI coding agents working on the Parallax Windows CLI codebase.
4+
5+
## Project Overview
6+
7+
Parallax Windows CLI is a Windows development environment configuration tool written in modern C++ (C++17). It provides automated detection and installation of WSL2, CUDA toolkit, and development tools through an NSIS-built installer. The project uses CMake as its build system and follows modern C++ design patterns including CRTP, Template Method, and Command patterns.
8+
9+
**Platform:** Windows 10 Version 2004+ / Windows 11
10+
**Architecture:** x86_64
11+
**Language:** C++17
12+
**Build System:** CMake 3.6+
13+
**Compiler:** MSVC (Visual Studio)
14+
15+
## Build Commands
16+
17+
### Building on Windows (Primary Method)
18+
19+
```bash
20+
# From the repository root
21+
cd src/parallax
22+
cmake -B build -S . -G "Visual Studio 17 2022" -A x64
23+
cmake --build build --config Release
24+
25+
# Or use Visual Studio directly after generating project files
26+
```
27+
28+
### Build Output
29+
30+
- Binary location: `src/parallax/build/x64/Release/parallax.exe`
31+
- Log file: `parallax.log` (created in the same directory as the executable)
32+
33+
### Building on Mac/Linux (Docker Cross-Compilation)
34+
35+
**Note:** This is for development/testing only. Production builds should use MSVC on Windows.
36+
37+
```bash
38+
# From the project root
39+
cd docker
40+
./build.sh
41+
42+
# Output: src/parallax/build-mingw/parallax.exe
43+
```
44+
45+
See [docker/README.md](docker/README.md) for detailed Docker build instructions.
46+
47+
### Building the Installer
48+
49+
```bash
50+
# From the installer directory (Windows only)
51+
cd installer
52+
.\build-nim.bat
53+
# Output: installer/Output/Parallax_Setup.exe
54+
```
55+
56+
### Common Build Issues
57+
58+
- Ensure MSVC toolchain is installed and in PATH (Windows builds)
59+
- For Docker builds, ensure Docker is installed and running
60+
- Unicode definitions are automatically set: `-DUNICODE -D_UNICODE`
61+
- Windows SDK minimum version: Windows 10 SDK (0x0601)
62+
63+
## Testing
64+
65+
**Note:** This project currently has no automated test suite. Testing is done manually through:
66+
67+
```bash
68+
# Run environment check
69+
parallax.exe check
70+
71+
# Run with help to verify commands
72+
parallax.exe --help
73+
parallax.exe config --help
74+
parallax.exe install --help
75+
```
76+
77+
When adding new features, manually test all affected commands with various argument combinations.
78+
79+
## Code Style Guidelines
80+
81+
### File Organization
82+
83+
```
84+
src/parallax/
85+
├── main.cpp # Entry point
86+
├── cli/ # Command-line interface
87+
│ ├── command_parser.* # Command parsing and routing
88+
│ └── commands/ # Individual command implementations
89+
├── config/ # Configuration management
90+
├── environment/ # Environment installation components
91+
├── utils/ # Utility functions
92+
└── tinylog/ # Logging system
93+
```
94+
95+
### Naming Conventions
96+
97+
- **Classes:** PascalCase (e.g., `ConfigManager`, `BaseCommand`)
98+
- **Functions/Methods:** PascalCase (e.g., `GetInstance()`, `Execute()`)
99+
- **Variables:** snake*case (e.g., `config_path*`, `stdout_output`)
100+
- **Constants:** UPPER_SNAKE_CASE (e.g., `KEY_PROXY_URL`, `DEFAULT_CONFIG_PATH`)
101+
- **Namespaces:** lowercase (e.g., `parallax`, `config`, `utils`, `commands`)
102+
- **Private members:** Suffix with underscore (e.g., `config_values_`, `mutex_`)
103+
104+
### Header Files
105+
106+
- Always use `#pragma once` for header guards
107+
- Include order:
108+
1. Corresponding header (for .cpp files)
109+
2. Standard library headers (`<iostream>`, `<string>`, etc.)
110+
3. Windows API headers (`<windows.h>`)
111+
4. Project headers (relative paths with quotes)
112+
113+
Example:
114+
115+
```cpp
116+
#include "config_manager.h" // Corresponding header
117+
#include <fstream> // Standard library
118+
#include <string>
119+
#include <windows.h> // Windows API
120+
#include "../tinylog/tinylog.h" // Project headers
121+
#include "../utils/utils.h"
122+
```
123+
124+
### Includes in Headers
125+
126+
Minimize includes in headers. Use forward declarations when possible:
127+
128+
```cpp
129+
// In header:
130+
namespace parallax { namespace config { class ConfigManager; } }
131+
132+
// In implementation:
133+
#include "config/config_manager.h"
134+
```
135+
136+
### Namespaces
137+
138+
All code must be within the `parallax` namespace with appropriate sub-namespaces:
139+
140+
```cpp
141+
namespace parallax {
142+
namespace commands {
143+
144+
// Code here
145+
146+
} // namespace commands
147+
} // namespace parallax
148+
```
149+
150+
### Class Design Patterns
151+
152+
#### CRTP (Curiously Recurring Template Pattern)
153+
154+
Used for compile-time polymorphism with zero runtime overhead:
155+
156+
```cpp
157+
template <typename Derived>
158+
class BaseCommand : public ICommand {
159+
public:
160+
CommandResult Execute(const std::vector<std::string>& args) override final {
161+
// ...
162+
return static_cast<Derived*>(this)->ExecuteImpl(context);
163+
}
164+
};
165+
166+
class CheckCommand : public AdminCommand<CheckCommand> {
167+
CommandResult ExecuteImpl(const CommandContext& context) {
168+
// Implementation
169+
}
170+
};
171+
```
172+
173+
#### Template Method Pattern
174+
175+
Define execution flow in base class, specific implementation in derived:
176+
177+
```cpp
178+
// Base class defines the template:
179+
// 1. ValidateArgs → 2. PrepareEnvironment → 3. ExecuteImpl
180+
181+
// Derived classes override:
182+
CommandResult ValidateArgsImpl(CommandContext& context) override;
183+
CommandResult ExecuteImpl(const CommandContext& context) override;
184+
void ShowHelpImpl() override;
185+
```
186+
187+
### Error Handling
188+
189+
- Use exceptions sparingly; prefer return codes (`CommandResult` enum)
190+
- Always log errors with `error_log()` before returning error codes
191+
- Check return values from Windows API calls
192+
- Provide user-friendly error messages to console via `ShowError()`
193+
194+
```cpp
195+
if (!result) {
196+
error_log("Failed to execute command: %s", error_msg.c_str());
197+
ShowError("Command execution failed. Check logs for details.");
198+
return CommandResult::ExecutionError;
199+
}
200+
```
201+
202+
### Logging
203+
204+
Use the tinylog system for all logging:
205+
206+
```cpp
207+
#include "tinylog/tinylog.h"
208+
209+
debug_log("Debug information: %s", debug_info.c_str());
210+
info_log("Operation started: %s", operation.c_str());
211+
warn_log("Warning: %s", warning_msg.c_str());
212+
error_log("Error occurred: %s", error_msg.c_str());
213+
crit_log("Critical failure: %s", critical_msg.c_str());
214+
```
215+
216+
Log levels:
217+
218+
- `debug_log`: Verbose debugging information
219+
- `info_log`: General information about program execution
220+
- `warn_log`: Warning messages that don't prevent execution
221+
- `error_log`: Error conditions that affect functionality
222+
- `crit_log`: Critical failures requiring immediate attention
223+
224+
### Comments and Documentation
225+
226+
- Use `/** ... */` for public API documentation
227+
- Use `//` for inline comments
228+
- Document complex algorithms and non-obvious code
229+
- Include parameter descriptions for non-trivial functions
230+
231+
```cpp
232+
/**
233+
* @brief Execute command line and get output result (synchronous version)
234+
*
235+
* @param cmd Command to execute
236+
* @param timeout Timeout in seconds
237+
* @param stdout_output Standard output content
238+
* @param stderr_output Standard error output content
239+
* @return Command execution return code, <0 indicates execution failure
240+
*/
241+
int ExecCommandEx(const std::string& cmd, int timeout,
242+
std::string& stdout_output, std::string& stderr_output);
243+
```
244+
245+
### Memory Management
246+
247+
- Prefer stack allocation over heap when possible
248+
- Use smart pointers (`std::unique_ptr`, `std::shared_ptr`) for dynamic allocation
249+
- Avoid raw `new`/`delete`
250+
- Use RAII for resource management
251+
252+
### String Handling
253+
254+
Be mindful of Windows encoding issues:
255+
256+
```cpp
257+
// Use utility functions for encoding conversion
258+
std::string utf8_str = UnicodeToUtf8(wide_str);
259+
std::wstring wide_str = Utf8ToUnicode(utf8_str);
260+
261+
// PowerShell output requires special handling
262+
std::string converted = ConvertPowerShellOutputToUtf8(raw_output);
263+
```
264+
265+
### Constants and Configuration
266+
267+
- Define configuration keys as constants in `config_manager.h`:
268+
```cpp
269+
extern const std::string KEY_PROXY_URL;
270+
```
271+
- Initialize in `config_manager.cpp`:
272+
```cpp
273+
const std::string KEY_PROXY_URL = "proxy_url";
274+
```
275+
276+
## Adding New Commands
277+
278+
To add a new command:
279+
280+
1. Create header/source files in `src/parallax/cli/commands/`
281+
2. Inherit from appropriate base class (`BaseCommand`, `AdminCommand`, `WSLCommand`)
282+
3. Implement required methods: `ValidateArgsImpl()`, `ExecuteImpl()`, `ShowHelpImpl()`
283+
4. Register command in `command_parser.cpp`
284+
5. Add files to `CMakeLists.txt` in appropriate group
285+
6. Update README.md with command documentation
286+
287+
## Common Pitfalls
288+
289+
- **Encoding Issues:** Always convert PowerShell/WSL output using utility functions
290+
- **Administrator Privileges:** Use `IsAdmin()` check for operations requiring elevation
291+
- **WSL Integration:** Use `BuildWSLCommand()` helpers for proper WSL command construction
292+
- **Thread Safety:** Use `std::lock_guard` for shared resources (e.g., ConfigManager)
293+
- **Resource Cleanup:** Ensure proper cleanup in destructors and error paths
294+
- **Unicode:** All strings should be UTF-8 internally; convert at boundaries
295+
296+
## Useful Utilities
297+
298+
```cpp
299+
// Path operations
300+
std::string exe_dir = parallax::utils::GetAppBinDir();
301+
std::string path = parallax::utils::JoinPath(dir, filename);
302+
303+
// Admin check
304+
bool is_admin = parallax::utils::IsAdmin();
305+
306+
// Process execution
307+
int result = parallax::utils::ExecCommandEx(cmd, timeout, stdout_out, stderr_out);
308+
309+
// Configuration access
310+
auto& config = parallax::config::ConfigManager::GetInstance();
311+
std::string value = config.GetConfigValue(KEY_PROXY_URL);
312+
```
313+
314+
## Project Structure Notes
315+
316+
- CMake files in `common_make/` define compilation/linking properties
317+
- NSIS installer scripts in `installer/SetupScripts/`
318+
- Split large source files into parts (e.g., `windows_feature_manager.cpp` and `windows_feature_manager2.cpp`)
319+
- Group related functionality using `source_group()` in CMakeLists for Visual Studio organization
320+
321+
## Additional Resources
322+
323+
- README.md: User-facing documentation and feature overview
324+
- CHANGELOG.md: Track all changes following semantic versioning
325+
- LICENSE: Apache 2.0 license

0 commit comments

Comments
 (0)