Build-time constants with BuildInfo.mqh¶
In this guide you will learn how to:
- Configure
definesinknitpkg.yaml - Use
kp compile --define / -Dorkp build --define / -Dto inject compile-time constants - Work with the generated
knitpkg/build/BuildInfo.mqhheader in your MQL code - Produce different builds (debug, beta, production) from the same source tree
- Keep EA metadata (version, author, description) in sync with your manifest
This section assumes you have already read the Concepts › BuildInfo page and are familiar with the basic idea.
1. What BuildInfo.mqh does¶
Every time you run kp compile or kp build KnitPkg will, before invoking the compiler:
- Load your project manifest (
knitpkg.yaml) - Collect constants from:
defines.from_manifestdefines.extra- CLI flags
--define/-D
- Generate (or update) the file:
knitpkg/build/BuildInfo.mqh
This file is a pure MQL header containing #define directives, which you
can then #include in your .mq5 / .mqh code.
You never edit BuildInfo.mqh manually — it is always generated by KnitPkg.
2. Declaring constants in knitpkg.yaml¶
Let’s start with a concrete example manifest:
2.1 from_manifest¶
The from_manifest section maps:
- key → the constant name you want in MQL (
MANIFEST_VERSION) - value → the manifest field that should provide the value (
version)
In the example:
MANIFEST_VERSION: versionMANIFEST_ORG: organizationMANIFEST_AUTHOR: authorMANIFEST_DESCRIPTION: description
All of these will end up as #defines in BuildInfo.mqh.
2.2 extra¶
The extra section is a simple map of:
- constant name → value (or no value)
In the example:
MQL_STORE_VERSION: '2.0'
→"2.0"will be emitted as a stringFEATURE_X_ENABLED: null
→ null value → emitted as a flag without value
You can mix strings, numbers and flags:
defines:
extra:
MQL_STORE_VERSION: '2.0' # → #define MQL_STORE_VERSION "2.0"
MAX_BARS: 500 # → #define MAX_BARS 500
ENABLE_DEBUG: null # → #define ENABLE_DEBUG
3. Running kp compile and inspecting BuildInfo.mqh¶
From the project root (where knitpkg.yaml lives), run:
After a successful run you should see:
knitpkg/build/BuildInfo.mqh
Open that file; for the manifest above it will look similar to:
// ======================================================================
// AUTO-GENERATED BY KNITPKG — DO NOT EDIT MANUALLY
// Project : douglasrechia/expertdemo
// Version : 2.0.1
// Generated: 2026-03-05T14:11:41Z
// ======================================================================
#ifndef __KNITPKG_DOUGLASRECHIA_EXPERTDEMO_BUILDINFO__
#define __KNITPKG_DOUGLASRECHIA_EXPERTDEMO_BUILDINFO__
#define MANIFEST_ORG "douglasrechia"
#define MANIFEST_AUTHOR "Douglas Rechia"
#define MANIFEST_DESCRIPTION "KnitPkg for Metatrader - Expert Demo"
#define MANIFEST_VERSION "2.0.1"
#define MQL_STORE_VERSION "2.1"
#define FEATURE_X_ENABLED
#endif // __KNITPKG_DOUGLASRECHIA_EXPERTDEMO_BUILDINFO__
You now have a single header you can include anywhere in your project to access all of these values at compile time.
4. Using BuildInfo.mqh in your EA¶
A common pattern is to include the header at the top of your main EA file.
For the expertdemo project above, assuming your main entrypoint is
src/KnitPkgExpertDemo.mq5, you can do:
#include "../knitpkg/build/BuildInfo.mqh"
// Your existing includes and code...
int OnInit()
{
Print("Expert: ", MANIFEST_DESCRIPTION);
Print("Version: ", MANIFEST_VERSION, " (store ", MQL_STORE_VERSION, ")");
#ifdef FEATURE_X_ENABLED
Print("Feature X is enabled for this build");
#else
Print("Feature X is disabled for this build");
#endif
return(INIT_SUCCEEDED);
}
Note:
- The
#includepath is relative to the.mq5file location. - You can safely include
BuildInfo.mqhin multiple source files; it is protected by an include guard.
5. Wiring EA "Common" tab properties¶
One of the most powerful uses of BuildInfo.mqh is to keep your EA metadata
in sync with the manifest.
You can use the constants exported from defines.from_manifest and
defines.extra directly in the #property declarations:
#include "../knitpkg/build/BuildInfo.mqh"
#property copyright "Copyright © 2026 " + MANIFEST_AUTHOR + ". All rights reserved."
#property link "https://knitpkg.dev"
#property version (string)MQL_STORE_VERSION
#property description ""
#property description "Version: " + MANIFEST_VERSION
#property description ""
#property description "Description: " + MANIFEST_DESCRIPTION
#property description "Organization: " + MANIFEST_ORG
#property description "Author: " + MANIFEST_AUTHOR
#property description "License: MIT"
#property description ""
#property description "Powered by KnitPkg for MetaTrader"
#property description "https://knitpkg.dev"
With this setup:
- When you bump
versionordescriptioninknitpkg.yaml, your EA "Common" tab is automatically updated after the nextkp compileorkp build. - You don’t have to manually synchronize strings in multiple places.
- Store-specific versions (for example
MQL_STORE_VERSION) can live indefines.extrawithout polluting the manifest with store-only details.
6. Overriding constants from the CLI¶
In addition to the manifest, you can define or override constants directly
from the command line using --define or -D with both kp compile and
kp build commands.
This is useful for:
- Debug / test builds
- Nightly / beta / production channels
- Broker-specific parameters
- CI pipelines that should not edit
knitpkg.yaml
6.1 Basic usage¶
Run:
kp compile -D NIGHTLY
kp compile -D BUILD_TYPE=release
kp compile -D FEATURE_X_ENABLED -D MAX_BARS=500
kp build -D NIGHTLY
kp build -D BUILD_TYPE=release
kp build -D FEATURE_X_ENABLED -D MAX_BARS=500
Accepted formats:
-D NAME
→ emits#define NAME-D NAME=value
→ emits#define NAME "value"ifvalueis non-numeric
→ emits#define NAME 42ifvalueis numeric (42,3.14, etc.)
These CLI-provided constants:
- Are applied only for the current invocation
- Are not written back into
knitpkg.yaml - Override any constant with the same name defined in the manifest
6.2 Priority¶
If a constant name appears in more than one place, the resolution order is:
- CLI
--define/-D(highest priority) defines.extradefines.from_manifest(lowest priority)
This means you can safely set defaults in the manifest and override them from CI or local scripts without touching the file.
Example:
Then:
BuildInfo.mqh will contain:
7. Practical build variants¶
Here are a few practical patterns you can adopt using BuildInfo.mqh and
kp compile -D.
7.1 Debug vs store builds¶
In knitpkg.yaml:
In code:
#include "../knitpkg/build/BuildInfo.mqh"
#ifdef DEBUG_BUILD
#define LOG_LEVEL 3
#else
#define LOG_LEVEL 1
#endif
In your terminal:
You can then branch logic based on DEBUG_BUILD or BUILD_TYPE inside
your code without changing any source file.
7.2 Broker or environment-specific builds¶
In code:
#include "../knitpkg/build/BuildInfo.mqh"
void OnInit()
{
Print("Environment: ", ENV);
Print("Broker code: ", BROKER_CODE);
#ifdef ENV
if(ENV == "prod")
{
// production parameters
}
else
{
// staging / sandbox parameters
}
#endif
}
8. Troubleshooting¶
Here are some common issues you may run into while adopting BuildInfo.mqh.
8.1 File not found on include¶
If MetaEditor shows an error like:
'../knitpkg/build/BuildInfo.mqh' cannot be opened
Check:
- You have run
kp compileat least once after addingdefines. - The
#includepath is correct relative to the.mq5file. - The folder
knitpkg/build/exists inside the project root.
If you are unsure about the path, open the project folder in your file
explorer and adjust the #include line accordingly.
8.2 Constants missing in BuildInfo.mqh¶
If a constant you added in defines.from_manifest or defines.extra does
not show up in BuildInfo.mqh:
- Confirm that
knitpkg.yamlis valid YAML (runkp validateif available). - Check for typos in the manifest field names used in
from_manifest. - Make sure you re-ran
kp compileafter editing the manifest. - Confirm that no CLI
-Dis overriding the same constant name.
9. Summary¶
With a small amount of configuration in knitpkg.yaml, BuildInfo.mqh
gives you:
- Centralized metadata: version, author, description, organization
- Compile-time feature flags: controlled via manifest or CLI
- Consistent EA "Common" tab: always in sync with your manifest
- Multiple build flavors (debug, store, beta, broker-specific) from the same codebase
This lets you treat your MQL projects much more like modern software projects: builds are reproducible, configuration is explicit, and you can automate everything in your scripts and CI pipelines without touching .mq5 files.