@title: Makem Specification @author: H. Cassé @date: 22/09/06 ====== Lexical Items ====== The scripts are organized by line. If a physical line ends with '\', the logical line continues on the next line. The comments extends from the '#' to the end of the line (comments may extends on many lines providing it ends with '\'). The variables names have the following format : ''[a-zA-Z_][a-zA-Z_-]''. Makem handle texts thanks its macro system. With some special functions or in rules, the text is split according the spaces or the tablation contained in a text to make file paths. To have a space or a tabulation in a path, you may : * prefix it with "\", * enclose it in "..." or '...'. Please note that file paths may be written but, whatever the running system, the used separator is always "/". When used in command action, the "/" are translated to the local system separator. ====== Script Syntax ====== ===== Line Level ===== The scripts are organized by line or by a group of line. The following pattern line-level syntax items may be used in a script : * nothing (an empty line), * a variable definition (only on one line), * a conditional instruction (extending on many line), * a repetition expression (extending on many line), * a static rule (extending on many line), * a pattern rule (extending on many line). ===== Variable Definition ===== A variable definition has several syntax: variable_definition ::= variable_path "=" text | variable_path "+=" text | variable_path ":=" text | variable_path "?=" text In the first form, the variable designed by the //variable_path// is now equal to the given //text// (where the variables are not expanded). In the second forme, the variable designed by the //variable_path// is now to its current value concatenated with the given text (no variable expansion is performed in the //text//). In the third form, the designed variable is now equal to the //text// where variable use and function calls have been expanded. The last form performs the assignment only if the variable is not defined. Look at the "Variables and Environment" for more information about variable expansion and variable paths. ======= Conditional Instruction ===== The conditional instruction allows to execute some parts of the script according a condition depending on the current state of the script interpretation. They follows the following syntax: conditional_instruction ::= condition "\n" then:script ("else" condition "\n" else:script)*("else" "\n" else:script)? "endif\n" condition ::= "ifdef" VARIABLE_NAME | "ifndef" VARIABLE_NAME | "ifeq" "(" expression "," expression ")" | "ifeq" '"' expression '"' '"' expression '"' | "ifeq" "'" expression "'" "'" expression "'" | "ifneq" "(" expression "," expression ")" | "ifneq" expression expression | "if" expression "ifdef" interpret the //then// script if the given variable exists while "ifndef" works in an opposite way. Else the //else// part is interpreted. "ifeq" interpret the //then// script if both expressions are equals (beware of spaces, the comparison is strict). "ifneq" works in opposite. "if" evaluates to true if the given expression evaluates to non-empty value (spaces and tabulation are ignored). ===== Repetition Instruction ===== The repetition cause the script processor to re-interpret many times the same part of the script. It allows to apply the same processing to a list of values. repetition ::= "for" VARIABLE_NAME "in" expression "\n" script "endfor" The expression is evaluated, split according blanks and the script is interpreted for each value of the obtained value. At each sript interpretation, the //VARIABLE_NAME// name takes the value of an item from the expression list in order of the list. ===== Static Rules ===== A rule is composed of three parts : * targets : the list of files built by the rule, * dependencies : the list of files used to build the targets, * actions : list of command used to build the target using the dependencies. The goal of the Makem script interpreter is to build a set of rules, possibly chained to form a tree, in order to perform an action. The rules are processed from the leaf to the root of trees that represents the targets that need to be built. The requested target may passed to the Makem command line or, if there no target argument, the target of the first rule. A rule implement the following semantics : if a dependency has changed (its modification time is earlier than its targets or if its action signature has changed), the targets are built by executing the actions. A rule follows the syntax below : rule ::= target:expression ":" dependencies:expression "\n" indented_lines* indented_lines ::= " "{8} action_line | "\t" action_line action_line ::= ("@" |"-" | "@-" | "-@")? action The action list continues until the next empty line. Usually, an action performs output to the standard output and stop the Makefile execution if it fails (non-null return code). Some prefixes may change this behaviour : * ''@'' block the output of the action, * ''-'' ignore failed command, The actions inside a rule may access special variables (called automatic variables in original Make) : * ''$@'' : the targets of the current rule, * ''<'' : the first dependency, * ''$?'' : all dependencies newer than the targets, * ''$^'' : all dependencies, * ''$+'' : the dependencies text, ===== Pattern Rules ===== As opposed to static rule that apply to specific targets and sources, the pattern rules may applies to a generic family of files sharing some name likeness. Pattern rules shares the same syntax than pattern rules but the used file name may contains "%" (one per file name) meaning any sequence of character. When a file need to be built, either there is a static rule whose targets contains the file and it is used. Else, the pattern rule targets are tested against the file. If a pattern target matches the file, the sources where the '%' has been replaced by its effective value for the given file are looked for possibly triggering other pattern rules. The process ends when all source files exists in the file system : the pattern is selected for building the file. When a source file cannot be built, the owner pattern is invalidated possibly invalidating the parent patterns. Makem give up only if there is no combination of static and pattern rule to build a file. The pattern rules add some automaic variables : * ''$*'' : the value of the "%". ====== Actions ====== ====== Variables and Environments ====== ===== Environment Work ===== An improvemt of Makem over Make is the use of environneme nt that allows to nest and re-use scripts efficiently or to customize pattern rules behaviour. In Makem, an environment is just a set of named variables. Each variable may contain a text or another environment. When Makem start, there is only one environment : the root environment. The environment are then embedded according their path in the file system. When Makem starts, it loads the ''main.mk'' script of the current directory. Each script creates an environment where it is interpreted. If this script includes a file in a directory above, an environment is created for directory in the current script environment. The scripts in the same directory shares the same environment. When a script located in a directory not descendant from the top-directory, its environment is put in a special environment /.extern that reflects the the root of the file system. The environments exists also for non-script files and for rules. In this way, modification of the environment in a script or in rule action does not affect the other environments and make easier the sharing of scripts. The environment attached to files allows also to change the behaviour of pattern rules if its action use variable defined in the source / targets environment. As default, each variable assignment is performed in the current environment if only the name of the variable is given. But, instead of names, path may be given and in this case, the designed environment is changed. ===== Variable Path ===== Note that the syntax of paths is very close to paths in a file system. The paths follows the syntax below. relative_path ::= NAME | "." | ".." | relative_path "/" NAME absolute_path ::= "/" relative_path variable_path ::= relative_path | absolute_path An absolute path starts from the root environment "/" and go down in the environment tree. Each environment has for name the tree it is contained in. The relative paths are built based on the current environment path. The special name "." represents the current environment and ".." the parent environment. ===== Variable Expansion ===== Before being used in rules or in straight assignment, the texte is evaluated and the variables accesses are replaced by texte. A variable access has the syntax below : variable_access ::= "$(" variable_path ")" | "$(" variable_path (" " | "\t")+ text ("," text)* ")" The first form is simply replaced by the value of the matching variable. If the variable path is a relalive path, the first part is retrieved from the current environment. If it is not found, it is looked for in the parent environments, from the nearest to the furthest. The remaining parts are retrieved from the obtained environment. If it is an absolute path, the path is resolved from the root environment. The second is often named a function call. The obtained variable is considered as a function text possibly containing ''$''//i//'' variables. Each of this variables matches, according their number starting at 1, an argument passed after the variable path (this arguments are evaluated before the evaluation of the variable). ===== File Environment Assignment ===== ====== Built-ins ====== ===== Default Scripts ===== Unlike Make, Makem does not provide any built-in pattern rule (called implicit rules) so there not overhead to initialization or name conflict : the use fully control the work of makem. Yet, Makem is delivered with a bunch of read-to-use scripts for handling common types of building : C, C++, CAML, Lex, Yacc and more to come. The default scripts of Makem are accessible from a path, OS-dependent, stored in the variable MAKEM_BASE. To use one of the deleivered script, **example** import $(MAKEM_BASE)/script.mk Below, we present the different scripts, their action and their variables. ===== Built-in Functions ===== Finally, Makem provides a large collection of built-in functions for formatting texts or accessing the file system. ==== Text Processing ==== **$(filter patterns,text)** Return file names of the //text// that matches a pattern in the given blank-separated list of //patterns//. **$(filter-out patterns,text)** Return file names of the //text// that does not match a pattern in the given blank-separated list of //patterns//. **$(finstring find,text)** If the //text// contains an occurence of //find//, return ''find''. Else return an empty string. **$(firstword text)** Return the first word of the given //text//. **$(join words1, words2)** Return a list of words build by concatenating in parallel words of //words1// with words of //words2//. **$(lastword text)** Return the last word of the given //text//. **$(patsubst pattern,replacement,text)** Replace in the given //text// the occurences of //pattern//, that may contain a ''%'' character meaning sequence of character by the given //replacement//. If the replacement contains a ''%'', it is replaced by the matching text in the //pattern//. **$(sort text)** Return a text with the name of the given //text// are sorted and duplicates removed. **$(strip text)** Remove heading and trailing spaces and replace any sequence of blank character by a single space. **$(subst from,to,text)** Replace in the given //text// the occurences of string //from// by the occurences of the //to// string. **$(word n,text)** Return the //n//th word of the text. **$(wordlist prefix,suffix,text)** Return words of the //text// starting with the given //prefix// and ending with the given //suffix//. **$(words text)** Return the number of words in the //text//. ==== File Names ==== In most file name function, the //text// parameter is viewed as a blank-separated list of file paths. **$(abspath paths)** Return the absolute form of the given list of paths. **$(addprefix prefix,paths)** Return the given //prefix// concatenated with the given //paths//. **$(addsuffix suffix,paths)** Return the given //paths// concatenated with the given //suffix//. **$(basename text)** Return only the base name part of the passed //paths//, that is, the full path without the extension. **$(dir paths)** Return only the directory part of the passed //paths//. **$(exists path)** Return the path if a file or a directory exists matching the path. Return an empty string else. **$(notdir text)** Return only the file part of the passed //paths//. **$(realpath paths)** Return the canonical absolute form of the given list of paths. **$(suffix text)** Return only the extension / suffix part of the passed //paths//. **$(wildcard expression)** Evaluates and return the given shell wildcards as it is performed in the OS shell. ==== Special Functions ==== **$(call variable,param1,param2,...)** Evaluates the content of the //variable// as a function call with the given parameters. This function is obsolete because, in Makem, any variable may be called with the standard syntax. It is only kept for compatibility with GnuMake. **$(error message)** Stop the execution of Makem and display the given //message//. **$(eval text)** Interpret the given text as the top-level script, possibly containing commands, variable assignment or rules. **$(foreach variable,list,text)** Build a text by concatenating the evaluation of the passed //text// for each word on the //list// assigned to the given //variable//. **$(if condition,then-part,else-part)** If the //condition// expression evaluates to non-empty string, the result is the evaluation of the //then-part// else it is the evaluation of the //else// part. **$(info message)** Display the given message as information. **$(origin variable)** Return one the following value about the origin of the //variable//. * ''undefined'' if the variable is undefined, * ''default'' (obsolete, not used in Makem), * ''environment'' if the variable is defined in the OS shell environment, * ''environment ovveride'' (obsolete, not used in Makem), * ''file'', defined in a script, * ''command line'', passed to the Makem command line, * ''override'', defined in a script with ''override'' keyword, * ''automatic'', an automatic variable. **$(shell command)** Execute the given command on the current OS shell. **$(value variable)** Return the value of the variable without expansion of the contained variable accesses. **$(warning message)** Display a warning with the given message. ==== Condition Functions ==== This condition functions helps to evaluate complex conditions. **$(and expression1,expression2,...)** Evaluation the expressions in turn. If one evaluates to an empty string, return it else return the evaluation of the last expression. **$(equal expression1,expression2)** Evaluates both expressions and return it if they are equals. Return an empty string else. **$(in word,words)** Return the //word// if it is contained in the //words// argument. Return an empty string else. **$(not text)** If the text is empty, return "empty" else return an empty string. **$(notequal expression1,expression2)** Evaluates both expressions and return the value of the second expressions if they are different, return an empty string else. **$(notin word,words)** Return the //word// if it is not contained in the //words// argument. Return an empty string else. **$(or expression1,expression2,...)** Evaluates to the first non-empty expression. ==== System Call ==== This functions ensure portability of the action through OSes. All return the return value of the command if it fails or an empty string if it succeeds. **$(install mode,paths,target)** Install the files of the given //paths// to the given //target// according the words in the //mode// : * exec : the files are executables, * lib : tne files are libraries, * adm : the file must be only accessed by administrator, * readonly : the file are read-only, * hidden : the files are hidden (on Unix, add a dot as prefix of files), * conf : configuration files. **$(ln path1,path2)** Create a soft link at //path2// from the file at //path1//. **$(mkdir paths)** Create directories for the given //paths//. **$(mv paths,target)** Move file and directories of //paths// in the given //target//. **$(rm paths)** Remove files and directories matching the given //paths//. **$(rmdir paths)** Remove directories matching the given //paths//. ====== Command Options ======