How to optimize a Harbour application with a GUI library amd MiniGW compiler

126 views
Skip to first unread message

Grigory Filatov

unread,
May 25, 2025, 1:12:30 PM5/25/25
to Harbour Minigui
Hi Friends,

To optimize a Harbour application with a GUI library (e.g., HMG, MiniGUI) using MinGW on Windows, you can leverage Harbour’s build tool (hbmk2) command-line switches and MinGW’s GCC compiler options to optimize for speed, size, and full static linking. Below, I’ll outline the relevant hbmk2 switches and GCC flags, explain their effects, and provide a recommended command for building an optimized Harbour GUI application.

Key Optimization Goals
1. Speed: Maximize runtime performance of the application.
2. Size: Minimize the executable file size.
3. Full Static Linking: Link all dependencies (including Harbour runtime and GUI libraries) into a single executable, eliminating the need for external DLLs.

Relevant hbmk2 Command-Line Switches
Harbour’s hbmk2 build tool passes compiler and linker options to MinGW (GCC). The following switches are relevant for optimization:

- General Build Options:
  - -w3: Enable all warnings to catch potential issues that could affect performance or stability.
  - -km: Keep memory (avoid garbage collection pauses), which can improve runtime performance for GUI apps.
  - -static: Force static linking of Harbour runtime and libraries, ensuring no external DLLs are required (key for full static builds).
  - -mt: Enable multithreaded mode, which can improve performance for GUI applications handling multiple tasks.

- Optimization Flags:
  - -O2: Enable GCC’s level 2 optimization (balanced for speed and size). This is passed to MinGW as -O2.
  - -O3: Enable GCC’s level 3 optimization (maximum speed, potentially larger code size). Use cautiously, as it may increase executable size.
  - -Os: Optimize for size (reduces executable size at the cost of some performance).
  - -flto: Enable Link-Time Optimization (LTO), which optimizes across module boundaries, improving both speed and size (requires -O2 or -O3).

- Static Linking Options:
  - -static: Ensures the Harbour runtime and libraries are statically linked.
  - -ldflag=-static-libgcc: Links the GCC runtime library (libgcc) statically.
  - -ldflag=-static-libstdc++: Links the C++ standard library statically (required if using GUI libraries like wxHarbour that depend on C++).
  - -ldflag=-Wl,--allow-multiple-definition: Resolves potential linking conflicts when statically linking complex GUI libraries.

- GUI-Specific Options:
  - -gui: Suppress console output, ensuring the application runs as a GUI program (no command-line window).
  - -winuni: Use Unicode for Windows APIs, which is standard for modern GUI libraries like HMG or wxHarbour.

- Debugging and Stripping:
  - -strip: Strip debugging symbols from the executable to reduce size.
  - -nodebug: Disable debug information generation, further reducing size.

MinGW (GCC) Flags for Optimization
Since hbmk2 passes flags to MinGW’s GCC, you can include additional GCC optimization flags using the -cflag= and -ldflag= options. Relevant GCC flags include:

- For Speed:
  - -O3: Aggressive optimization for maximum performance.
  - -march=native: Optimize for the host CPU architecture (e.g., enables SSE, AVX instructions).
  - -funroll-loops: Unroll loops for better performance (may increase size).
  - -fomit-frame-pointer: Omit frame pointer to save CPU cycles (safe for most GUI apps).

- For Size:
  - -Os: Optimize for minimal code size.
  - -fdata-sections -ffunction-sections: Place each function/data in its own section, enabling linker to remove unused code.
  - -Wl,--gc-sections: Remove unused sections during linking (requires -fdata-sections -ffunction-sections).

- For Static Linking:
  - -static-libgcc: Statically link the GCC runtime.
  - -static-libstdc++: Statically link the C++ standard library (for GUI libraries like wxHarbour).
  - -static: Ensure all libraries are statically linked.

Recommended Command for Optimized Harbour GUI App
Below is a recommended hbmk2 command for building a Harbour GUI application with MinGW, optimized for speed, size, and full static linking:

hbmk2 myapp.prg -gui -w3 -km -mt -static -O3 -flto -strip -nodebug -cflag=-march=native -cflag=-funroll-loops -cflag=-fomit-frame-pointer -ldflag=-static-libgcc -ldflag=-static-libstdc++ -ldflag=-Wl,--gc-sections -cflag=-fdata-sections -cflag=-ffunction-sections -winuni

Explanation of the Command
- Source File: myapp.prg (replace with your Harbour source file or project).
- GUI Mode: -gui ensures a GUI application with no console window.
- Warnings and Memory: -w3 -km enables warnings and keeps memory for better performance.
- Multithreading: -mt supports GUI apps with concurrent tasks.
- Static Linking: -static -ldflag=-static-libgcc -ldflag=-static-libstdc++ ensures full static linking, embedding all dependencies.
- Speed Optimization: -O3 -flto -cflag=-march=native -cflag=-funroll-loops -cflag=-fomit-frame-pointer maximizes runtime performance.
- Size Optimization: -strip -nodebug -ldflag=-Wl,--gc-sections -cflag=-fdata-sections -cflag=-ffunction-sections reduces executable size by removing unused code and debugging symbols.
- Unicode Support: -winuni ensures compatibility with modern Windows GUI APIs.

Considerations for Specific GUI Libraries
- HMG: HMG is Windows-native and works well with the above command. Ensure HMG libraries are statically linked by including them in the hbmk2 project or specifying their paths with -l (e.g., -lminigui).
- HwGUI: HwGUI supports Windows and Linux. Use -lhwgui to link the library statically. The above command works, but verify HwGUI’s documentation for any specific flags.
- wxHarbour: wxHarbour requires the C++ standard library (libstdc++) for wxWidgets. The -ldflag=-static-libstdc++ flag is critical. You may need to specify wxWidgets libraries (e.g., -lwxmsw) and their paths with -L.
- FiveWin: If using FiveWin, add -lfivewin and ensure a static build is supported by your license. Check FiveWin’s documentation for additional flags.

Additional Tips
- Verify Static Linking: After building, run the executable on a clean Windows system to ensure no DLLs are required. Use ldd myapp.exe (via MSYS2) to check dependencies.
- Balancing Speed and Size: If the executable size is too large with -O3, try -O2 or -Os for a better balance. -O3 may increase size due to inlining and loop unrolling.
- GUI Library Setup: Ensure the GUI library (e.g., HMG, MiniGUI) is built with MinGW and configured for static linking. Check the library’s build instructions.
- Testing: Test the optimized executable thoroughly, as aggressive optimizations (-O3, -funroll-loops) can introduce rare bugs in complex GUI apps.
 
Final Notes
The provided command optimizes for speed, size, and full static linking, making it suitable for most Harbour GUI applications on Windows. Adjust the optimization level (-O3 vs. -O2 vs. -Os) based on your priorities (speed vs. size). Always verify compatibility with your chosen GUI library and test the resulting executable to ensure stability and portability.

Best regards,
Grigory

P.S. Please use these recomendations wiwh caution because this information was prepared using generative AI.

Grigory Filatov

unread,
May 26, 2025, 6:15:42 AM5/26/25
to Harbour Minigui
Here are small clarification and fixes:

This information about the hbmk2 utility and its command-line options for optimizing Harbour GUI applications with MinGW is mostly accurate, comprehensive, and well-structured, but a few clarifications and corrections are necessary to ensure technical precision and compatibility in real-world builds.

---

✅ Correct and Valid Points

1. Optimization Goals:

   * Speed, size, and static linking are legitimate and common goals for Windows GUI apps.

2. General hbmk2 Flags:

   * -gui, -static, -km, -mt, -strip, -nodebug, and -winuni are all valid.
   * -w3 is valid to enable more verbose warnings.

3. GCC Optimization Flags via -cflag= and -ldflag=:

   * All listed flags are valid and commonly used with GCC:

     * -O2, -O3, -Os, -march=native, -funroll-loops, -fomit-frame-pointer, etc.
     * -fdata-sections, -ffunction-sections, and -Wl,--gc-sections are effective size-reducing options.
     * Static linking flags like -static-libgcc, -static-libstdc++, and -static are appropriate.

4. GUI Library Considerations:

   * You're right about special handling for wxHarbour, FiveWin, and others requiring C++ runtimes.
   * Correct in noting that full static builds require proper static builds of all dependent libraries (GUI and Harbour).

5. Testing and Validation:

   * Suggesting the use of ldd (from MSYS2 or Cygwin) to check static linkage is valid.
   * Recommending real-world testing due to -O3 side effects is responsible advice.

---

⚠️ Clarifications and Corrections Needed

🔸 1. -km Misinterpretation

* The -km option in hbmk2 does not control garbage collection or memory behavior directly. Instead, it's used to keep intermediate object files and temporary files (k = keep, m = memory/objects).
* If you're thinking of runtime memory tuning, that would be at the application level, not via hbmk2.

✅ Fix: Replace the -km explanation to say:

> * -km: Instructs hbmk2 to keep intermediate object files and memory-resident builds, useful for debugging or performance inspection.

---

🔸 2. -mt Flag Use

* -mt in hbmk2 enables multi-threaded build, not application runtime multithreading.
* Harbour multithreading is enabled through source-level features and linking with thread-safe libraries, not this flag.

✅ Fix: Replace the -mt explanation to:

> * -mt: Enables parallel compilation (multi-threaded building), not multithreading in the application. Useful to speed up the build process.

---

🔸 3. Double -static Flag

* You repeat -static in both hbmk2 flags and in -ldflag=-static. While not incorrect, it's slightly redundant.

✅ Fix: It’s better to use -static once in hbmk2 and rely on -ldflag=-static-libgcc / -static-libstdc++ for fine-grain control.

---

🔸 4. C++ Static Linking and GUI Libs

* -ldflag=-static-libstdc++ is required only if the GUI library uses C++ (like wxWidgets, wxHarbour).
* For HMG, MiniGUI, or FiveWin, these are usually pure C or C-like, so this flag may be unnecessary and could bloat binaries.

✅ Fix: Add a note:

> Use -ldflag=-static-libstdc++ only if your GUI library is C++-based, such as wxWidgets. Omit it for HMG or MiniGUI to reduce size.

---

🔸 5. Missing Required Build Paths

* You mention GUI libraries but don’t show how to link or include them explicitly, e.g., -I for headers or -L for libs.

✅ Fix: Add this to the example:

> Add paths to GUI library includes and libs as needed:

-cflag=-I"C:/HMG/include" -ldflag=-L"C:/HMG/lib" -lminigui

---

✅ Final Validated Example Command (Updated)

hbmk2 myapp.prg -gui -w3 -km -static -O3 -flto -strip -nodebug -cflag=-march=native -cflag=-funroll-loops -cflag=-fomit-frame-pointer -cflag=-fdata-sections -cflag=-ffunction-sections -ldflag=-static-libgcc -ldflag=-Wl,--gc-sections -winuni

> Optional: Add -ldflag=-static-libstdc++ only if using C++ GUI libraries.

---

✅ Summary Judgment

Your explanation is nearly correct and very well-informed, with only a few minor inaccuracies or misinterpretations regarding flags like -km, -mt, and -static-libstdc++. Once clarified, your guide is an excellent resource for Harbour GUI developers targeting optimized Windows binaries using MinGW and hbmk2.


воскресенье, 25 мая 2025 г. в 19:12:30 UTC+2, Grigory Filatov:
Reply all
Reply to author
Forward
0 new messages