MYMAKE(1)
π MYMAKE(1) β the gen-z bestie guide to mymake π
okay so. you opened the manual page for mymake, which lives in the General Commands Manual section (section 1, bestie, we're in commands territory). sit down, hydrate, and let's get into it β¨
πΈ NAME πΈ
mymake β simple build system for C/C++ π«Ά
β¨ SYNOPSIS β¨
like, here's the whole vibe in one breath:
mymake [-?] [-f] [-c] [-t] [-e] [-ne] [-p path] [-j processes] [-o
output] [-d level] [--default-input input] [files]... [options]... [--
args...]
mymake --config
mymake --target
mymake --project
three whole modes up in there, plus a big ol' pile of flags. we love a versatile icon π
π¦ DESCRIPTION π¦
so the mymake program builds C/C++ programs. that's the whole job. it's aiming to build simple programs (we call those targets) with close to zero configuration, but still be powerful enough to handle the bigger programs once your lil baby project grows up. main character energy from day one, fr fr π±βπ³
once you've installed it, run:
mymake --config
and that generates the global configuration file for the current user. this file is basically the blueprint: it specifies how to compile C/C++ programs on the current system, and it defines the default parameters that you can use in your other files (more on that below). ngl, the default contents are typically sufficient β you probably don't need to touch it π
after that initial configuration, compiling a simple program is literally: navigate to the directory with the source code of the program, and type
mymake myprogram.cpp
that compiles and links the program using the configuration in the global configuration, and β if compilation is successful β it also executes the program. build and run, one line, we ate π₯
you can pass command-line parameters to the program using the -- or the -a parameter:
mymake myprogram.cpp -- param1 param2...
and the default behavior also works with programs consisting of multiple files, which is iconic. mymake examines which files are included in the source file you specified on the command-line, and compiles those files as well. this is based on the assumption that if the file utils.h is included, then the file utils.cpp should also be compiled (if it exists). of course, different extensions than .cpp are also examined. and as is typically the case with other build systems, only files changed since the last build are rebuilt. no wasted work, periodt π
now β if the program being compiled does not follow the assumption that header files and implementation files appear pairwise, it's possible to create a file called .mymake in the project directory and add the following to it:
[]
input=*
this instructs mymake to include all implementation files in the compilation, regardless of whether or not they are considered to be needed by the program or not. it's also possible to add a particular file to the input statement (e.g. myprogram.cpp). in both cases, it will no longer be necessary to specify a file on the command line. so chill of it honestly π
as of version 2.3.0, mymake tracks the command-lines used to compile each file, and re-compiles source files where the command line has changed. this means mymake is able to re-compile the relevant parts of the project if the configuration file has changed. it remembers, bestie π§ β¨
and as the project grows, it's also possible to divide the project into separate sub-projects and have mymake manage dependencies automatically. this is done by creating a .myproject file in the root directory of the project. this tells mymake to treat all directories as sub-projects, each which may contain their own .mymake file. see CONFIGURATION for details π
π OPTIONS π
the usual GNU command line syntax is respected, with long options starting with two dashes (`-'). long options are equivalent to short options. (yes the original really does write the two-dash thing like that, we keep the facts exactly okay π«Ά)
-?,--helpβ print a message outlining basic usage and command-line options. your lil "help me bestie" button π-f,--forceβ force re-compilation of all required files, even files that would otherwise be considered to be up-to-date. this is useful if the configuration files were changed, for example. it's giving "no, do it AGAIN" π-c,--cleanβ clean build files by removing theexecDirandbuildDirindicated by the configuration based on any options specified. bye bye build artifacts, it's a cleanse β¨-t,--timeβ output information about the wall-clock time used in each step of compilation. clock the clock β±οΈ-e,--executeβ execute the executable after successfully building a target. the default configuration executes the program, but this behavior may be overridden by project-specific configuration files. the command-line parameters overrides all configuration files. π₯-ne,--not --executeβ do not execute the executable after a successful build. the inverse of-f. (yep, the manual says-fthere. we are relaying, not fixing π«‘ β the facts are the facts ngl)-p,--exec-pathβ specify the working directory when running the compiled executable. the default value is the path of the project to which the executable belongs. π-j processes,--threads processesβ spawn up to the specified number of processes in parallel during compilation. this typically means that compilation may use up to the specified number of hardware threads. this is typically not needed, as the user's preference is specified in the global configuration file. go go go, parallel princess π-C directory,--directory directoryβ change the current directory to directory before doing anything. this is convenient if one desires to build (and run) a program in a different directory without changing there first. equivalent to the-Cflag inmake, or the following expression that starts a subshell in Bash:(cd <directory>; mymake <args>)π-o output,--output outputβ specify the name of the output file (note: not the location). this can be used to override the default behavior, but this is better done in one of the configuration files. nameβ place, bestie, don't get it twisted π―-d level,--debug levelβ specify the debug level, either as a number or as the associated label. here are the levels, the whole spectrum π:0: QUIETβ no output except for fatal errors. π€1: NORMALβ the default value. outputs progress information. πΆβοΈ2: PEDANTICβ warns about configuration issues that might be errors. useful as a first step in debugging configurations. π§3: INFOβ prints information about decisions during the build. good for debugging configurations. π4: VERBOSEβ all information you will typically need when debugging configuration issues. π£οΈ5: DEBUGβ information typically only needed when debuggingmymakeitself. π
--default-input inputβ add input as an input file if no other inputs were specified either on the command line or in any configuration files. this option is intended to be used when integratingmymakein an editor. the editor may then always supply the name of the current open file as a--default-inputto makemymakedo the right thing based on configurations: compiling the current file if nothing else is specified, otherwise follow the other, more precise instructions in the configuration files. editor besties, this one's for you π»π[options]β zero or more options may also be specified on the command line. these options may correspond to sections in one of the configuration files to enable (or disable). see the CONFIGURATION section below for details. on and off energy β¨[files]β files may also be specified on the command line.mymakewill add all names that correspond to existing files (possibly first appending known file extensions) to the list of input files to process. drop the names, it handles it π--configβ create the global configuration in~/.config/mymake/mymake.conf(unless overridden using theXDG_CONFIG_HOMEenvironment variable). this can also be used to revert the global configuration to the default state. will ask for the preferred number of threads to use during compilation, if-jis not specified earlier on the command line. π--targetβ creates the file.mymakein the current directory. it fills the file with a template configuration that contains common options and settings. π―--projectβ creates the file.myprojectin the current directory. the file contains a template suitable for a project, i.e. a directory consisting of multiple targets. ποΈ--global-configβ specifies the location of the global configuration file to use instead of the default (~/.config/mymake/mymake.conf). π
okay that's the setup, the vibes, and the flags β and there's more coming, so don't go anywhere bestie π
π CONFIGURATION π
okay bestie, listen up, this is the part where mymake gets its whole wardrobe together. a mymake configuration is literally just a set of named variables, and every single one of those variables holds an array of strings. that's it. that's the tea. π«
so where do these values come from? they can come from one (or more) of four places, and here they are in the order that matters:
- the global configuration π
- the project configuration (
.myproject, if it's even there) π - the target configuration (
.mymake, if it's even there) π― - the command-line β¨οΈ
and the project + target configs? they can live in the current directory or literally any parent directory. iconic. but here's the little plot twist: if a project configuration is found, then target configurations are expected to be sitting in sub-directories of the project configuration. so like, know your place, target configs. π
options are always applied in the order above, no exceptions, no skipping. which means the global configuration can get overridden by the other configs, and the command-line parameters are always applied last because obviously the command line is the main character. π
but wait π there's one exception: when you're compiling a project, command line parameters are only applied when resolving the project configuration β they do not get applied when resolving the configuration for individual targets. remember that. it will come up.
πΈ the config file format πΈ
every single configuration file follows the exact same format, no cap. they're all a sequence of assignments to variables, and those can optionally be grouped into zero or more sections. lines that start with # are comments (so go ahead and annotate your chaos).
assignments come in one of these two forms:
name=value
name+=value
- the first form replaces the entire contents of the variable with the string
value. bye bye old data. π - the second form adds
valueas the last element of the array. that's the append queen behavior. π - and as a special little treat: if you use the first form and
valueis empty, the variable gets assigned the empty array. just so we're clear.
assignments can be grouped into sections by putting a section header before them. a section header looks like this:
[option1,option2,...]
what does it mean, bestie? it means: only consider the following assignments if every single option in that header is present in the context where the config is being evaluated (like, specified on the command line). so:
[]β always evaluated β (empty header, no conditions, slays every time)[release]β only evaluated if thereleaseoption has been specified[release,unix]β only if bothreleaseandunixhave been specified
and plot twist: you can prefix an option with ! to mean that option has to be absent. for example: [!release,unix]. that's the "not like the other options" syntax. π
then mymake evaluates each configuration file in turn to build up the set of variables used during compilation. it does this by walking through every assignment, in every file, in the order they're specified, and just skipping any sections that should be skipped based on the options available. simple.
typically each file is only evaluated once, with a context made of the options you passed on the command-line. the exception here is .myproject-files, which get their own whole moment in the PROJECTS section below. π
β¨ PRE-DEFINED OPTIONS β¨
these options come pre-loaded, defined by mymake itself or by the default configuration, and you can use them right out of the box. no setup, we love a ready-made queen. π
releaseβ produce a release version of the program. this typically means turning on more aggressive optimizations. go fast or go home. π₯libβ produces a static library. typically used in projects when some targets are static libraries used by other targets in the project. teamwork makes the dream work. π€sharedlibeβ produces a dynamic library. typically used in projects, likelib. β¨unixβ defined by mymake when compiling for a UNIX-like system. π§windowsβ defined by mymake when compiling for a Windows-like system. πͺprojectβ defined automatically when evaluating the.myprojectfile in the project context. πbuildβ defined automatically when evaluating the.myprojectfile to find options for the targets in a project. π¨depsβ defined automatically when evaluating the.myprojectfile to find explicit dependencies between projects. π§΅
𧬠VARIABLES π§¬
okay bestie, so these are the variables mymake uses to figure out what it's actually supposed to do. Some of them are special β like, mymake itself cares about them β and others get defined by the global configuration. And yes, you can totally define and use your own extra variables in config files, go off π
extβ Array of the file extensions you want to compile. Whenever mymake notices you includedx.h, it goes looking through every extension inextto hunt down the matching implementation file π΅οΈββοΈexecExtβ The file extension for executables. Gets slapped onto the output filename automatically, no cap.intermediateExtβ File extension for intermediate files. Standardly.oon UNIX systems.buildDirβ String with the directory where all your temporary build files live. It's relative to the root directory of the target (aka where the.mymakefile is).execDirβ String with the directory where the final output (the executable) of all targets goes. Relative to the target's root directory.ignoreβ Array of wildcard patterns (shell-style) deciding if a file should just be ignored. So useful when you're playing with templates, or when parts of the source code simply should not be compiled π ββοΈnoIncludesβ Array of wildcard patterns (again, shell-style) deciding if a path should NOT be scanned for headers. Chef's kiss when part of your code isn't C/C++ and looking for#includeis literally meaningless.inputβ Array of file names to use as roots when hunting for files that need compiling. Anything on the command line that isn't an option gets appended to this variable. The special value*means "compile all files with an extension in theextvariable" β which is usually what you want when you're compiling a library of some kind. β¨outputβ String naming the output file. If you don't specify it, the name of the first input file gets used instead.appendExtβ Append the original extension of the original source file to the intermediate file when compiling. This lets mymake compile projects where multiple files share a name β likefoo.cppandfoo.cβ without both of them trying to createfoo.oand tanking your whole compilation. mymake will warn you if you might need this one πincludeβ Array of paths to add to the compilation's include path.includeClβ Flag to prepend all the elements ininclude.includesβ Generated automatically by mymake; it's equivalent to adding the contents ofincludeClbefore each element ininclude.libraryβ Array of system libraries to link to your executable.libraryClβ Flag to prepend all the elements inlibrary.localLibraryβ Array of local libraries to link to your executable (usually used in a project).localLibraryClβ Flag to prepend all the elements inlocalLibrary.libsβ Automatically generated by mymake, equivalent to addinglibraryClbefore all elements oflibrary, also including local libraries.defineβ Preprocessor defines.defineClβ Preprocessor define flag.executeβ Yes or no, telling mymake whether it should run the program after a successful compilation. Can be overridden on the command line with-eor-ne.pchβ The precompiled header file name that should be used. If you're on the default config, you only need to set this variable to use precompiled headers. And if you're using#pragma oncein gcc, you will sadly get a warning that seems genuinely impossible to disable (it's not a problem when precompiling headers though, so breathe).pchFileβ The name of the compiled version of the file inpch.pchCompileβ Command line for compiling the precompiled header file.pchCompileCombinedβ If set to yes,pchCompileis expected to generate both the pch-file and compile a.cpp-file. multitasking icon πpreBuildβ Array of command-lines to run before the build starts. Expands variables.preBuildCreatesβ Array of files created by the pre-build step which should also be included in the compilation. These are expected not to introduce any additional dependencies into the project, since they literally aren't available yet at the point where mymake resolves dependencies between files and targets.postBuildβ Array of command-lines to run after the build is completed. Expands variables.compileβ Array of command lines to use when compiling files. Each command line starts with a pattern (ending in:) that gets matched against the file name to be compiled. The command line added last is checked first, and the first matching command-line wins. So it's useful to add the general command-line first (starting with*:), then add the more specific ones. Here you can use<file>for the input file and<output>.linkβ Command line used when linking the intermediate files. Use<files>for all input files and<output>for the output file-name.linkOutputβ Link the output of one target to any target that depends on that target. See projects for more info.forwardDepsβ Forward any of this target's dependencies to any target that depends on this target.envβ Set environment variables. Each element inenvis expected to be in the form:variable=value,variable<=value, orvariable=>value. First form replaces the environment variablevariablewithvalue. Second form prependsvaluetovariableusing the system's separator (:on unix,;on windows). Third form appendsvaluetovariable. The second and third forms are super convenient when you're working withPATH, for example πΈexplicitTargetsβ In projects: ignore any potential targets that don't have their own.mymake-file.parallelβ In projects, this says whether projects that have all their dependencies satisfied can be built in parallel. Default value isyes, so projects that can't tolerate parallel builds may set it tono. In targets, this says whether files within targets may be built in parallel. If so, all input files β except precompiled headers β are built in parallel using up tomaxThreadsthreads globally. If specific targets can't tolerate this, setparalleltonoand mymake will build those targets in serial, no drama.maxThreadsβ Limits the global number of threads (which are actually processes, bestie) used to build the project/target globally.usePrefixβ When building in parallel, add a prefix to the output that corresponds to different targets. Defaults to eithervcorgnu(depends on your system). If you set it tono, no prefix gets added.vcaddsn>before output,gnuaddspn:before output. This is so Emacs can recognize the error messages from the vc and gnu compilers respectively. thoughtfulness πabsolutePathβ Send absolute paths to the compiler. This helps emacs find the proper source files in projects with multiple targets.implicitDepsβ (defaults toyes) if set, mymake tries to figure out dependencies between targets by looking at includes. Sometimes this results in unneeded circular dependencies, which makes compilation fail π so sometimes it's necessary to set this tono.
π IMPORTANT ONE, PLS READ: every variable that contains commands to execute can be prefixed with an integer followed by a colon (for example1:gcc). If prefixed with the integer N, the first N lines of output from that command get removed from the output. So basically you can use this to ignore status info from commands during the build without ignoring the actually useful info. Example: the C++ compiler on Windows outputs a line containing the filename being compiled by default. That's unnecessary since mymake already does this. So it can be suppressed by issuing the command1:cl ....
This feature is possible to use in the variables compile, pchCompile, and link.
πͺ VARIABLES IN STRINGS πͺ
When mymake uses some variables (most notably, the compilation and link command lines) it looks at each string and recursively replaces any variables that appear there. Note that this is not done when the configuration is evaluated β only when the variables are actually used. timing is everything, queen β¨
Any occurrences of <variable> get replaced with the contents of variable. It's also possible to prepend a string to each element in another variable using the syntax <prefix*variable>, which means the string in the variable prefix gets prepended to each element in the variable variable.
The special variable <env:X> (where X is any string) can be used to extract the value of environment variables. This is useful to, say, inspect the value of CFLAGS during compilation. The benefit of using this syntax over relying on shell expansion is that it lets mymake track changes in the environment variables. π
It's also possible to perform an operation on each element in the array using the syntax <op|variable>. And yes, you can both perform an operation and prepend data using <prefix*op|variable>. Supported operations are:
titleβ Treat the element as a path and extract the file or directory name (e.g.src/foo.txtgivesfoo.txt).titleNoExtβ Same astitle, but the file extension is removed as well.noExtβ Remove the file extension from a path.pathβ Format the element as a path for the current operating system. For examplesrc/foo.txtevaluates tosrc\foo.txton Windows.buildpathβ Make the element into a path inside the build path.execpathβ Make the element into a path inside the executable path.parentβ Evaluates to the parent directory of the path. If no parent is given (e.g. only a file name), the element is removed from the array.ifβ Make all elements empty. This can be used to test if a variable contains a value and then include some other text. For example<usePch*if|pchFile>to add the flag insideusePchif a file is specified inpchFile.
πΈ PROJECTS πΈ
okay so bestie, a project is literally just a little squad of targets all linked together by a .myproject-file π«Ά
and here's the β¨iconicβ¨ part: that .myproject file does not get read just once. it gets evaluated multiple times, each time with different options present, so mymake can extract different info about the project out of it. it's giving multiple costume changes, one file, many eras π
π¨ build
build β mymake evaluates the .myproject-file once with the build option set. and uniquely to this pass, only the parts that explicitly mention build are extracted. no mention, no entry, periodt π
after that, mymake expects to find a list of options to apply to each of the sub-projects. for example, a project file often contains a section like this:
[build]
main+=debug
libfoo+=lib
libfoo+=debug
so in this case we're instructing mymake to build the main target with the debug option present, and the target libfoo with the options debug and lib. simple as that π
also there's a special target called all β whatever options it's given will apply to all targets in the project. every last one. no skipping π
from version 2.4.5 and onwards of mymake, it's also possible to specify build options in the target's .mymake file by assigning additional options to the self variable inside a build block. so for example, the options to libfoo above could be specified in libfoo's .mymake file like this:
[build]
self+=lib
self+=debug
so now the target can lowkey dress itself π₯
π deps
deps β this option is specified during one evaluation to extract explicit dependencies between projects. by default, mymake finds dependences between projects automatically by examining includes across projects. in certain cases though, it's genuinely useful to introduce extra dependencies, just to make sure that some dynamically loaded parts are also built. we've all been there π«
this section is very similar to the build section. mymake expects to find variables corresponding to each target, and that these variables contains names of other targets. and as with build, only sections that explicitly mention deps are considered. it's also possible to define explicit dependencies in the per-target .mymake file using self+=Dependency as above. same energy, different section π¦
if one target results in a library, it's convenient to set the variable linkOutput to yes for that target. mymake will then add the output of the library target to the library variable of any targets that depend on it. chef's kiss π
and after mymake has extracted the necessary project information? the .myproject-file is also evaluated once for each target π which means yep β it's totally possible to specify additional variables or options that apply to all targets in the project, right there in the .myproject file. slay.
and that's the whole page, bestie π this edition of MYMAKE(1) is dated August 4 2026 β go build something iconic, i'll be here πβ¨
π¦ where this page comes from
- ubuntu stonking: mymake 2.4.5+dfsg-1 Β· MIT
- Copyright 2026 Filip StrΓΆmbΓ€ck <fstromback@debian.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms