Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Compiler And Toolchain Configuration

techy4shri edited this page Nov 25, 2025 · 1 revision

Compiler & Toolchain Configuration

This document explains how CppLab IDE manages MinGW toolchains and compiler configuration.

Overview

CppLab IDE bundles two complete MinGW toolchains:

Toolchain Bits Purpose Compiler Libraries
mingw32 32-bit Graphics (graphics.h) GCC 8.1.0+ WinBGIm, GDI32
mingw64 64-bit OpenMP, Modern C++ GCC 8.1.0+ libgomp, pthread

Directory Structure

compilers/
├── mingw32/ # 32-bit toolchain
│ ├── bin/
│ │ ├── gcc.exe # C compiler
│ │ ├── g++.exe # C++ compiler
│ │ ├── gdb.exe # Debugger (future)
│ │ └── *.dll # Runtime libraries
│ ├── include/
│ │ ├── graphics.h # WinBGIm header
│ │ ├── winbgim.h
│ │ └── ... # Standard headers
│ ├── lib/
│ │ ├── libbgi.a # WinBGIm library
│ │ ├── libgdi32.a # Windows GDI
│ │ └── ...
│ └── libexec/
│ └── gcc/
│ └── ... # GCC internals
│
└── mingw64/ # 64-bit toolchain
 ├── bin/
 │ ├── gcc.exe
 │ ├── g++.exe
 │ └── ...
 ├── include/
 │ ├── omp.h # OpenMP header
 │ └── ...
 ├── lib/
 │ ├── libgomp.a # OpenMP library
 │ ├── libpthread.a
 │ └── ...
 └── libexec/
 └── ...

Toolchain Discovery

Initialization

File: src/cpplab/core/toolchains.py

def get_toolchains() -> dict:
 """Discover and return available MinGW toolchains."""
 app_root = get_app_root()
 compilers_dir = app_root / "compilers"
 
 toolchains = {}
 
 # Check mingw32
 mingw32_path = compilers_dir / "mingw32"
 if mingw32_path.exists():
 gcc_path = mingw32_path / "bin" / "gcc.exe"
 gpp_path = mingw32_path / "bin" / "g++.exe"
 if gcc_path.exists() and gpp_path.exists():
 toolchains["mingw32"] = Toolchain(
 name="mingw32",
 root=mingw32_path,
 gcc=gcc_path,
 gpp=gpp_path,
 bits=32
 )
 
 # Check mingw64
 mingw64_path = compilers_dir / "mingw64"
 if mingw64_path.exists():
 gcc_path = mingw64_path / "bin" / "gcc.exe"
 gpp_path = mingw64_path / "bin" / "g++.exe"
 if gcc_path.exists() and gpp_path.exists():
 toolchains["mingw64"] = Toolchain(
 name="mingw64",
 root=mingw64_path,
 gcc=gcc_path,
 gpp=gpp_path,
 bits=64
 )
 
 return toolchains

Toolchain Data Structure

@dataclass
class Toolchain:
 name: str # "mingw32" or "mingw64"
 root: Path # C:/path/to/CppLabIDE/compilers/mingw32
 gcc: Path # Path to gcc.exe
 gpp: Path # Path to g++.exe
 bits: int # 32 or 64
 
 def is_available(self) -> bool:
 return self.gcc.exists() and self.gpp.exists()

Toolchain Selection Logic

Decision Tree

┌─────────────────────────────────────┐
│ Project/File Configuration │
└─────────────┬───────────────────────┘
 │
 ↓
 ┌─────────────────┐
 │ graphics=true? │
 └────┬────────────┘
 │
 YES │ NO
 │
 ┌────↓────┐ ┌──────────────┐
 │ mingw32 │ │ openmp=true? │
 └─────────┘ └──────┬───────┘
 │
 YES │ NO
 │
 ┌────↓────┐ ┌──────────┐
 │ mingw64 │ │ mingw64 │
 └─────────┘ └──────────┘
 (default)

Implementation

File: src/cpplab/core/toolchains.py

def select_toolchain(config: ProjectConfig, toolchains: dict) -> Toolchain:
 """Select appropriate toolchain based on project features."""
 
 # User override takes precedence
 if config.toolchain_preference != "auto":
 return toolchains.get(config.toolchain_preference)
 
 # Graphics requires 32-bit
 if config.features.get("graphics", False):
 return toolchains["mingw32"]
 
 # OpenMP prefers 64-bit
 if config.features.get("openmp", False):
 return toolchains["mingw64"]
 
 # Default to 64-bit
 return toolchains["mingw64"]

Why This Logic?

  1. Graphics → 32-bit: WinBGIm library is 32-bit only
  2. OpenMP → 64-bit: Better performance, more memory
  3. Default → 64-bit: Modern systems, better performance

Compiler Configuration

Language Standards

C Standards

C_STANDARDS = {
 "c99": "-std=c99",
 "c11": "-std=c11",
 "c17": "-std=c17",
 "c18": "-std=c18", # Alias for c17
 "c23": "-std=c23", # Experimental
}

C++ Standards

CPP_STANDARDS = {
 "c++11": "-std=c++11",
 "c++14": "-std=c++14",
 "c++17": "-std=c++17",
 "c++20": "-std=c++20",
 "c++23": "-std=c++23", # Experimental
}

Compiler Flags

Base Flags (Always Included)

-Wall # Enable all warnings
-Wextra # Extra warnings
-o <output_file> # Output file

Optional Flags

Graphics.h Projects (32-bit):

-lbgi # WinBGIm library
-lgdi32 # Windows GDI
-lcomdlg32 # Windows dialogs
-luuid # Windows UUID
-lole32 # Windows OLE
-loleaut32 # Windows OLE Automation

OpenMP Projects (64-bit):

-fopenmp # Enable OpenMP

Debug Mode (future):

-g # Include debug symbols
-O0 # No optimization

Release Mode (future):

-O2 # Optimize for speed
-DNDEBUG # Disable assertions

Build Command Construction

Example: Graphics Project

Input:

ProjectConfig(
 name="CircleDemo",
 language="cpp",
 standard="c++17",
 features={"graphics": True, "openmp": False},
 files=["src/main.cpp"],
 main_file="src/main.cpp"
)

Output Command:

C:/CppLabIDE/compilers/mingw32/bin/g++.exe \
 src/main.cpp \
 -std=c++17 \
 -Wall \
 -Wextra \
 -o build/CircleDemo.exe \
 -lbgi \
 -lgdi32 \
 -lcomdlg32 \
 -luuid \
 -lole32 \
 -loleaut32

Example: OpenMP Project

Input:

ProjectConfig(
 name="ParallelSum",
 language="cpp",
 standard="c++20",
 features={"graphics": False, "openmp": True},
 files=["src/main.cpp"],
 main_file="src/main.cpp"
)

Output Command:

C:/CppLabIDE/compilers/mingw64/bin/g++.exe \
 src/main.cpp \
 -std=c++20 \
 -Wall \
 -Wextra \
 -fopenmp \
 -o build/ParallelSum.exe

Example: Plain Console Project

Input:

ProjectConfig(
 name="HelloWorld",
 language="c",
 standard="c17",
 features={"graphics": False, "openmp": False},
 files=["src/main.c"],
 main_file="src/main.c"
)

Output Command:

C:/CppLabIDE/compilers/mingw64/bin/gcc.exe \
 src/main.c \
 -std=c17 \
 -Wall \
 -Wextra \
 -o build/HelloWorld.exe

Auto-Detection

Feature Detection from Source Code

File: src/cpplab/core/builder.py

def detect_features_from_source(source_path: Path) -> dict:
 """Detect graphics.h and OpenMP usage by scanning source code."""
 features = {"graphics": False, "openmp": False}
 
 try:
 with open(source_path, 'r', encoding='utf-8', errors='ignore') as f:
 content = f.read()
 
 # Check for graphics.h
 if '#include' in content and 'graphics.h' in content:
 features["graphics"] = True
 
 # Check for OpenMP
 if '#pragma' in content and 'omp' in content:
 features["openmp"] = True
 
 except Exception:
 pass
 
 return features

Standalone File Workflow

1. User opens: test.cpp
2. User presses F7 (Build)
3. detect_features_from_source(test.cpp)
 → Scans for #include <graphics.h>
 → Scans for #pragma omp
4. Select toolchain based on features
5. Build with appropriate flags

Toolchain Verification

Startup Check

Location: src/cpplab/app.py_check_toolchains()

def _check_toolchains(self):
 """Check if toolchains are available and show warning if not."""
 self.toolchains = get_toolchains()
 
 mingw32 = self.toolchains.get("mingw32")
 mingw64 = self.toolchains.get("mingw64")
 
 missing = []
 if not mingw32 or not mingw32.is_available():
 missing.append("mingw32 (32-bit, required for graphics.h)")
 if not mingw64 or not mingw64.is_available():
 missing.append("mingw64 (64-bit, required for OpenMP)")
 
 if missing:
 msg = (
 "<h3>Toolchains Not Found</h3>"
 "<p>The following MinGW toolchains are missing:</p>"
 "<ul>"
 )
 for item in missing:
 msg += f"<li>{item}</li>"
 msg += (
 "</ul>"
 "<p>Expected location: <code>compilers/</code> directory</p>"
 "<p>Building will not work until toolchains are installed.</p>"
 )
 QMessageBox.warning(self, "Toolchains Missing", msg)

User Feedback

If toolchains are missing:

┌─────────────────────────────────────────┐
│ ⚠ Toolchains Not Found │
├─────────────────────────────────────────┤
│ The following MinGW toolchains are │
│ missing: │
│ │
│ • mingw32 (32-bit, required for │
│ graphics.h) │
│ • mingw64 (64-bit, required for │
│ OpenMP) │
│ │
│ Expected location: compilers/ directory │
│ │
│ Building will not work until toolchains │
│ are installed. │
└─────────────────────────────────────────┘

Frozen Mode Support

Challenge

  • Development: compilers/ relative to source code
  • Frozen: compilers/ relative to .exe

Solution

def get_app_root() -> Path:
 """Get application root directory (works in dev and frozen modes)."""
 if getattr(sys, 'frozen', False):
 # Running as PyInstaller bundle
 return Path(sys._MEIPASS).parent
 else:
 # Running from source
 return Path(__file__).parent.parent.parent

Usage:

app_root = get_app_root()
# Dev: C:/Users/Dev/CppLabEngine
# Frozen: C:/Program Files/CppLabIDE
compilers_dir = app_root / "compilers"
# Dev: C:/Users/Dev/CppLabEngine/compilers
# Frozen: C:/Program Files/CppLabIDE/compilers

Toolchain UI

Toolbar Combo Box

Location: src/cpplab/app.py_setup_combo_boxes()

self.toolchainComboBox = QComboBox()
self.toolchainComboBox.addItem("Auto", "auto")
self.toolchainComboBox.addItem("64-bit (mingw64)", "mingw64")
self.toolchainComboBox.addItem("32-bit (mingw32)", "mingw32")

Behavior:

  • Auto: Selects based on project features (default)
  • 64-bit: Forces mingw64 (even for graphics - may fail)
  • 32-bit: Forces mingw32 (even for OpenMP - slower)

User Override

Users can override toolchain selection:

def on_toolchain_changed(self, index: int):
 """Handle toolchain combo box selection change."""
 toolchain_map = {0: "auto", 1: "mingw64", 2: "mingw32"}
 value = toolchain_map.get(index, "auto")
 
 if self.current_project:
 self.current_project.toolchain_preference = value
 self.current_project.save() # Persist to JSON
 else:
 self.standalone_toolchain_preference = value

Troubleshooting

Toolchains Not Detected

Symptom: Warning on startup "Toolchains Not Found"

Causes:

  1. Missing compilers/ directory
  2. Missing mingw32/ or mingw64/ subdirectories
  3. Missing bin/gcc.exe or bin/g++.exe

Solution:

  1. Check directory structure matches expected layout
  2. Verify compiler executables exist and are not corrupted
  3. Re-extract toolchains from release package

Build Fails with "No such file or directory"

Symptom: Build error: gcc.exe: error: CreateProcess: No such file or directory

Cause: Toolchain path contains spaces or special characters

Solution: Install CppLabIDE to path without spaces (e.g., C:\CppLabIDE)

Graphics Build Fails on 64-bit

Symptom: Linker error: cannot find -lbgi

Cause: Graphics project trying to use mingw64 (64-bit)

Solution:

  1. Check project configuration: "features": {"graphics": true}
  2. Set toolchain to "Auto" or "32-bit" explicitly
  3. Rebuild project

Performance Considerations

Toolchain Caching

Toolchains discovered once at startup:

# MainWindow.__init__
self.toolchains = get_toolchains() # Cached for session

Benefit: No repeated filesystem checks during builds

Path Resolution

Absolute paths used throughout:

# Bad: Relative path (requires working directory)
cmd = ["gcc", "main.c"]
# Good: Absolute path (works from any directory)
cmd = [str(toolchain.gcc), "main.c"]

Benefit: Builds work regardless of current directory


Next: Language Standards Support
Previous: Asynchronous Build System

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /