# Calculator — a native Nervous (DGrid) example whose UI is DML, built ON a Nervous system.
#
# This shows the full Qt-style flow. `dml-compiler` (shipped in /usr/bin, the Nervous `uic`) turns
# calculator_ui.dml into:
#   - calculator_uiDML.cpp : the widget-tree builder (CalculatorWidget::load_from_dml()).
#   - ui_calculator_ui.h    : `struct Ui::CalculatorWidget` with a typed pointer to every named widget.
# CalculatorWidget.cpp does `#include "ui_calculator_ui.h"`, calls m_ui.setup(*this), and then
# reaches every control as m_ui.display, m_ui.btn_7, … — exactly like Qt's ui.* .
#
# Usage:   make            # generates the DML files, then builds ./Calculator
#          ./Calculator
#          make clean
#
# Nervous ships bmake as `make`, the DGrid link fragment as /usr/share/mk/DGrid.mk, and the desktop
# dev headers under /usr/include, so this needs no build tree.
#
# Why there's a "bin/Calculator/CalculatorWidget.h" rule below even though this directory is flat:
# the DML root class is "@Calculator::CalculatorWidget", and dml-compiler always resolves a custom
# (non-GUI::/WebView::) root class's header as <bin/<Namespace>/<Class>.h> (see include_path_for()
# in tools/DMLCompiler/main.cpp) -- the same convention the in-tree apps (desktop/bin/<App>/)
# satisfy for free through their build's -I flags. If that __has_include() in the generated
# calculator_uiDML.cpp can't find the header, it silently falls back to emitting its OWN barebones
# CalculatorWidget declaration -- a SECOND, incompatible definition of the same class in a different
# translation unit from the real one in CalculatorWidget.h. That's an ODR violation (a silent
# miscompile, not a build error): the crash symptoms look exactly like the memory-corruption bugs
# elsewhere in this tree (VERIFICATION FAILED in Vector.h / RefPtr.h). Rather than nesting the real
# source under bin/Calculator/ (this example is meant to be self-contained, a flat directory you can
# copy anywhere), the rule below generates a one-line forwarding shim at that exact path -- a build
# artifact, cleaned by `make clean`, that just #includes the real, single CalculatorWidget.h next to
# this Makefile. That satisfies the __has_include() so only one definition of the class ever exists.

.include <DGrid.mk>

PROG_CXX=	Calculator
MAN=

SRCS=	calculator_uiDML.cpp \
	CalculatorWidget.cpp \
	main.cpp

# The generated headers must exist before the sources that include them compile.
SRCS+=	ui_calculator_ui.h bin/Calculator/CalculatorWidget.h

# The standard comes from DGrid.mk (CXXSTD): bsd.sys.mk appends its own -std after CXXFLAGS.
CXXFLAGS+=	-fno-exceptions -I.
LDADD+=		${DGRID_LIBADD}

CLEANFILES+=	calculator_uiDML.cpp ui_calculator_ui.h bin/Calculator/CalculatorWidget.h
CLEANDIRS+=	bin

# DML -> tree builder (.cpp) and the Qt-style typed header (ui_*.h), via the shipped compiler.
calculator_uiDML.cpp: calculator_ui.dml
	dml-compiler --dml-companion ${.ALLSRC} > ${.TARGET}
ui_calculator_ui.h: calculator_ui.dml
	dml-compiler --header ${.ALLSRC} > ${.TARGET}

# Forwarding shim so dml-compiler's <bin/Calculator/CalculatorWidget.h> __has_include() (see the
# note above) finds the real header, kept flat right next to this Makefile.
bin/Calculator/CalculatorWidget.h: CalculatorWidget.h
	mkdir -p ${.TARGET:H}
	echo '#pragma once' > ${.TARGET}
	echo '#include "../../CalculatorWidget.h"' >> ${.TARGET}

.include <bsd.prog.mk>
