macOS Platform Guide

The macOS backend uses Cocoa/AppKit (Objective-C++) for all native UI components. It provides a true Mac experience with native widgets, dark mode support via NSAppearanceNameDarkAqua, and full integration with the macOS windowing system.

Backend Statistics
LanguageObjective-C++
Lines of code~3,800
HB_FUNC functions~158
Native APICocoa / AppKit (NSView, NSWindow)
Scintilla5.5.3 (static library)
Supported OSmacOS 12 (Monterey) and later
Architecturesx86_64, ARM64 (Apple Silicon)

Architecture Overview

graph TB A["Harbour .prg"] --> B["hbbuilder.ch
#xcommand preprocessor"] B --> C["TForm, TControl
Harbour OOP classes"] C --> D["HB_FUNC Bridge
~158 functions"] D --> E["Cocoa Backend
Objective-C++ / NSView"] E --> F["AppKit
NSButton, NSTextField, etc."] E --> G["Core Graphics
Drawing"] E --> H["Scintilla 5.5.3
Static lib"] style A fill:#58a6ff,stroke:#388bfd,color:#0d1117 style B fill:#8b5cf6,stroke:#7c3aed,color:#fff style C fill:#f59e0b,stroke:#d97706,color:#0d1117 style D fill:#f59e0b,stroke:#d97706,color:#0d1117 style E fill:#555,stroke:#333,color:#fff style F fill:#555,stroke:#333,color:#fff style G fill:#555,stroke:#333,color:#fff style H fill:#555,stroke:#333,color:#fff

Native Window Creation

Every HarbourBuilder form is a native NSWindow with an NSView content view. Controls are Cocoa subclasses of NSView:

// cocoa_backend.mm - Creating a form window
HB_FUNC( UI_FORMNEW )
{
   const char * cTitle = hb_parc( 1 );
   NSInteger nWidth  = hb_parni( 2 );
   NSInteger nHeight = hb_parni( 3 );

   NSRect frame = NSMakeRect( 0, 0, nWidth, nHeight );
   NSWindowStyleMask style = NSWindowStyleMaskTitled |
                             NSWindowStyleMaskClosable |
                             NSWindowStyleMaskMiniaturizable |
                             NSWindowStyleMaskResizable;

   NSWindow * window = [[NSWindow alloc] initWithContentRect:frame
                                                    styleMask:style
                                                      backing:NSBackingStoreBuffered
                                                        defer:NO];
   [window setTitle:[NSString stringWithUTF8String:cTitle]];
   [window center];

   // Set up the content view (NSView for child controls)
   NSView * contentView = [[NSView alloc] initWithFrame:frame];
   [window setContentView:contentView];

   // Store handle in Harbour-side object table
   hb_retnint( (NSInteger)(intptr_t) window );
}

Controls map to native Cocoa classes:

HarbourBuilder ControlCocoa Class
ButtonNSButton (NSButtonTypeMomentaryPushIn)
LabelNSTextField (label style, non-editable)
EditNSTextField (editable, single-line)
MemoNSTextView (in NSScrollView)
CheckBoxNSButton (NSButtonTypeSwitch or NSButtonTypeCheck)
ComboBoxNSComboBox
ListBoxNSScrollView with NSListView
GroupBoxNSBox (NSBoxTypeCustom)
ProgressBarNSProgressIndicator (NSProgressIndicatorStyleBar)
Slider/TrackBarNSSlider
ImageNSImageView
TabControlNSTabView
TableViewNSTableView (in NSScrollView)
TimerNSTimer

Event Handling

The macOS backend uses Cocoa's target-action pattern and notification system. Each control registers an action target that calls into the Harbour event system:

// cocoa_backend.mm - Button event binding
HB_FUNC( UI_ONEVENT )
{
   NSInteger nHandle = hb_parnint( 1 );
   NSInteger nEventId = hb_parnint( 2 );
   PHB_ITEM pBlock = hb_param( 3, HB_IT_BLOCK );

   NSButton * btn = (NSButton *)(intptr_t) nHandle;

   // Store the Harbour code block in a side table
   StoreEventBlock( nHandle, nEventId, pBlock );

   // Set up the Cocoa action target
   EventTarget * target = [[EventTarget alloc] initWithHandle:nHandle eventId:nEventId];
   [btn setTarget:target];
   [btn setAction:@selector( fire: )];
}

// EventTarget fires the Harbour code block
@implementation EventTarget
- (void) fire:(id)sender {
   FireEvent( self.handle, self.eventId );
}
@end

Dark Mode

macOS dark mode is handled natively by AppKit:

// cocoa_backend.mm - Dark mode setup
void SetupAppearance(void)
{
   // Follow the system appearance (light or dark)
   [[NSApplication sharedApplication] setAppearance:nil];

   // To force dark mode regardless of system setting:
   // NSAppearance * dark = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
   // [[NSApplication sharedApplication] setAppearance:dark];
}
System theme

HarbourBuilder follows the macOS system appearance setting. If your Mac is set to Dark mode (System Settings → Appearance), HarbourBuilder and all apps built with it will automatically use the dark theme. No configuration needed.

Scintilla Integration

On macOS, Scintilla 5.5.3 is built as a static library and linked directly into the HarbourBuilder binary:

FileTypePurpose
libscintilla.aStatic libraryScintilla core editing component
liblexilla.aStatic libraryLexer library

The Scintilla view is embedded as an SCIView (Scintilla's Cocoa view class) within the code editor tab. It communicates via the Scintilla direct function interface.

// Embedding Scintilla in the Cocoa view hierarchy
@interface HBCodeEditorView : NSView
@property (strong) SCIView * scintillaView;
@end

// Create and configure
SCIView * sciView = [[SCIView alloc] initWithFrame:frame];
Scintilla_SendMessage( sciView, SCI_SETLEXER, SCLEX_CPP, 0 );
Scintilla_SendMessage( sciView, SCI_SETSTYLEBITS, 8, 0 );

Build Process

Prerequisites

  1. Xcode Command Line Tools — This is the only prerequisite. Install with:
    xcode-select --install
    This provides clang, make, and the macOS SDK headers.
  2. No separate Harbour install needed — The build script downloads and compiles Harbour automatically if it's not already present.

Build Script (build_mac.sh)

The script performs these steps:

  1. Check for Harbour — If $HBDIR is not set or Harbour is not found at ~/harbour, it clones and compiles Harbour from github.com/harbour/core.
  2. Build Scintilla — Downloads Scintilla 5.5.3 source and builds libscintilla.a and liblexilla.a as static libraries.
  3. Compile the IDE — Compiles HarbourBuilder source using the Harbour compiler and clang for the Objective-C++ backend.
  4. Link — Links against the macOS frameworks: -framework Cocoa, -framework Foundation, -framework AppKit, plus the Harbour runtime and Scintilla static libs.
# build_mac.sh - Typical build session
cd HarbourBuilder/samples
./build_mac.sh

# Copy to bin/ and run
cp HbBuilder ../bin/
../bin/HbBuilder
Custom Harbour path

If you already have Harbour installed elsewhere: HBDIR=/path/to/harbour ./build_mac.sh

Apple Silicon Considerations

The default build targets x86_64 for compatibility. On Apple Silicon Macs (M1/M2/M3/M4), the binary runs under Rosetta 2 translation. For native ARM64 builds:

  1. Recompile Harbour for darwin/clang/arm64
  2. Update HBDIR in build_mac.sh to point to the ARM64 Harbour build
  3. Rebuild Scintilla with -arch arm64
  4. Build HarbourBuilder with clang -arch arm64
# Building for Apple Silicon (ARM64)
export CFLAGS="-arch arm64"
export LDFLAGS="-arch arm64"
HBDIR=~/harbour_arm64 ./build_mac.sh
Rosetta 2 performance

Rosetta 2 translation is very efficient on Apple Silicon. Most applications run with negligible performance impact. However, for the best performance — especially with CPU-intensive operations like compiling — a native ARM64 build is recommended.

.app Bundle Creation

To distribute a HarbourBuilder application as a standard macOS application bundle:

MyApp.app/
├── Contents/
│   ├── Info.plist          // Bundle metadata
│   ├── MacOS/
│   │   └── MyApp           // The compiled binary
│   ├── Resources/
│   │   ├── icon.icns       // Application icon
│   │   └── MainMenu.nib    // (optional) MainMenu
│   └── PkgInfo             // APPL????

The Info.plist must include at minimum:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>MyApp</string>
    <key>CFBundleIconFile</key>
    <string>icon</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>NSHighResolutionCapable</key>
    <true/>
</dict>
</plist>

Platform-Specific Features

FeaturemacOS Implementation
Native menusNSMenu / NSMenuItem in the system menu bar
Open/Save dialogsNSOpenPanel / NSSavePanel
Font pickerNSFontPanel
Color pickerNSColorPanel
Alert dialogsNSAlert
NotificationsNSUserNotificationCenter
File eventsFSEvents API
PasteboardNSPasteboard
Dark modeNSAppearanceNameDarkAqua
Retina supportAutomatic via backing:NSBackingStoreBuffered

Known Limitations

Dependencies

Framework/LibraryPurpose
-framework CocoaComplete Cocoa/AppKit/Foundation umbrella framework
-framework AppKitUI controls, windows, views, events
-framework FoundationNSString, NSArray, NSDate, etc.
libscintilla.aCode editing component (static)
liblexilla.aLexer component (static)
libharbour.aHarbour runtime

On This Page

Getting Started Component Palette IDE Features Tutorials Reference Platforms Architecture Overview Native Window Creation Event Handling Dark Mode Scintilla Integration Build Process Prerequisites Build Script (build_mac.sh) Apple Silicon Considerations .app Bundle Creation Platform-Specific Features Known Limitations Dependencies