Skip to content

Version Management

Complete guide to managing versions in CCGO projects using semantic versioning, git tags, and automated version injection.

Overview

CCGO provides comprehensive version management features:

  • Semantic Versioning - Follow SemVer 2.0.0 specifications
  • Automated Tagging - Create git tags from CCGO.toml version
  • Version Injection - Automatically inject version info into builds
  • Multi-Platform Support - Consistent versioning across all platforms
  • Build Metadata - Include git commit SHA, build timestamp in binaries
  • Release Management - Simplify release workflows

Version Format

Semantic Versioning

CCGO follows Semantic Versioning 2.0.0:

MAJOR.MINOR.PATCH[-PRERELEASE][+BUILDMETADATA]

Components: - MAJOR: Incompatible API changes - MINOR: New backward-compatible functionality - PATCH: Backward-compatible bug fixes - PRERELEASE: Optional pre-release identifier (alpha, beta, rc) - BUILDMETADATA: Optional build metadata (commit SHA, timestamp)

Examples:

1.0.0           # Stable release
1.2.3           # Patch update
2.0.0-alpha.1   # Pre-release
1.5.0+20240115  # With build metadata
2.1.0-rc.2+g8f3a  # Pre-release with git hash

Configuration

CCGO.toml

[package]
name = "mylib"
version = "1.2.3"  # SemVer format
authors = ["Your Name <you@example.com>"]

[version]
# Version injection settings
inject_build_metadata = true  # Include git SHA and timestamp
inject_to_code = true          # Generate version header files
prerelease_suffix = "beta"     # Optional: alpha, beta, rc

# Platform-specific version overrides (optional)
[version.android]
version_code = 10203  # Android integer version (auto-calculated if not set)

[version.ios]
build_number = "123"  # iOS build number (defaults to PATCH)

[version.windows]
file_version = "1.2.3.0"  # Windows 4-part version

Version Auto-Calculation

CCGO automatically calculates platform-specific version numbers:

Android version_code:

version_code = MAJOR * 10000 + MINOR * 100 + PATCH

Example: 1.2.3 → 10203

iOS build number:

build_number = PATCH (default)
Or custom: build_number = "123"

Windows file version:

file_version = MAJOR.MINOR.PATCH.0

Example: 1.2.3 → 1.2.3.0

Creating Version Tags

Using ccgo tag

# Create tag from CCGO.toml version
ccgo tag

# Create tag with custom version
ccgo tag v2.0.0

# Create tag with message
ccgo tag --message "Release version 2.0.0 with new features"

# Create annotated tag
ccgo tag --annotate

# Push tag to remote
ccgo tag --push

Tag Format

# CCGO creates tags in format: v{VERSION}
v1.0.0
v1.2.3-beta.1
v2.0.0

Manual Tagging

# Create lightweight tag
git tag v1.0.0

# Create annotated tag
git tag -a v1.0.0 -m "Release 1.0.0"

# Push tag to remote
git push origin v1.0.0

# Push all tags
git push --tags

Version Injection

Build-Time Injection

CCGO automatically injects version information during builds:

# Version info injected into all builds
ccgo build android

# Disable version injection
ccgo build android --no-version-inject

Generated Version Header

C++ Header (include/<project>/version.h):

#pragma once

#define MYLIB_VERSION "1.2.3"
#define MYLIB_VERSION_MAJOR 1
#define MYLIB_VERSION_MINOR 2
#define MYLIB_VERSION_PATCH 3

#define MYLIB_GIT_SHA "8f3a2b1c"
#define MYLIB_GIT_BRANCH "main"
#define MYLIB_BUILD_TIMESTAMP "2024-01-15T10:30:00Z"
#define MYLIB_BUILD_TYPE "Release"

// Platform-specific
#ifdef __ANDROID__
#define MYLIB_VERSION_CODE 10203
#elif defined(__APPLE__)
#define MYLIB_BUNDLE_VERSION "123"
#elif defined(_WIN32)
#define MYLIB_FILE_VERSION "1.2.3.0"
#endif

namespace mylib {
    const char* get_version();
    const char* get_git_sha();
    const char* get_build_timestamp();
}

Implementation:

// src/version.cpp (auto-generated)
#include "mylib/version.h"

namespace mylib {
    const char* get_version() {
        return MYLIB_VERSION;
    }

    const char* get_git_sha() {
        return MYLIB_GIT_SHA;
    }

    const char* get_build_timestamp() {
        return MYLIB_BUILD_TIMESTAMP;
    }
}

Using Version in Code

#include "mylib/version.h"
#include <iostream>

void print_version() {
    std::cout << "MyLib version: " << mylib::get_version() << "\n";
    std::cout << "Git SHA: " << mylib::get_git_sha() << "\n";
    std::cout << "Built: " << mylib::get_build_timestamp() << "\n";
}

Platform-Specific Versioning

Android

Version Code and Version Name:

[package]
version = "1.2.3"

[version.android]
version_code = 10203       # Integer for Play Store
version_name = "1.2.3"     # Display name (defaults to package.version)

Gradle Integration:

// Generated in build.gradle.kts
android {
    defaultConfig {
        versionCode = 10203
        versionName = "1.2.3"
    }
}

iOS

Bundle Version:

[package]
version = "1.2.3"

[version.ios]
bundle_short_version = "1.2.3"  # CFBundleShortVersionString
build_number = "123"             # CFBundleVersion

Info.plist:

<key>CFBundleShortVersionString</key>
<string>1.2.3</string>
<key>CFBundleVersion</key>
<string>123</string>

OpenHarmony

HAR Version:

[package]
version = "1.2.3"

[version.ohos]
app_version_code = 10203
app_version_name = "1.2.3"

module.json5:

{
  "module": {
    "versionCode": 10203,
    "versionName": "1.2.3"
  }
}

Windows

File Version:

[package]
version = "1.2.3"

[version.windows]
file_version = "1.2.3.0"        # Four-part version
product_version = "1.2"          # Display version
company_name = "Your Company"
copyright = "Copyright © 2024"

Resource File (.rc):

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,3,0
PRODUCTVERSION 1,2,0,0
{
    VALUE "FileVersion", "1.2.3.0"
    VALUE "ProductVersion", "1.2"
    VALUE "CompanyName", "Your Company"
    VALUE "LegalCopyright", "Copyright © 2024"
}

Pre-Release Versions

Alpha Releases

[package]
version = "2.0.0-alpha.1"

[version]
prerelease_suffix = "alpha"
# Tag alpha release
ccgo tag v2.0.0-alpha.1 --message "Alpha release 1"

Beta Releases

[package]
version = "2.0.0-beta.2"

[version]
prerelease_suffix = "beta"

Release Candidates

[package]
version = "2.0.0-rc.1"

[version]
prerelease_suffix = "rc"

Promotion to Stable

# Promote RC to stable
# 1. Update CCGO.toml
version = "2.0.0"  # Remove -rc.1

# 2. Create stable tag
ccgo tag v2.0.0 --message "Stable release 2.0.0"

Build Metadata

Git Information

CCGO automatically includes: - Commit SHA: Current git commit hash - Branch: Current git branch name - Tag: Closest git tag (if any) - Dirty: Whether working directory has uncommitted changes

Timestamp

// ISO 8601 format
#define MYLIB_BUILD_TIMESTAMP "2024-01-15T10:30:00Z"

Build Type

// Release or Debug
#define MYLIB_BUILD_TYPE "Release"

Custom Metadata

[version]
custom_metadata = [
    "jenkins_build_123",
    "ci_pipeline_456"
]

Version Queries

Check Current Version

# Show version from CCGO.toml
ccgo --version

# Show detailed version info
ccgo version --detailed

# Output:
# CCGO version: 3.0.10
# Project: mylib
# Version: 1.2.3
# Git SHA: 8f3a2b1c
# Git branch: main
# Modified: no

Runtime Version Query

// In your application
#include "mylib/mylib.h"

const char* version = mylib::get_version();
printf("Library version: %s\n", version);

Versioning Workflows

Development Workflow

# 1. Start new feature
git checkout -b feature/new-api
# CCGO.toml: version = "1.2.0"

# 2. Develop and test
ccgo build --all
ccgo test

# 3. Merge to main
git checkout main
git merge feature/new-api

# 4. Bump version
# Update CCGO.toml: version = "1.3.0"

# 5. Create tag
ccgo tag v1.3.0 --message "Add new API"

# 6. Push
git push origin main --tags

Release Workflow

# 1. Create release branch
git checkout -b release/2.0
# CCGO.toml: version = "2.0.0-rc.1"

# 2. Test release candidate
ccgo build --all
ccgo test --all

# 3. Fix bugs if needed
# ... bug fixes ...

# 4. Promote to stable
# Update CCGO.toml: version = "2.0.0"
ccgo tag v2.0.0 --message "Release 2.0.0"

# 5. Merge back to main
git checkout main
git merge release/2.0

# 6. Push
git push origin main --tags

Hotfix Workflow

# 1. Create hotfix branch from tag
git checkout -b hotfix/1.2.4 v1.2.3
# CCGO.toml: version = "1.2.4"

# 2. Fix critical bug
# ... fix ...

# 3. Test
ccgo build --all
ccgo test

# 4. Create tag
ccgo tag v1.2.4 --message "Hotfix: critical bug"

# 5. Merge to main and release branch
git checkout main
git cherry-pick hotfix/1.2.4

git checkout release/1.2
git cherry-pick hotfix/1.2.4

# 6. Push
git push origin main release/1.2 --tags

Changelog Integration

Automatic Changelog Generation

# Generate changelog from git tags
ccgo changelog

# Output to file
ccgo changelog --output CHANGELOG.md

# Between specific versions
ccgo changelog --from v1.0.0 --to v2.0.0

Changelog Format

# Changelog

## [2.0.0] - 2024-01-15

### Added
- New authentication API
- Support for OAuth 2.0

### Changed
- Updated dependency versions
- Improved error handling

### Fixed
- Memory leak in network module
- Crash on invalid input

### Breaking Changes
- Removed deprecated APIs
- Changed function signatures

## [1.2.3] - 2024-01-01

### Fixed
- Critical security vulnerability

Version Constraints

Dependency Versions

[dependencies]
openssl = { version = "^1.1.0" }  # Compatible with 1.1.x
boost = { version = "~1.80.0" }   # Compatible with 1.80.x
zlib = { version = "1.2.11" }     # Exact version

# Version ranges
protobuf = { version = ">=3.0.0, <4.0.0" }

Operators: - ^: Compatible with (same major version) - ~: Approximately compatible (same minor version) - >=, <=, >, <: Comparison operators - ,: AND operator

Platform-Specific Constraints

[dependencies.android]
androidx-core = { version = "1.12.0" }

[dependencies.ios]
alamofire = { version = "~5.8.0" }

Best Practices

1. Version Numbering

  • Start at 1.0.0 for first stable release
  • 0.y.z for initial development (unstable API)
  • Increment MAJOR for breaking changes
  • Increment MINOR for new features
  • Increment PATCH for bug fixes

2. Tag Management

# Always use annotated tags for releases
git tag -a v1.0.0 -m "Release 1.0.0"

# Lightweight tags for internal use only
git tag build-123

# Push tags explicitly
git push origin v1.0.0

3. Version in Commit Messages

# Good commit messages
git commit -m "chore: bump version to 1.2.3"
git commit -m "release: v2.0.0"
git commit -m "hotfix: v1.2.4 - fix critical bug"

4. Pre-Release Testing

# Test all platforms before release
ccgo build --all --release
ccgo test --all

# Verify version info
ccgo version --detailed

5. Documentation

  • Update CHANGELOG.md before each release
  • Document breaking changes clearly
  • Maintain migration guides for major versions

CI/CD Integration

GitHub Actions

name: Release
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Extract version
        id: version
        run: |
          VERSION=${GITHUB_REF#refs/tags/v}
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      - name: Build all platforms
        run: ccgo build --all --release

      - name: Create GitHub Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ steps.version.outputs.version }}
          draft: false
          prerelease: false

GitLab CI

release:
  stage: deploy
  only:
    - tags
  script:
    - ccgo build --all --release
    - ccgo publish --all --registry official
  artifacts:
    paths:
      - target/

Troubleshooting

Version Mismatch

Problem:

Warning: CCGO.toml version (1.2.3) doesn't match git tag (v1.2.2)

Solution:

# Update CCGO.toml to match tag
# Or create new tag matching CCGO.toml
ccgo tag --force

Invalid Version Format

Problem:

Error: Invalid version format: "1.2.3.4.5"

Solution:

# Use SemVer format
version = "1.2.3"  # Not "1.2.3.4.5"

Tag Already Exists

Problem:

Error: tag 'v1.0.0' already exists

Solution:

# Delete old tag (if intentional)
git tag -d v1.0.0
git push origin :refs/tags/v1.0.0

# Create new tag
ccgo tag v1.0.0

Examples

Complete Versioning Setup

# CCGO.toml
[package]
name = "mylib"
version = "1.2.3"
authors = ["Your Name <you@example.com>"]

[version]
inject_build_metadata = true
inject_to_code = true

[version.android]
version_code = 10203

[version.ios]
build_number = "123"

[version.windows]
file_version = "1.2.3.0"
company_name = "Your Company"
copyright = "Copyright © 2024"

Resources

Tools

CCGO Documentation

Community

Next Steps