Windows Platform¶
Complete guide to building C++ libraries for Windows with CCGO.
Overview¶
CCGO provides comprehensive Windows support with:
- Multiple toolchains: MSVC (Visual Studio) and MinGW (GCC)
- Multiple architectures: x86, x64, ARM64
- Output formats: Static libraries (.lib), Dynamic libraries (.dll)
- Build methods: Local (Visual Studio/MinGW) or Docker (cross-platform)
- IDE support: Visual Studio project generation
- Subsystems: Console and Windows subsystems
- Runtime libraries: Static and dynamic CRT linking
Prerequisites¶
Option 1: Local Build (Windows Required)¶
For MSVC: - Windows 10+ (64-bit) - Visual Studio 2019+ with C++ workload - CMake 3.20+
Installation:
# Install Visual Studio from visualstudio.microsoft.com
# Select "Desktop development with C++" workload
# Install CMake
# Download from cmake.org or use chocolatey
choco install cmake
# Verify installation
cmake --version
cl.exe
For MinGW: - Windows 10+ (64-bit) - MinGW-w64 or MSYS2 - CMake 3.20+
Installation:
# Install MSYS2 from msys2.org
# Then install MinGW-w64
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake
# Add to PATH
# C:\msys64\mingw64\bin
# Verify
gcc --version
g++ --version
Option 2: Docker Build (Any OS)¶
Build Windows libraries on Linux or macOS using Docker with MinGW.
Required: - Docker Desktop installed and running - 5GB+ disk space for Docker image
Advantages: - Build on any operating system - No Windows license required - Consistent build environment - MinGW-w64 cross-compilation
Limitations: - MinGW only (no MSVC) - Cannot run/test Windows apps - Larger initial download (~1.2GB image)
See Docker Builds section for details.
Quick Start¶
Basic Build¶
# Build for x64 with default toolchain
ccgo build windows
# Build with Docker (MinGW cross-compile)
ccgo build windows --docker
# Specify toolchain
ccgo build windows --toolchain msvc # MSVC (Windows only)
ccgo build windows --toolchain mingw # MinGW
ccgo build windows --toolchain auto # Both toolchains (default)
# Specify architecture
ccgo build windows --arch x86 # 32-bit
ccgo build windows --arch x64 # 64-bit (default)
ccgo build windows --arch arm64 # ARM64
# Build types
ccgo build windows --build-type debug # Debug build
ccgo build windows --build-type release # Release build (default)
# Link types
ccgo build windows --build-as static # Static library only
ccgo build windows --build-as shared # DLL only
ccgo build windows --build-as both # Both types (default)
Generate Visual Studio Project¶
# Generate Visual Studio solution
ccgo build windows --ide-project
# Open in Visual Studio
start cmake_build/windows/msvc/MyLib.sln
Output Structure¶
Default Output (target/windows/)¶
target/windows/
├── MyLib_Windows_SDK-1.0.0.zip # Main package
│ ├── lib/
│ │ ├── static/
│ │ │ ├── msvc/
│ │ │ │ └── mylib.lib # MSVC static library
│ │ │ └── mingw/
│ │ │ └── libmylib.a # MinGW static library
│ │ └── shared/
│ │ ├── msvc/
│ │ │ ├── mylib.dll # MSVC DLL
│ │ │ └── mylib.lib # Import library
│ │ └── mingw/
│ │ ├── libmylib.dll # MinGW DLL
│ │ └── libmylib.dll.a # Import library
│ ├── bin/ # DLLs (for runtime)
│ │ ├── msvc/
│ │ │ └── mylib.dll
│ │ └── mingw/
│ │ └── libmylib.dll
│ ├── include/
│ │ └── mylib/ # Header files
│ │ ├── mylib.h
│ │ └── version.h
│ └── build_info.json # Build metadata
│
└── MyLib_Windows_SDK-1.0.0-SYMBOLS.zip # Debug symbols
└── symbols/
├── msvc/
│ └── mylib.pdb # MSVC debug symbols
└── mingw/
└── libmylib.dll.debug # MinGW debug symbols
Library Types¶
Static library:
- MSVC: .lib file
- MinGW: .a file
- Linked at compile time
- Larger executable
- No runtime dependencies
Dynamic library (DLL):
- MSVC: .dll + .lib (import library)
- MinGW: .dll + .dll.a (import library)
- Loaded at runtime
- Smaller executable
- Requires DLL at runtime
Build Metadata¶
build_info.json contains:
{
"project": {
"name": "MyLib",
"version": "1.0.0",
"description": "My Windows library"
},
"build": {
"platform": "windows",
"architectures": ["x64"],
"toolchains": ["msvc", "mingw"],
"build_type": "release",
"link_types": ["static", "shared"],
"timestamp": "2024-01-15T10:30:00Z",
"ccgo_version": "0.1.0",
"msvc_version": "19.38",
"mingw_version": "13.2.0"
},
"outputs": {
"libraries": {
"msvc": {
"static": "lib/static/msvc/mylib.lib",
"shared": "lib/shared/msvc/mylib.dll"
},
"mingw": {
"static": "lib/static/mingw/libmylib.a",
"shared": "lib/shared/mingw/libmylib.dll"
}
},
"headers": "include/mylib/",
"symbols": {
"msvc": "symbols/msvc/mylib.pdb",
"mingw": "symbols/mingw/libmylib.dll.debug"
}
}
}
MSVC vs MinGW¶
MSVC (Microsoft Visual C++)¶
Pros: - Official Microsoft compiler - Best Windows integration - Excellent debugging with Visual Studio - Better optimization for Windows - Compatible with Windows SDK
Cons: - Windows-only - Requires Visual Studio installation - Larger toolchain
When to use: - Windows-specific development - Need Visual Studio integration - Maximum Windows performance - Using Windows SDK APIs
MinGW (Minimalist GNU for Windows)¶
Pros: - GCC-based (cross-platform compatible) - Can cross-compile from Linux/macOS - Smaller toolchain - Open source - Compatible with Unix tools
Cons: - Some Windows APIs not fully supported - Potentially slower than MSVC - Less Windows-specific optimization
When to use: - Cross-platform development - Building on non-Windows systems - Want GCC compatibility - Don't need advanced Windows APIs
Using Libraries in C++¶
Linking Static Library¶
CMakeLists.txt (MSVC):
# Find library
find_library(MYLIB_LIBRARY
NAMES mylib
PATHS "path/to/lib/static/msvc"
)
# Link to target
target_link_libraries(myapp PRIVATE ${MYLIB_LIBRARY})
target_include_directories(myapp PRIVATE "path/to/include")
CMakeLists.txt (MinGW):
find_library(MYLIB_LIBRARY
NAMES mylib libmylib.a
PATHS "path/to/lib/static/mingw"
)
target_link_libraries(myapp PRIVATE ${MYLIB_LIBRARY})
target_include_directories(myapp PRIVATE "path/to/include")
Linking Dynamic Library¶
CMakeLists.txt:
# Link import library
target_link_libraries(myapp PRIVATE "path/to/lib/shared/msvc/mylib.lib")
# Copy DLL to output directory
add_custom_command(TARGET myapp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"path/to/bin/msvc/mylib.dll"
$<TARGET_FILE_DIR:myapp>
)
Using in code:
#include <mylib/mylib.h>
int main() {
// DLL functions are automatically resolved
mylib::MyClass obj;
obj.do_work();
return 0;
}
Docker Builds¶
Build Windows libraries on any OS using Docker with MinGW:
Prerequisites¶
# Install Docker Desktop
# Download from: https://www.docker.com/products/docker-desktop/
# Verify Docker is running
docker ps
Build with Docker¶
# First build downloads prebuilt image (~1.2GB)
ccgo build windows --docker
# Subsequent builds are fast
ccgo build windows --docker --arch x64
# All standard options work (MinGW only)
ccgo build windows --docker --build-as static
How It Works¶
- CCGO uses prebuilt
ccgo-builder-windowsimage from Docker Hub - Project directory mounted into container
- Build runs with MinGW-w64 cross-compiler
- Output written to host filesystem
Limitations¶
- MinGW only: Cannot build with MSVC in Docker
- Cannot run: No Windows runtime in Docker
- Cannot test: Cannot execute Windows binaries
Platform Configuration¶
CCGO.toml Settings¶
[package]
name = "mylib"
version = "1.0.0"
[library]
type = "both" # static, shared, or both
[build]
cpp_standard = "17" # C++ standard
[windows]
subsystem = "console" # console or windows
runtime_library = "MD" # MT, MD, MTd, MDd (MSVC only)
windows_sdk_version = "10.0" # Windows SDK version
CMake Variables¶
When building for Windows:
${PLATFORM} # "windows"
${ARCHITECTURE} # "x86", "x64", or "arm64"
${BUILD_TYPE} # "Debug" or "Release"
${LINK_TYPE} # "static", "shared", or "both"
${TOOLCHAIN} # "msvc" or "mingw"
${WINDOWS_SUBSYSTEM} # "console" or "windows"
${MSVC_RUNTIME_LIBRARY} # "MD", "MT", etc. (MSVC only)
Conditional Compilation¶
// Platform detection
#ifdef _WIN32
// Windows-specific code
#include <windows.h>
#ifdef _WIN64
// 64-bit Windows
#else
// 32-bit Windows
#endif
#endif
// Compiler detection
#ifdef _MSC_VER
// MSVC-specific code
#pragma warning(disable: 4996)
#elif defined(__MINGW32__) || defined(__MINGW64__)
// MinGW-specific code
#endif
// DLL export/import
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
// Usage
class MYLIB_API MyClass {
public:
void do_work();
};
Best Practices¶
1. Support Both Toolchains¶
Build with both MSVC and MinGW:
2. Use Proper DLL Export¶
Always use __declspec(dllexport/dllimport):
// mylib_export.h
#ifdef _WIN32
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#define MYLIB_API
#endif
3. Handle Runtime Libraries¶
Choose correct CRT linking:
[windows]
runtime_library = "MD" # Dynamic CRT (recommended)
# runtime_library = "MT" # Static CRT (larger, no dependencies)
4. Include DLLs in Distribution¶
Always include DLLs with your binaries:
distribution/
├── myapp.exe
├── mylib.dll # Your DLL
└── vcruntime140.dll # MSVC runtime (if needed)
5. Test on Target Windows¶
Always test on actual Windows systems: - Different Windows versions (10, 11) - Different architectures (x86, x64) - With and without Visual Studio installed
Troubleshooting¶
MSVC Not Found¶
Solution:
# Install Visual Studio with C++ workload
# Or install Build Tools
# Verify
where cl.exe
# Add to PATH if needed
$env:PATH += ";C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64"
MinGW Not Found¶
Solution:
# Install MSYS2/MinGW
# Add to PATH
export PATH="/c/msys64/mingw64/bin:$PATH"
# Verify
gcc --version
g++ --version
DLL Not Found¶
Solutions:
- Copy DLL to executable directory
-
Add DLL directory to PATH:
-
Use delayed loading (MSVC):
Symbol Not Found¶
Solutions:
-
Check DLL exports:
-
Verify __declspec(dllexport):
-
Use .def file for exports:
Performance Tips¶
1. Use Link-Time Optimization¶
2. Enable Optimizations¶
3. Static CRT for Standalone¶
For deployment without Visual C++ redistributable:
Migration Guides¶
From Visual Studio Project¶
Before:
After:
-
Create CCGO project:
-
Copy source files to
src/ -
Configure CCGO.toml:
-
Build:
From CMake¶
CMakeLists.txt:
CCGO.toml:
Then: ccgo build windows