FreeBSD Manual Pages
MK(1) General Commands Manual MK(1) NAME mk -- build stuff SYNOPSIS mk [-hkpsSv] [-C dir] [-f makefile] [-o objdir] [-V var] [target ...] DESCRIPTION mk is designed to help you build stuff. It is specifically designed for larger projects, for which make(1) is not suitable enough. The following options are available: -h Print a help page for the current directory. -hv Similar to -h, but do so recursively for all subdirectories. -p Dump the current directory's makefile. -pv Same as -p, but do so recursively for all subdirectories. -s Do not echo commands, as they are executed. Equivalent to specifying '@' before each command in the makefile. -S stop processing when an erorr is encountered. This is the de- fault behavior and is the opposite of -k. -k Continue processing after errors are encountered, but only on those targets that do not depend on the target whose creating caused the error. This options is the opposite of the -S op- tion. -v Cause mk to print more verbose output. This option can be specified multiple times, to increase the verbosity. This op- tion is negated by the -s option. -C dir Change the current working directory to dir. -f mk Read file mk instead of the default makefile. Contrary to other implementations, only the last occurence of this option is honored. -o obj Put generated artifacts into the obj directory. mk will also search for artifacts in this directory. This is very useful for out-of-tree builds. -V var Print the expanded value of var to the standard output and exit. DEPENDENCY LINES Dependency lines consist of one or more targets, and zero or more pre- requisites: target ...:[prerequisite ...] This creates a relationship, where the targets "depend" on the prereq- uisites, and are built from them. Targets must consist of only characters in "[a-zA-Z._-]". Dependencies can additionally contain "/" characters, but the resulting paths must be relative, and cannot cross directories, that are outside the build. SHELL COMMANDS Each target may have associated with it a series of shell commands, normally used to build the target. While several dependency lines may name the same target, only one of these dependency lines may be fol- lowed by shell commands, and thus define a complete target rule. If a command line begins with one of the characters, `@' or `-', the command is treated specially: `@' causes the command not to be echoed before it is executed. `-' causes any non-zero exit status of the command line to be ignored. Commands are executed using /bin/sh in "set -e" mode, unless `-' is specified, or the shell is broken (in case of Minix-vmd). INFERENCE RULES TODO VARIABLE ASSIGNMENTS Variables in mk are much like variables in the shell: name = value They are also sometimes refered to as `macros'. Variable names can only consist of "[a-zA-Z0-9._-]" and may not start with a digit or hy- phen. By tradition names consist of all upper-case letters. The following operators can be used to define variables: = Assign the value to the variable. Any previous value is over- riden. := Like "=", but expand the value, before assigning it. ::= Currently equivalent to ":=". += Append the value to the current value of the variable. ?= Assign the value, if it is not already defined. ??= Similar to "?=", but take environment variables into account. != Perform variable expansion and pass the result to the shell for execution. The output of the shell command will be assigned to the variable. Any whitespace before or after the assigned value will be removed; if the value is being appended, a single space is inserted between the previous contents of the variable and the appended value. Variables are expanded by surrounding the variable name with curly braces (`{}') and preceding it with a doller sign (`$'). If the vari- able name consists of only a single letter, the surrounding braces can be omitted. Variables can be made visible into subdirectories using the ".EXPORT:" directive. SPECIAL VARIABLES The following special variables can be used: $$ The literal $ character. $. Relative path to the top-level directory. This is the short- form of ${.TOPDIR}. $@ The name of the target currently being built. This is the shortform of ${.TARGET}. $< The name of the prerequisite from which this target is to be built, if a valid inference rule (suffix rule) is in scope. This is the shortform of ${.IMPSRC}. $^ All source dependencies. This is the shortform of ${.ALLSRC}. $* This is the shortform of ${.IMPSRC:T}. ${.SUBDIRS} A list of subdirectories specified by the .SUBDIRS: directive. ${.EXPORTS} A list of variables specified by the .EXPORTS: directive. This is useful for invoking other build systems in foreign subdirec- tories. ${.OBJDIR} The object directory specified by the -o objdir option, or the current directory. ${.MAKEFILES} A list of Mkfiles from this directory upwards. ${SHELL} The shell used to interpret the command lines. ${MAKE} The name of the mk command. Alias for ${.MAKE}. ${MAKEFLAGS} A list of options given to mk. Alias for ${.MAKEFLAGS}. MODIFIERS Modifiers can be applied to a macro expansion using the following syn- tax: ${NAME:modfiers...} The following modifiers can be applied to variable expansions: :U Make all characters in string uppercase. :L Make all characters in string lowercase. :F Search for files in either the source directory, or in ${.OBJDIR}. :E Replace each word by it's suffix. "suffix" refers to the file extension. :R Replace each word by everything but it's suffix. :H Replace each word by it's dirname(1) equivalent. :T Replace each word by it's basename(1) equivalent. :Mpattern Only retain words that match pattern. :Npattern The opposite of the :M modifier. :Jseparator Concatenate each word and separate the resulting string by separator. :name=value Replace every occurence of name with value. This has to be the last modifier. These are a few examples for using macro modifiers: SOURCE = main.c lex.l parse.y gen.S # Only retain words that match the glob *.c CFILES = ${SOURCE:M*.c} # Replace all the file extension .c with .o COBJS = ${CFILES:.c=.o} clean: # Use :F to search for the object files in ${.OBJDIR} rm -f ${COBJS:F} print: # Multiple modifiers can be specified: @echo ${SOURCE:T:U} INCLUDE STATEMENTS Using the include statement it is possible to instruct mk to read an- other file. Examples: # Include a file called "templates.mk" include templates.mk # Try including a file called "config.mk", if it exists -include config.mk SUBDIRECTORIES Subdirectories can be declared using the .SUFFIXES: directive. The handling of subdirectories is done lazily, such that the Mkfile of the subdirectory is only parsed, once a target in that subdirectory tree is needed. Examples: # Declare subdirectories foo and bar .SUBDIRS: foo bar # Depend on targets from other directories foobar: foo/libfoo.a bar/libbar.so ../config.h # $^ refers to the list of prerequisites build -o foobar $^ # Print a ", " separated list of subdirectories list: @echo "${.SUBDIRS:J, }" # Depend on the clean target of every subdirectories: clean: ${.SUBDIRS:=/clean} # Prefix with ${.OBJDIR}/ for compatibility with the -o option. rm -f ${.OBJDIR}/foobar FOREIGN SUBDIRECTORIES TODO Foreign subdirectories allow integration with other build systems. This is an example of integrating an example Autotools dependency: # Declare hello as a "foreign directory" .FOREIGN: hello HELLODIR = hello ## External make used for building libhello EMAKE ?= make ## C Compiler CC ?= cc ## C Compiler Flags CFLAGS ?= ## Installation Prefix PREFIX ?= /usr/local ## Installation destination directory DESTDIR ?= .EXPORTS: CC CFLAGS DESTDIR ## Build hello/hello and xhello all: hello/hello xhello ## Delete build artifacts clean: hello/clean rm -f xhello ## Delete all non-source files distclean: clean rm -rf ${HELLODIR:F} rm -f ${.OBJDIR}/{hello.tgz,.hello-configure,.hello-extract} ## Install hello and xhello into ${DESTDIR}${PREFIX} install: hello/install xhello mkdir -p ${DESTDIR}${PREFIX}/bin cp -f ${.OBJDIR}/xhello ${DESTDIR}${PREFIX}/bin/ ## Download hello source hello.tgz: ftp -o $@ https://got.stuerz.xyz/download/hello-2.0.tgz .hello-extract: hello.tgz tar -xzf $< -C ${.OBJDIR} touch $@ .hello-configure: .hello-extract (cd ${HELLODIR:F} && ./configure --prefix=${PREFIX}) touch $@ # Check if $< is fresh in hello hello?: test -e ${HELLODIR:F}/Makefile ${EMAKE} -q -C ${HELLODIR:F} ${.EXPORTS} "$$(echo "$<" | sed 's#./##')" # Build $< in hello hello!: .hello-configure ${EMAKE} -C ${HELLODIR:F} ${.EXPORTS} "$$(echo "$<" | sed 's#./##')" ## Build the xhello binary xhello: xhello.c hello/libhello.a ${CC} -o $@ xhello.c -I${HELLODIR:F} -L${HELLODIR:F} -lhello ${CFLAGS} CONDITIONALS TODO OTHER DIRECTIVES TODO COMMENTS Comments begin with a single hash (`#') character, anywhere but in a shell command line, and continue to the end of the line. A (#) charac- ter within a shell command line will be interpreted as a comment by the shell. DOCUMENTATION COMMENTS Documentation comments are a special variant of comments, which can only appear before rule and macro definitions. To define a doc-com- ment, two hash (`#') characters must be used. Example: # This is a doc-comment for macro NAME ## Define the name of the project NAME = hello # Macros in doc-comments will be expanded: ## Build ${NAME} ${NAME}: ${NAME}.c ${CC} -o $@ $< SPECIAL TARGETS TODO ENVIRONMENT TODO FILES Mkfile default makefile EXAMPLES The following is a list of real-world projects built with mk: • desktop: https://got.stuerz.xyz/?action=summary&path=desktop.git • 286bsd: https://got.stuerz.xyz/?action=summary&path=286bsd.git EXIT STATUS The mk utility exits 0 on success, and >0 if an error occurs. SEE ALSO make(1), sh(1) STANDARDS This implementation of make(1) does not strictly follow any POSIX stan- dard, but still most simple Makefiles will work fine. HISTORY Over the the long history of make, there have been many (competing) im- plementations of make(1): • Original make from PWB/UNIX 1.0 • GNU Make • Various versions of BSD Make • Plan 9's mk(1) AUTHORS Benjamin Strz <benni@stuerz.xyz> CAVEATS • All paths used as targets/dependencies must be relative. • The handling of the `?=` and `??=` is different from POSIX. • The way environment and commandline variables are treated is dif- ferent from POSIX. BUGS • There exists another project called mk(1). • Defining recursive dependencies can lead to mk crashing. • Specifying multiple targets at once is broken. • This manual is unfinished. TODO • Run commands of the same rule in the same shell, instead of creat- ing a new shell for every command line. • Create a detailed list of all features. • Create a second implementation in Rust, which will support parallel execution of targets. • Create a comparison to other makes. • See TODO.md file. • Optional prerequisites (continue even if the prerequisite failed). • Numbered prerequisite macros. • Strip "./" prefix for $< and other variables. FreeBSD ports 15.0 January 4, 2025 MK(1)
NAME | SYNOPSIS | DESCRIPTION | DEPENDENCY LINES | SHELL COMMANDS | INFERENCE RULES | VARIABLE ASSIGNMENTS | INCLUDE STATEMENTS | SUBDIRECTORIES | CONDITIONALS | OTHER DIRECTIVES | COMMENTS | SPECIAL TARGETS | ENVIRONMENT | FILES | EXAMPLES | EXIT STATUS | SEE ALSO | STANDARDS | HISTORY | AUTHORS | CAVEATS | BUGS | TODO
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=mk&sektion=1&manpath=FreeBSD+Ports+15.0>
