🚨 Oracle not porting Rdb to x86 and EOL on Itanium 12/2027 🚨
Technical Capabilities
Having trouble finding what you need?
Get in touch with us, so we can answer your specific questions directly.
Get In Touch

VX/MMS - OpenVMS MMS to make and XML

Overview

VX/MMS is a native Linux implementation of the OpenVMS Module Management System (MMS), DEC's dependency-driven build tool and the OpenVMS analogue of make. It reads an MMS description file, builds an in-memory dependency graph, works out which targets are out of date by comparing file timestamps, and brings each target up to date by running its action lines through VX/DCL. Existing DESCRIP.MMS and MAKEFILE descriptions, their rules, macros, suffix rules and conditionals build the same way on Linux as they did on OpenVMS, so the build automation migrates alongside the application it drives.

Because the action lines are executed through the same VX/DCL command interpreter that runs migrated .COM procedures, the compile, link and utility commands inside a build (COPY, DELETE, LINK, CC, COBOL, FORTRAN and the rest) keep working after migration. VX/MMS plugs into Sector7's continuous integration migration approach: teams keep developing on OpenVMS while the same descriptions rebuild on Linux, so a build environment moves across without a code freeze.

<!-- Webflow embed (min). Source: mms-page-technical/mms-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … --> <div class="s7-tech-embed" data-vxmmsd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">What VX/MMS is</h2><p> VX/MMS is a standalone build engine, not a translator that emits an intermediate project file. It is shipped as a single image and is also reachable as the <code>MMS</code> verb inside the VX/DCL shell, so a description file that was invoked with <code>MMS</code> on OpenVMS is invoked the same way on Linux. The engine reads a description file, resolves OpenVMS-style file specifications through the VX runtime so they open on a Linux filesystem, and drives the build directly. </p><div class="table-wrapper"><table><thead><tr><th>OpenVMS MMS concept</th><th>VX/MMS counterpart</th><th>Role</th></tr></thead><tbody><tr><td>MMS utility</td><td><code>mms</code> image + <code>MMS</code> DCL verb</td><td>Reads the description file, builds the dependency graph, updates out-of-date targets.</td></tr><tr><td>Description-file parser</td><td>Line-oriented MMS lexer and parser</td><td>Parses comments, continuation, dependencies, directives, macros and conditionals.</td></tr><tr><td>Dependency and build engine</td><td>Verification and bottom-up build engine</td><td>Compares timestamps, applies built-in and suffix rules, orders the build.</td></tr><tr><td>Action execution (spawns DCL)</td><td>VX/DCL action-line bridge</td><td>Runs each action line through VX/DCL and translates the exit status back to VMS status.</td></tr><tr><td><code>MMS$STATUS</code> / <code>MMS$SEVEREST_STATUS</code></td><td>Published DCL global symbols</td><td>Exposes the per-image and worst-case build status to the surrounding procedure.</td></tr></tbody></table></div><div class="callout"><strong>Actions run through VX/DCL.</strong> VX/MMS does not reimplement the compilers or file utilities a build calls. It hands each action line to VX/DCL, the same interpreter that runs migrated <code>.COM</code> procedures, so <code>COPY</code>, <code>DELETE</code>, <code>LINK</code>, <code>CC</code>, <code>COBOL</code> and <code>FORTRAN</code> behave consistently across scripts and builds. </div><h6>Build data flow</h6><p>The engine runs one description file through three stages and emits updated targets:</p><style>.s7-tech-embed .process-flow {margin: 1.5rem 0;padding: 16px;border: 1px solid var(--s7t-border);border-radius: 10px;background: rgba(255, 255, 255, 0.01);}.s7-tech-embed .process-inputs,.s7-tech-embed .process-stages,.s7-tech-embed .process-search {display: grid;gap: 10px;}.s7-tech-embed .process-inputs {grid-template-columns: repeat(3, minmax(0, 1fr));margin-bottom: 10px;}.s7-tech-embed .process-stages,.s7-tech-embed .process-search {grid-template-columns: repeat(4, minmax(0, 1fr));}.s7-tech-embed .process-stage {min-width: 0;padding: 15px;border-top: 3px solid var(--s7t-accent);border-radius: 6px;background: var(--s7t-surface2);color: var(--s7t-text);}.s7-tech-embed .process-input {border: 1px solid var(--s7t-note-bd);border-top-width: 3px;background: var(--s7t-note-bg);}.s7-tech-embed .process-number,.s7-tech-embed .process-label {display: block;margin-bottom: 10px;font-family: var(--s7t-mono);color: var(--s7t-accent);font-size: 0.76em;font-weight: 700;letter-spacing: 0.08em;text-transform: uppercase;}.s7-tech-embed .process-stage strong,.s7-tech-embed .process-stage span:last-child {display: block;}.s7-tech-embed .process-stage strong {margin-bottom: 4px;color: var(--s7t-text);}.s7-tech-embed .process-stage span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}@media (max-width: 900px) {.s7-tech-embed .process-stages,.s7-tech-embed .process-search {grid-template-columns: repeat(2, minmax(0, 1fr));}}@media (max-width: 600px) {.s7-tech-embed .process-inputs,.s7-tech-embed .process-stages,.s7-tech-embed .process-search {grid-template-columns: 1fr;}}</style><div class="process-flow" aria-label="VX/MMS build data flow"><div class="process-inputs" aria-label="Description file inputs"><div class="process-stage process-input"><span class="process-label">Input candidate 1</span><strong>DESCRIP.MMS</strong><span>Preferred default description file.</span></div><div class="process-stage process-input"><span class="process-label">Input candidate 2</span><strong>MAKEFILE.</strong><span>Second default description file candidate.</span></div><div class="process-stage process-input"><span class="process-label">Input candidate 3</span><strong>&lt;target&gt;.MMS</strong><span>Target-derived description file candidate.</span></div></div><div class="process-stages"><div class="process-stage"><span class="process-number">01</span><strong>Parse</strong><span>Expand macros and interpret directives from the selected input.</span></div><div class="process-stage"><span class="process-number">02</span><strong>Dependency graph</strong><span>Resolve targets, sources, and explicit or built-in rules.</span></div><div class="process-stage"><span class="process-number">03</span><strong>Verify timestamps</strong><span>Compare modification times to identify out-of-date targets.</span></div><div class="process-stage"><span class="process-number">04</span><strong>Update targets</strong><span>Run action lines through VX/DCL in bottom-up dependency order.</span></div></div></div><p> The build is driven bottom-up: a target's sources are brought up to date first, recursively, before the target's own action lines run. A target is considered out of date when it is forced, when it is built from sources, when it does not exist, when any source is newer than it, or when a prerequisite was itself just rebuilt. </p><h2 id="lifecycle">Build lifecycle</h2><p> VX/MMS follows the classic MMS three-phase model. The same phases and the same description-file search order that OpenVMS MMS uses are preserved, so an existing build resolves its description file and its default target identically on Linux. </p><div class="table-wrapper"><table><thead><tr><th>Phase</th><th>What happens</th></tr></thead><tbody><tr><td>Initialization</td><td>Locate and parse the description file, expand macros, and build the dependency graph. With <code>/DESCRIPTION=foo</code> and no dot, <code>.MMS</code> is appended.</td></tr><tr><td>Verification</td><td>Stat each target and its sources and compare modification times to decide what must be rebuilt.</td></tr><tr><td>File processing</td><td>Bottom-up: build sources first (recursively), then run the target's action lines through VX/DCL.</td></tr></tbody></table></div><h6>Description-file search order</h6><p> When no <code>/DESCRIPTION</code> qualifier is given, VX/MMS looks for a description file in the OpenVMS order and uses the first one it finds: </p><div class="process-flow" aria-label="VX/MMS description file search order"><div class="process-search"><div class="process-stage"><span class="process-number">Search 01</span><strong>DESCRIP.MMS</strong><span>Use immediately when this preferred default exists.</span></div><div class="process-stage"><span class="process-number">Search 02</span><strong>MAKEFILE.</strong><span>Checked only when <code>DESCRIP.MMS</code> is absent.</span></div><div class="process-stage"><span class="process-number">Search 03</span><strong>MAKEFILE</strong><span>Checked only when both earlier candidates are absent.</span></div><div class="process-stage"><span class="process-number">Search 04</span><strong>&lt;first-target&gt;.MMS</strong><span>Target-derived fallback used after all standard names are absent.</span></div></div></div><p> The default goal is the first target declared in the file when no target is named on the command line, matching OpenVMS behaviour. </p><h6>Special targets and ordering</h6><div class="table-wrapper"><table><thead><tr><th>Target</th><th>Effect</th></tr></thead><tbody><tr><td><code>.FIRST</code></td><td>Its actions run once, before any other target is processed.</td></tr><tr><td><code>.LAST</code></td><td>Its actions run once, after all targets, even if the build failed.</td></tr><tr><td><code>.DEFAULT</code></td><td>Supplies actions for any target that has none of its own.</td></tr></tbody></table></div><div class="callout"><strong>Cycle protection.</strong> Each target carries a visit state while the graph is walked. Re-entering a target that is still on the build stack is reported as a circular dependency (<code>%MMS-F-GWKLOOP</code>) rather than looping forever. </div><h2 id="description-language">Description-file language</h2><p> The parser is a real, line-oriented MMS lexer: it honours the same lexical rules, dependency forms, action-line prefixes, directives and macro syntax as OpenVMS MMS. The examples below use a banking demo estate, but the syntax is exactly what a migrated description file contains. </p><h6>Lexical rules</h6><div class="table-wrapper"><table><thead><tr><th>Construct</th><th>Handling</th></tr></thead><tbody><tr><td>Comment</td><td><code>!</code> to end of line, respecting text inside double quotes.</td></tr><tr><td>Line continuation</td><td>A trailing <code>-</code> or <code>\</code> joins the next physical line.</td></tr><tr><td>Blank line</td><td>Ends the current rule group.</td></tr><tr><td>Indented line</td><td>An action line for the current rule.</td></tr><tr><td>Column-1 line</td><td>A directive, a macro definition, or a dependency.</td></tr><tr><td>Target / source split</td><td>Commas and/or whitespace separate list members.</td></tr></tbody></table></div><h6>Dependency separators</h6><p>Three dependency forms are recognised:</p><ul><li><code>::</code> anywhere on the line declares a double-colon rule.</li><li><code>:</code> with whitespace on either side declares a single-colon rule.</li><li>the keyword <code>DEPENDS_ON</code> (case-insensitive) is treated as a single-colon rule.</li></ul><p> Mixing <code>:</code> and <code>::</code> for the same target is flagged as an error (<code>%MMS-E-GFBTYPEMIX</code>). </p><h6>Action-line prefixes</h6><div class="table-wrapper"><table><thead><tr><th>Prefix</th><th>Meaning</th></tr></thead><tbody><tr><td><code>-</code></td><td>Ignore this line's error and keep going.</td></tr><tr><td><code>@</code></td><td>Silent: do not echo the line before running it.</td></tr><tr><td><code>?name</code></td><td>Remap this line's status through a matching <code>.ACTION_STATUS</code> definition.</td></tr></tbody></table></div><h6>A description file</h6><p> A representative banking build: macros, a link target with two object sources, a compile rule, and a conditional that selects debug or optimised compiler flags. </p> <pre><span class="cmt">! Ledger posting build</span> CC = CC LINK = LINK <span class="kw">.IFDEF</span> prod CFLAGS = /OPTIMIZE <span class="kw">.ELSE</span> CFLAGS = /DEBUG <span class="kw">.ENDIF</span> LEDGER.EXE : LEDGER.OBJ, POSTING.OBJ $(LINK)/EXE=LEDGER.EXE LEDGER.OBJ, POSTING.OBJ LEDGER.OBJ : LEDGER.C LEDGER.H $(CC)$(CFLAGS) LEDGER.C POSTING.OBJ : POSTING.C LEDGER.H <span class="kw">-</span> $(CC)$(CFLAGS) POSTING.C</pre> <h6>Directives</h6><div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Effect</th></tr></thead><tbody><tr><td><code>.SILENT</code></td><td>Global no-echo of action lines.</td></tr><tr><td><code>.IGNORE</code> / <code>.IGNORE_ALL</code></td><td>Global ignore-error.</td></tr><tr><td><code>.FIRST</code> / <code>.LAST</code> / <code>.DEFAULT</code></td><td>Run-before, run-after, and fallback action sets.</td></tr><tr><td><code>.SUFFIXES</code></td><td>Replace the suffix precedence list (empty clears it).</td></tr><tr><td><code>.SUFFIXES_AFTER</code> / <code>.SUFFIXES_BEFORE</code> / <code>.SUFFIXES_DELETE</code></td><td>Append, prepend, or remove named suffixes.</td></tr><tr><td><code>.ACTION_STATUS name = val</code></td><td>Define a named status for <code>?name</code> action prefixes.</td></tr><tr><td><code>.INCLUDE "file"</code></td><td>Parse another description file inline (macro-expanded, quote-stripped).</td></tr><tr><td><code>.IF</code> / <code>.IFDEF</code> / <code>.IFNDEF</code></td><td>Open a conditional on an expression or on a macro being (un)defined.</td></tr><tr><td><code>.ELSE</code> / <code>.ELSIF</code> / <code>.ENDIF</code></td><td>Branch and close a conditional.</td></tr></tbody></table></div><div class="callout"><strong>Nothing is silently dropped.</strong> An unrecognised <code>.</code>-directive is warned (<code>%MMS-W-DRVPARSERR</code>), not ignored without notice. <code>.INCLUDE</code> nesting is capped to guard against loops (<code>%MMS-F-LEXFILELOOP</code>), and an unterminated <code>.IF</code> at end of file warns (<code>%MMS-W-LEXNOENDIF</code>). </div><h6>Special and user macros</h6><p> Macro expansion is recursive, so <code>CFLAGS = $(OPT)/debug</code> resolves nested references, with a depth guard that raises an error on a probable circular reference. Undefined macros expand to the null string, per the OpenVMS manual, and a command-line <code>/MACRO</code> definition wins over an in-file definition. The predefined per-rule macros are populated while a rule's actions run: </p><div class="table-wrapper"><table><thead><tr><th>Macro</th><th>Meaning</th></tr></thead><tbody><tr><td><code>$(MMS$TARGET)</code></td><td>The current target specification.</td></tr><tr><td><code>$(MMS$TARGET_NAME)</code></td><td>The target name.</td></tr><tr><td><code>$(MMS$SOURCE)</code></td><td>The first source.</td></tr><tr><td><code>$(MMS$SOURCE_LIST)</code></td><td>All sources, space-joined.</td></tr><tr><td><code>$(MMS$CHANGED_LIST)</code></td><td>Sources newer than the target.</td></tr></tbody></table></div><h6>Extended string functions</h6><p> Under <code>/EXTENDED_SYNTAX</code>, VX/MMS adds a set of GNU-make-style string functions for description files that use them. Patterns use a single <code>%</code> stem, and path splitting recognises the OpenVMS and Unix separators <code>/</code>, <code>]</code> and <code>:</code>. </p><div class="kw-grid"><div>SUBST</div><div>STRIP</div><div>WORD</div><div>WORDS</div><div>WORDLIST</div><div>FIRSTWORD</div><div>LASTWORD</div><div>FILTER</div><div>FILTER-OUT</div><div>SORT</div><div>ADDPREFIX</div><div>ADDSUFFIX</div><div>DIR</div><div>NOTDIR</div><div>BASENAME</div><div>FILETYPE</div><div>FINDSTRING</div><div>PATSUBST</div><div>JOIN</div><div>WILDCARD</div><div>ORIGIN</div></div><h2 id="builtin-rules">Built-in rules, suffixes and macros</h2><p> VX/MMS seeds the standard OpenVMS built-in rules, suffix precedence and rule macros after the description file has been parsed, so any definition the file already provides takes precedence over the built-in default. A description file that relies on the implicit <code>.C.OBJ</code> or <code>.OBJ.EXE</code> rules builds without listing them. </p><h6>Default suffix precedence</h6><p>Used only when the description file gives no <code>.SUFFIXES</code> of its own, most-derived first:</p> <pre>.EXE .OLB .OBJ .C .FOR .COB .PAS .MAR .BAS .CLD .MSG</pre> <h6>Built-in suffix rules</h6><div class="table-wrapper"><table><thead><tr><th>Rule</th><th>Action</th></tr></thead><tbody><tr><td><code>.C.OBJ</code></td><td><code>$(CC)$(CFLAGS) $(MMS$SOURCE)</code></td></tr><tr><td><code>.FOR.OBJ</code></td><td><code>$(FORT)$(FFLAGS) $(MMS$SOURCE)</code></td></tr><tr><td><code>.COB.OBJ</code></td><td><code>$(COBOL)$(COBFLAGS) $(MMS$SOURCE)</code></td></tr><tr><td><code>.PAS.OBJ</code></td><td><code>$(PASCAL)$(PFLAGS) $(MMS$SOURCE)</code></td></tr><tr><td><code>.MAR.OBJ</code></td><td><code>$(MACRO)$(MFLAGS) $(MMS$SOURCE)</code></td></tr><tr><td><code>.OBJ.EXE</code></td><td><code>$(LINK)$(LFLAGS) $(MMS$SOURCE)</code></td></tr></tbody></table></div><h6>Default rule macros</h6><p>Each of these is overridable from the description file or the command line:</p><div class="kw-grid"><div>CC = cc</div><div>CFLAGS =</div><div>LINK = link</div><div>LFLAGS =</div><div>FORT = fortran</div><div>FFLAGS =</div><div>COBOL = cobol</div><div>COBFLAGS =</div><div>PASCAL = pascal</div><div>PFLAGS =</div><div>MACRO = macro</div><div>MFLAGS =</div><div>LIBR = library</div></div><h6>Suffix-rule inference</h6><p> When a target has no explicit sources and no actions, VX/MMS infers a rule: for each source suffix in precedence order whose rule <code>.&lt;src&gt;.&lt;tar&gt;</code> exists and whose candidate file is present on disk, that source and the rule's actions are adopted. When a target has explicit sources but no actions, the first source's suffix drives the rule lookup. This is how a bare <code>LEDGER.EXE : LEDGER.OBJ</code> line links without spelling out the link command. </p><h2 id="execution">Action execution and status</h2><p> The point of difference from a pure <code>make</code> clone is that VX/MMS action lines are OpenVMS DCL, not shell. Each action line is handed to VX/DCL for execution, so the compile, link and file commands inside a migrated build run through the same interpreter that runs the estate's <code>.COM</code> procedures. </p><h6>The VX/DCL bridge</h6><p> Each action line is run by spawning a fresh VX/DCL process that executes just that command and exits. The child's real exit status is captured and translated back into an OpenVMS status value: success maps to a success status, a non-zero exit maps to error severity, and a process killed by a signal maps to fatal severity. A <code>/OUTPUT=file</code> qualifier redirects each child's output so that action output joins MMS's own output stream. </p><div class="callout warn"><strong>DCL state does not persist across action lines.</strong> Because each line runs in its own one-shot VX/DCL process, changes such as <code>SET DEFAULT</code>, local symbols and logical names defined in one action line are not visible to the next. Lines that need shared state must be combined onto one line or moved into a command procedure. This is a deliberate, documented divergence from OpenVMS MMS, which runs actions in a single subprocess context. </div><h6>Status model</h6><p> VX/MMS tracks the worst status seen across all action lines. A line whose status indicates failure aborts the build (<code>%MMS-F-ABORT</code>) unless the failure is suppressed by a line-level <code>-</code> prefix, a global <code>.IGNORE</code>, or a <code>/IGNORE</code> severity floor. Severity is ranked WARNING below ERROR below FATAL. The final status is returned by the image and published as the DCL global symbols <code>MMS$STATUS</code> and <code>MMS$SEVEREST_STATUS</code> for the surrounding procedure to test. </p><p> The <code>.ACTION_STATUS</code> directive maps status letters to OpenVMS status values for use with the <code>?name</code> action prefix: </p><div class="table-wrapper"><table><thead><tr><th>Letter</th><th>Severity</th></tr></thead><tbody><tr><td><code>S</code></td><td>Success.</td></tr><tr><td><code>I</code></td><td>Informational.</td></tr><tr><td><code>W</code></td><td>Warning.</td></tr><tr><td><code>E</code></td><td>Error (the default).</td></tr><tr><td><code>F</code></td><td>Fatal.</td></tr></tbody></table></div><p>A numeric value is taken as-is, so a description file can define an exact status code.</p><h2 id="compatibility">CLI qualifiers and compatibility</h2><p> The <code>MMS</code> verb takes a target list and the OpenVMS MMS qualifiers. The qualifiers that control the build itself are honoured; a set of less common qualifiers is parsed and warned as deferred rather than being silently accepted, so a build never behaves differently than the description file implies. </p><h6>Honoured qualifiers</h6><div class="table-wrapper"><table><thead><tr><th>Qualifier</th><th>Effect</th></tr></thead><tbody><tr><td><code>/DESCRIPTION=file</code></td><td>Use a named description file (<code>.MMS</code> appended if no dot).</td></tr><tr><td><code>/ACTION</code> / <code>/NOACTION</code></td><td>Run action lines, or print them without running.</td></tr><tr><td><code>/VERIFY</code> / <code>/NOVERIFY</code></td><td>Echo, or suppress the echo of, action lines.</td></tr><tr><td><code>/FORCE</code></td><td>Rebuild targets regardless of timestamps.</td></tr><tr><td><code>/FROM_SOURCES</code></td><td>Rebuild everything from sources.</td></tr><tr><td><code>/IGNORE[=WARNING|ERROR|FATAL]</code></td><td>Set the severity floor below which a failing action does not abort.</td></tr><tr><td><code>/MACRO=("N=V",...)</code></td><td>Define macros on the command line; these win over in-file definitions.</td></tr><tr><td><code>/EXTENDED_SYNTAX</code></td><td>Enable the extended string functions.</td></tr><tr><td><code>/OUTPUT=file</code></td><td>Send MMS and action output to a file.</td></tr><tr><td><code>/LOG</code></td><td>Emit informational diagnostics.</td></tr><tr><td><code>/IDENTIFICATION</code></td><td>Print the version and exit.</td></tr></tbody></table></div><h6>Compatibility status</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Status</th></tr></thead><tbody><tr><td>Description-file parse (comments, continuation, blank-line grouping)</td><td><span class="ac-live">live</span></td></tr><tr><td>Single-colon, double-colon and <code>DEPENDS_ON</code> rules</td><td><span class="ac-live">live</span></td></tr><tr><td>Action prefixes <code>-</code>, <code>@</code>, <code>?name</code></td><td><span class="ac-live">live</span></td></tr><tr><td>Simple and recursive macro expansion, special macros</td><td><span class="ac-live">live</span></td></tr><tr><td>Conditionals (<code>.IF</code> / <code>.IFDEF</code> / <code>.IFNDEF</code> / <code>.ELSE</code> / <code>.ELSIF</code> / <code>.ENDIF</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td>Directives (<code>.SILENT</code> / <code>.IGNORE</code> / <code>.FIRST</code> / <code>.LAST</code> / <code>.DEFAULT</code> / <code>.INCLUDE</code> / <code>.ACTION_STATUS</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>.SUFFIXES</code> family and built-in suffix rules</td><td><span class="ac-live">live</span></td></tr><tr><td>Suffix-rule inference for undeclared targets</td><td><span class="ac-live">live</span></td></tr><tr><td>DCL action execution, status and severity handling, abort/ignore</td><td><span class="ac-live">live</span></td></tr><tr><td><code>/EXTENDED_SYNTAX</code> string functions</td><td><span class="ac-live">live</span></td></tr><tr><td>Persistent DCL state across action lines</td><td><span class="ac-no">out of scope: per-line one-shot, documented</span></td></tr><tr><td><code>/OVERRIDE /REVISE_DATE /RULES /SKIP_INTERMEDIATE /LIST /CHANGED /CMS /SCA_LIBRARY /GENERATE</code></td><td><span class="ac-v2">deferred: parse-and-warn</span></td></tr></tbody></table></div><div class="callout"><strong>Deferred qualifiers are named, not ignored.</strong> A deferred qualifier emits <code>%MMS-W-DRVQUALIF, /&lt;q&gt; is recognised but not yet implemented (deferred), ignored</code>, so a build script relying on one is told clearly rather than getting a silently different result. </div><h6>Divergences from OpenVMS MMS</h6><div class="table-wrapper"><table><thead><tr><th>Divergence</th><th>Reason</th></tr></thead><tbody><tr><td>Action lines run as one VX/DCL process per line, with no shared DCL state.</td><td>The one-shot command path is reliable across platforms; lines needing shared state combine onto one line or use a command procedure.</td></tr><tr><td><code>/NODESCRIPTION</code> (build purely from built-in rules) is not yet supported.</td><td>Built-in-rule-only builds are planned for a later phase; the qualifier reports rather than misbuilds.</td></tr></tbody></table></div><h2 id="quickref">Quick reference</h2><h6>Invocation</h6> <pre>MMS [/quals] target[,target...]</pre> <h6>Common qualifiers</h6><div class="kw-grid"><div>/DESCRIPTION=file</div><div>/MACRO=("N=V")</div><div>/FORCE</div><div>/FROM_SOURCES</div><div>/NOACTION</div><div>/NOVERIFY</div><div>/IGNORE[=ERROR]</div><div>/LOG</div><div>/EXTENDED_SYNTAX</div><div>/OUTPUT=file</div><div>/IDENTIFICATION</div></div><h6>Description-file resolution</h6><p> Without <code>/DESCRIPTION</code>, VX/MMS uses the first available candidate in the canonical search order shown under <a href="#lifecycle">Build lifecycle</a>. </p><h6>Rule syntax</h6><p><code>target[,...] : [source[,...]]</code> (or <code>::</code> / <code>DEPENDS_ON</code>), then indented action lines. Action prefixes: <code>-</code> ignore error, <code>@</code> silent, <code>?name</code> status map. </p><h6>Special macros</h6><div class="kw-grid"><div>$(MMS$TARGET)</div><div>$(MMS$TARGET_NAME)</div><div>$(MMS$SOURCE)</div><div>$(MMS$SOURCE_LIST)</div><div>$(MMS$CHANGED_LIST)</div></div><h6>Built-in suffix rules</h6><div class="kw-grid"><div>.C.OBJ</div><div>.FOR.OBJ</div><div>.COB.OBJ</div><div>.PAS.OBJ</div><div>.MAR.OBJ</div><div>.OBJ.EXE</div></div><h6>Diagnostic codes</h6><div class="kw-grid"><div>ABORT</div><div>DRVBADPARSE</div><div>DRVDEPFIL</div><div>DRVOUTFIL</div><div>DRVPARSERR</div><div>DRVQUALIF</div><div>EXENCRE</div><div>GFBTYPEMIX</div><div>GWKCURRNT</div><div>GWKLOOP</div><div>GWKNOACTS</div><div>LEXFILELOOP</div><div>LEXNOENDIF</div><div>LEXNULLNAME</div><div>LFSBADFP</div><div>MBREDEFILL</div></div><h6>Related tools</h6><p> VX/MMS drives, and runs alongside, the rest of a migrated OpenVMS build: <a href="/technical/vx-dcl-vms-dcl">VX/DCL</a> executes the action lines, <a href="/technical/vx-cdd-vms-cdd">VX/CDD</a> handles repository definitions, <a href="/technical/vx-decforms---decforms-ifdl-compiler-and-forms">VX/DECFORMS</a> handles forms, and <a href="/technical/vx-msg-vms-message-compiler">VX/MSG</a> compiles messages. The compilers a build calls include <a href="/technical/vx-c-vms-c-to-ansi-c">VX/C</a>, <a href="/technical/vx-cobol-vms-cobol-to-ansi-cobol">VX/COBOL</a> and <a href="/technical/vx-fortran-vms-fortran-to-ansi-fortran">VX/FORTRAN</a>. </p></div>

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

What is VX/MMS?

VX/MMS is a Linux implementation of the OpenVMS Module Management System (MMS), DEC's dependency-driven build tool and the OpenVMS analogue of make. It reads your existing MMS description files, works out which targets are out of date, and rebuilds them on Linux, so your build automation migrates with the rest of your OpenVMS application.

Do I have to rewrite my MMS description files?

No. Existing DESCRIP.MMS and MAKEFILE descriptions, along with their rules, macros, suffix rules and conditionals, are parsed and built the same way on Linux as they were on OpenVMS.

How does VX/MMS run the commands in my build?

Each action line is executed through VX/DCL, the same command interpreter that runs your migrated .COM procedures. Commands such as COPY, DELETE, LINK, CC, COBOL and FORTRAN keep working after migration because they run in the same DCL environment as the rest of the estate.

Does migrating my build force a code freeze?

No. VX/MMS fits Sector7's continuous integration migration approach. Teams keep developing on OpenVMS while the same descriptions rebuild on Linux, so the build environment moves across without a code freeze.

Which MMS features does VX/MMS support?

VX/MMS supports single-colon, double-colon and DEPENDS_ON rules; the action-line prefixes; recursive macro expansion and the special MMS$ macros; the full conditional family (.IF, .IFDEF, .IFNDEF, .ELSE, .ELSIF, .ENDIF); directives such as .FIRST, .LAST, .DEFAULT, .INCLUDE and the .SUFFIXES family; the built-in suffix rules; and extended string functions under /EXTENDED_SYNTAX.

How does VX/MMS differ from OpenVMS MMS?

The main difference is that each action line runs in its own VX/DCL process, so state such as SET DEFAULT, local symbols and logical names does not persist between lines. Lines that need shared state are combined onto one line or moved into a command procedure. A small set of less common qualifiers is deferred, and VX/MMS reports each one clearly rather than ignoring it silently.

Does VX/MMS work with the rest of my migrated OpenVMS toolchain?

Yes. VX/MMS drives the migrated compilers such as VX/C, VX/COBOL and VX/FORTRAN, and it runs alongside VX/DCL, VX/CDD, VX/DECFORMS and VX/MSG during a build.

How does VX/MMS report build status and errors?

VX/MMS tracks the worst status across all action lines, aborts on a failing line unless the failure is ignored, and publishes MMS$STATUS and MMS$SEVEREST_STATUS as DCL symbols for the surrounding procedure to test. Unrecognised directives and deferred qualifiers are named in diagnostics rather than dropped silently.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.