Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# TheSuperHackers @build JohnsterID 15/09/2025 Add clang-tidy configuration for code quality analysis
---
# Clang-tidy configuration for GeneralsGameCode project
# This configuration is tailored for a legacy C++98/C++20 hybrid codebase
# with Windows-specific code and COM interfaces

# Enable specific checks that are appropriate for this codebase
Checks: >
-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-narrowing-conversions,
-bugprone-signed-char-misuse,
cert-*,
-cert-dcl21-cpp,
-cert-dcl50-cpp,
-cert-dcl58-cpp,
-cert-env33-c,
-cert-err58-cpp,
clang-analyzer-*,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-no-malloc,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-special-member-functions,
google-*,
-google-build-using-namespace,
-google-explicit-constructor,
-google-readability-casting,
-google-readability-todo,
-google-runtime-int,
-google-runtime-references,
hicpp-*,
-hicpp-avoid-c-arrays,
-hicpp-explicit-conversions,
-hicpp-no-array-decay,
-hicpp-signed-bitwise,
-hicpp-special-member-functions,
-hicpp-uppercase-literal-suffix,
-hicpp-use-auto,
-hicpp-vararg,
misc-*,
-misc-const-correctness,
-misc-include-cleaner,
-misc-non-private-member-variables-in-classes,
-misc-use-anonymous-namespace,
modernize-*,
-modernize-avoid-c-arrays,
-modernize-concat-nested-namespaces,
-modernize-loop-convert,
-modernize-pass-by-value,
-modernize-raw-string-literal,
-modernize-return-braced-init-list,
-modernize-use-auto,
-modernize-use-default-member-init,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
performance-*,
-performance-avoid-endl,
portability-*,
readability-*,
-readability-avoid-const-params-in-decls,
-readability-braces-around-statements,
-readability-convert-member-functions-to-static,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-named-parameter,
-readability-redundant-access-specifiers,
-readability-uppercase-literal-suffix

# Treat warnings as errors for CI/CD
WarningsAsErrors: false

# Header filter to include project headers
HeaderFilterRegex: '(Core|Generals|GeneralsMD|Dependencies)/.*\.(h|hpp)$'

# Check options for specific rules
CheckOptions:
# Naming conventions - adapted for the existing codebase style
- key: readability-identifier-naming.ClassCase
value: CamelCase
- key: readability-identifier-naming.StructCase
value: CamelCase
- key: readability-identifier-naming.FunctionCase
value: CamelCase
- key: readability-identifier-naming.MethodCase
value: CamelCase
- key: readability-identifier-naming.VariableCase
value: lower_case
- key: readability-identifier-naming.ParameterCase
value: lower_case
- key: readability-identifier-naming.MemberCase
value: lower_case
- key: readability-identifier-naming.MemberPrefix
value: m_
- key: readability-identifier-naming.ConstantCase
value: UPPER_CASE
- key: readability-identifier-naming.EnumConstantCase
value: UPPER_CASE
- key: readability-identifier-naming.MacroDefinitionCase
value: UPPER_CASE

# Performance settings
- key: performance-for-range-copy.WarnOnAllAutoCopies
value: true
- key: performance-unnecessary-value-param.AllowedTypes
value: 'AsciiString;UnicodeString;Utf8String;Utf16String'

# Modernize settings - be conservative for legacy code
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm

# Readability settings
- key: readability-function-size.LineThreshold
value: 150
- key: readability-function-size.StatementThreshold
value: 100
- key: readability-function-size.BranchThreshold
value: 25
- key: readability-function-size.ParameterThreshold
value: 8
- key: readability-function-size.NestingThreshold
value: 6

# Bugprone settings
- key: bugprone-argument-comment.StrictMode
value: false
- key: bugprone-suspicious-string-compare.WarnOnImplicitComparison
value: true
- key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison
value: true

# Google style settings
- key: google-readability-braces-around-statements.ShortStatementLines
value: 2
- key: google-readability-function-size.StatementThreshold
value: 100

# CERT settings
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: false

# Use .clang-format for formatting suggestions
FormatStyle: file

# Exclude certain directories and files
# Note: This is handled by HeaderFilterRegex above, but can be extended
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,11 @@ cmake-build-*/
## Ninja
.ninja_deps
.ninja_log
build.ninja
build.ninja

## Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
119 changes: 117 additions & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Test Replays
# Testing

## Test Replays

The GeneralsReplays folder contains replays and the required maps that are tested in CI to ensure that the game is retail compatible.

Expand All @@ -11,4 +13,117 @@ START /B /W generalszh.exe -jobs 4 -headless -replay subfolder/*.rep > replay_ch
echo %errorlevel%
PAUSE
```
It will run the game in the background and check that each replay is compatible. You need to use a VC6 build with optimizations and RTS_BUILD_OPTION_DEBUG = OFF, otherwise the game won't be compatible.
It will run the game in the background and check that each replay is compatible. You need to use a VC6 build with optimizations and RTS_BUILD_OPTION_DEBUG = OFF, otherwise the game won't be compatible.

## Code Quality Analysis with clang-tidy

The project includes clang-tidy configuration for static code analysis to help maintain code quality and catch potential bugs.

### Prerequisites

1. **CMake with compile commands export**: The CMake presets already have `CMAKE_EXPORT_COMPILE_COMMANDS=ON` configured.
2. **clang-tidy**: Install clang-tidy for your platform:
- **Linux**: `apt install clang-tidy` or `yum install clang-tools-extra`
- **Windows**: Install LLVM or use the version that comes with Visual Studio
- **macOS**: `brew install llvm` or use Xcode command line tools

### Running clang-tidy

#### Method 1: Using the helper script (Recommended)

The project includes a Python script that simplifies running clang-tidy:

```bash
# Analyze all source files
python3 scripts/run-clang-tidy.py

# Analyze only Core directory
python3 scripts/run-clang-tidy.py --include Core/

# Analyze GeneralsMD but exclude certain patterns
python3 scripts/run-clang-tidy.py --include GeneralsMD/ --exclude test

# Use specific build directory
python3 scripts/run-clang-tidy.py --build-dir build/win32

# Apply fixes automatically (use with caution!)
python3 scripts/run-clang-tidy.py --fix --include Core/Libraries/
```

#### Method 2: Direct clang-tidy usage

First, ensure you have a `compile_commands.json` file:

```bash
# Configure with any preset that exports compile commands
cmake --preset win32 # or vc6, unix, etc.

# Run clang-tidy on specific files
clang-tidy -p build/win32 Core/Libraries/Source/RTS/File.cpp

# Run on multiple files with pattern (Unix/Linux/macOS)
find Core/ -name "*.cpp" | xargs clang-tidy -p build/win32

# Windows Command Prompt alternative
for /r Core\ %i in (*.cpp) do clang-tidy -p build/win32 "%i"

# Windows PowerShell alternative
Get-ChildItem -Path Core\ -Recurse -Filter "*.cpp" | ForEach-Object { clang-tidy -p build/win32 $_.FullName }
```

### Configuration

The `.clang-tidy` file in the project root contains configuration tailored for this legacy C++ codebase:

- **Enabled checks**: Focus on bug-prone patterns, performance issues, and readability
- **Disabled checks**: Overly strict modernization rules that don't fit the legacy codebase
- **Naming conventions**: Adapted to match the existing code style (CamelCase for classes, m_ prefix for members)
- **Header filtering**: Only analyzes project headers, not system/external headers

### Integration with Development Workflow

#### For Contributors

Run clang-tidy on your changes before submitting PRs:

```bash
# Analyze only files you've modified
python3 scripts/run-clang-tidy.py --include "path/to/your/changes/"
```

#### For Maintainers

Consider running periodic full codebase analysis:

```bash
# Full analysis (may take a while)
python3 scripts/run-clang-tidy.py > clang-tidy-report.txt 2>&1
```

### MinGW-w64 Compatibility

The clang-tidy configuration is designed to work with the MinGW-w64 cross-compilation setup. The project supports:

- **MinGW-w64 headers**: For Windows API compatibility
- **ReactOS ATL**: For COM interface support (as referenced in PR #672)
- **Legacy C++98 patterns**: While encouraging modern practices where appropriate

### Troubleshooting

**Issue**: `compile_commands.json not found`
**Solution**: Run cmake configuration first: `cmake --preset <preset-name>`

**Issue**: PCH file not found errors (e.g., `cmake_pch.cxx.pch' not found`)
**Solution**: The script now automatically strips precompiled header flags that are incompatible with clang-tidy. If you still encounter issues, ensure you're using the Python helper script which handles this automatically.

**Issue**: Command line too long on Windows
**Solution**: The script now processes files in batches of 50 to avoid Windows command line length limits. This happens automatically.

**Issue**: clang-tidy reports errors in system headers
**Solution**: The configuration should filter these out, but you can also use `--system-headers=false`

**Issue**: Too many warnings for legacy code
**Solution**: Use the `--include` flag to focus on specific directories or files you're working on

**Issue**: Script fails with relative paths
**Solution**: This has been fixed - the script now properly resolves relative paths. Make sure you're using the latest version.
Loading
Loading