How to Use the 'mk' Command (with Examples)
The mk
command in Plan 9 serves as a task runner for targets described in an Mkfile, functioning similarly to GNU Make. It is predominantly used to control the process of compiling an executable from source code. Within this context, the Mkfile specifies targets and the commands necessary to build each of those targets. The mk
command interprets this file and manages the dependencies, ensuring the correct sequence and conditions for building software.
Use Case 1: Call the First Target Specified in the Mkfile
Code:
mk
Motivation:
In a typical build setup, the first target in an Mkfile is often labeled “all” and includes the full suite of tasks necessary to compile a complete program. Using mk
without specifying a target is a convenient way to perform all operations necessary to bring your project to its final compiled form without explicit instructions for each component.
Explanation:
mk
: When run without arguments, it defaults to executing the first target specified in the Mkfile. This default behavior simplifies the build process, especially for common build scenarios where no specific target needs to be named.
Example Output:
compiling object files...
linking executable...
build complete.
Use Case 2: Call a Specific Target
Code:
mk target
Motivation:
In some circumstances, it may be desirable to execute a particular subset of tasks within an Mkfile, such as recompiling only a specific module of a large program. Using a specific target allows for more precise control over the build process, thus saving time and compute resources.
Explanation:
mk target
: This command specifies that only the named ’target’ should be built. Targets define specific build instructions and dependencies; hence specifying one focuses on completing just those instructions.
Example Output:
compiling component A...
build for target complete.
Use Case 3: Call a Specific Target, Executing 4 Jobs at a Time in Parallel
Code:
NPROC=4 mk target
Motivation:
When building large projects, builds can become time-consuming if executed sequentially. By specifying multiple jobs to be run concurrently, you can utilize available system resources more effectively and significantly decrease build times, particularly on multi-core machines.
Explanation:
NPROC=4
: This environment variable determines the number of concurrent processes to be run. Setting this to 4 allowsmk
to execute up to four tasks simultaneously.mk target
: It builds the specified target while respecting theNPROC
constraint.
Example Output:
compiling components concurrently...
task 1 complete.
task 2 complete.
task 3 complete.
building target complete.
Use Case 4: Force Mking of a Target, Even if Source Files are Unchanged
Code:
mk -wtarget target
Motivation:
In certain situations, you may need to rebuild a target even if the prerequisite files have not been altered. Forcing a rebuild can be critical when dealing with non-standard dependencies or when debugging, ensuring that all components are newly compiled and linked.
Explanation:
-wtarget
: This flag forces the recompilation of the target, ignoring timestamps of existing files which would otherwise indicate that an object is up-to-date.mk target
: Initiates the build process for the specified target.
Example Output:
force compiling all files...
target rebuild complete.
Use Case 5: Assume All Targets to Be Out of Date
Code:
mk -a target
Motivation:
This example is used to refresh not only a single target but also all of its dependencies, assuming everything to be outdated. Such situations arise when a fundamental change in the codebase affects many components, ensuring completeness of the update.
Explanation:
-a
: Assumes all targets are outdated, compellingmk
to rebuild the specified target and every associated dependency.mk target
: Specifies which primary target and its dependencies should be updated or rebuilt.
Example Output:
rebuilding all dependencies...
updating target and dependencies...
rebuild complete.
Use Case 6: Keep Going as Far as Possible on Error
Code:
mk -k
Motivation:
In cases where some parts of the build process might fail but you wish to obtain as much of the build as possible, using the -k
option allows the continuation of parallel tasks even after an error occurs. This is especially useful during development and testing phases.
Explanation:
-k
: The ‘keep going’ flag allowsmk
to continue executing tasks regardless of encountered errors, only halting when it completely cannot proceed.mk
: This runs the command as normal, applying the ‘keep going’ behavior globally.
Example Output:
compiling module...
error in module B, continuing with other tasks...
other tasks complete.
Conclusion
The mk
command is a powerful tool for managing the build process in Plan 9 environments, offering tailored operation through its diverse set of options and commands. By understanding and utilizing these command-line options, users can efficiently manage the complexity and requirements of software development tasks.